很多人都分不清Major GC, Full GC的概念,事实上我查了下资料,也没有查到非常精确的Major GC和Full GC的概念定义。分不清这两个概念可能就会对这个问题疑惑:Full GC会引起Minor GC吗?

经过一系列的查找和对JVM表现的分析,基本可以给Full GC和Major GC下一个定义了,这篇说一说概念和理由。

这篇文章Major GCs – Separating Myth from Reality 基本讨论的也是这个问题,但是它没有给出实际的证明。

我们可以认为Major GC == Full GC,他们是一个概念,就是针对老年代/永久代进行GC。因为取名叫Full就会让人疑惑,到底会不会先Minor GC。事实上Full GC本身不会先进行Minor GC,我们可以配置,让Full GC之前先进行一次Minor GC,因为老年代很多对象都会引用到新生代的对象,先进行一次Minor GC可以提高老年代GC的速度。比如老年代使用CMS时,设置CMSScavengeBeforeRemark优化,让CMS remark之前先进行一次Minor GC。

弄清楚了Full GC本意单纯就是针对老年代了之后,我们再进一步深入理解Full GC的含义。因为CMS主要可以分为initial mark(stop the world), concurrent mark, remark(stop the world), concurrent sweep几个阶段,其中initial mark和remark会stop the world。

在这篇聊聊JVM(二)说说GC的一些常见概念 我们说了一次CMS至少会给Full GC的次数 + 2,因为Full GC的次数是按照老年代GC时stop the world的次数而定的

再来看Full GC的Time的定义,可以理解它也指的是老年代GC时stop the world的时间。我们看一个实例来证明一下。

这段日志是我从一个tomcat的JVM GC日志中抓取的,老年代使用了CMS收集器

2014-12-08T17:24:18.514+0800: 77443.326: [GC [1 <strong><span style="color:#FF0000;">CMS-initial-mark: 1382782K(1843200K)] 1978934K(4710400K), 0.0702700 secs] [Times: user=0.07 sys=0.00, real=0.07 secs]</span></strong>
2014-12-08T17:24:18.586+0800: 77443.398: [CMS-concurrent-mark-start]
2014-12-08T17:24:19.890+0800: 77444.702: [CMS-concurrent-mark: 1.206/1.303 secs] [Times: user=2.80 sys=0.07, real=1.30 secs]
2014-12-08T17:24:19.890+0800: 77444.702: [CMS-concurrent-preclean-start]
2014-12-08T17:24:19.906+0800: 77444.718: [CMS-concurrent-preclean: 0.015/0.015 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
2014-12-08T17:24:19.906+0800: 77444.718: [CMS-concurrent-abortable-preclean-start]
CMS: abort preclean due to time 2014-12-08T17:24:25.181+0800: 77449.993: [CMS-concurrent-abortable-preclean: 5.241/5.275 secs] [Times: user=6.03 sys=0.09, real=5.27 secs]
2014-12-08T17:24:25.187+0800: 77449.999: [GC[YG occupancy: 749244 K (2867200 K)]77450.000: [Rescan (parallel) , 0.0276780 secs]77450.028: [weak refs processing, 0.2029030 secs]
 [<span style="color:#FF0000;"><strong>1 CMS-remark: 1382782K(1843200K)] 2132027K(4710400K), 0.2340660 secs] [Times: user=0.43 sys=0.00, real=0.23 secs</strong></span>]
2014-12-08T17:24:25.424+0800: 77450.236: [CMS-concurrent-sweep-start]
2014-12-08T17:24:27.420+0800: 77452.232: [CMS-concurrent-sweep: 1.918/1.996 secs] [Times: user=2.61 sys=0.05, real=2.00 secs]
2014-12-08T17:24:27.421+0800: 77452.233: [CMS-concurrent-reset-start]
2014-12-08T17:24:27.430+0800: 77452.242: [CMS-concurrent-reset: 0.010/0.010 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
2014-12-09T12:45:05.545+0800: 147090.358: [GC [<span style="color:#FF0000;"><strong>1 CMS-initial-mark: 1384080K(1843200K)] 2013429K(4710400K), 0.0656230 secs] [Times: user=0.06 sys=0.00, real=0.07 secs</strong></span>]
2014-12-09T12:45:05.613+0800: 147090.425: [CMS-concurrent-mark-start]
2014-12-09T12:45:06.848+0800: 147091.660: [CMS-concurrent-mark: 1.196/1.235 secs] [Times: user=2.77 sys=0.03, real=1.23 secs]
2014-12-09T12:45:06.849+0800: 147091.661: [CMS-concurrent-preclean-start]
2014-12-09T12:45:06.862+0800: 147091.674: [CMS-concurrent-preclean: 0.013/0.013 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
2014-12-09T12:45:06.862+0800: 147091.674: [CMS-concurrent-abortable-preclean-start]
CMS: abort preclean due to time 2014-12-09T12:45:11.874+0800: 147096.686: [CMS-concurrent-abortable-preclean: 4.948/5.012 secs] [Times: user=6.04 sys=0.10, real=5.01 secs]
2014-12-09T12:45:11.882+0800: 147096.694: [GC[YG occupancy: 815312 K (2867200 K)]147096.695: [Rescan (parallel) , 0.0476710 secs]147096.743: [weak refs processing, 0.1565260 secs]
[1 <span style="color:#FF0000;"><strong>CMS-remark: 1384080K(1843200K)] 2199393K(4710400K), 0.2064660 secs] [Times: user=0.48 sys=0.00, real=0.20 secs</strong></span>]
2014-12-09T12:45:12.091+0800: 147096.903: [CMS-concurrent-sweep-start]
2014-12-09T12:45:14.078+0800: 147098.890: [CMS-concurrent-sweep: 1.934/1.986 secs] [Times: user=2.43 sys=0.04, real=1.99 secs]
2014-12-09T12:45:14.078+0800: 147098.890: [CMS-concurrent-reset-start]
2014-12-09T12:45:14.084+0800: 147098.896: [CMS-concurrent-reset: 0.006/0.006 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

我把CMS的initial mark和remark的日志都标记了。

我们可以看到总共发生了两次CMS,所以Full GC的次数应该是4

Full GC的时间 = 0.07 secs(第一次initial mark)+ 0.23 secs(第一次remark) + 0.07 secs(第二次initial mark) + 0.20 secs(第二次remark) = 0.57s

用jstat -gc 得到的时间Full GC的次数和时间也是吻合的。

所以jstat是Java官方提供的工具,所以我们可以说得出的结论是和官方的一致的。

下面是Visual GC的截图,看Old Gen的统计数据: 4 collections, 576.421ms

再来看一个更加直接的例子,从OpenJDK里面找线索:

这段代码来自openjdk/hotspot/src/share/vm/services/memoryService.cpp,从代码中可以看到JVM使用了一个_fullGC的布尔值来表示是否是Full GC

DefNew, ParNew, ASParNew都是新生代的收集器算法,当使用它们时,_fullGC = false

MarkSweepCompact(Serial Old收集器), ConcurrentMarkSweep(CMS), ASConcurrentMarkSweep时_fullGC = true。所以只有收集老年代的时候,才算Full GC

我们可以安全的说:

1. Full GC == Major GC指的是对老年代/永久代的stop the world的GC

2. Full GC的次数 = 老年代GC时 stop the world的次数

3. Full GC的时间 = 老年代GC时 stop the world的总时间

4. CMS 不等于Full GC,我们可以看到CMS分为多个阶段,只有stop the world的阶段被计算到了Full GC的次数和时间,而和业务线程并发的GC的次数和时间则不被认为是Full GC

我们可以看到正常的CMS的stop the world的时间很短,都是在几十到几百ms的级别,对Full GC的时间影响很小。但是有时候我们用jstat看到的Full GC的时间很长。比如下面这个例子,和上面的Tomcat是同一个应用,只是是我调优之前的数据。

我们看到调优之前的Full GC的评价时间 = 1188 / 223 = 5秒,也就是说单次Full GC的stop the world的时间达到了5s! 进一步分析日志,得到如下日志:

54090.152: [Full GC (System) 54090.153: [CMS: 1211220K->1428569K(4096000K), 5.4936890 secs] 3483935K->1428569K(7168000K),
[CMS Perm : 148045K->147921K(262144K)], 5.4963160 secs] [Times: user=5.50 sys=0.00, real=5.50 secs]
57696.218: [Full GC (System) 57696.219: [CMS: 1513461K->1213731K(4096000K), 4.7293810 secs] 3283076K->1213731K(7168000K),
[CMS Perm : 148019K->147881K(262144K)], 4.7317730 secs] [Times: user=4.73 sys=0.00, real=4.74 secs]
61301.483: [Full GC (System) 61301.484: [CMS: 1288630K->968887K(4096000K), 4.5720170 secs] 2466308K->968887K(7168000K),
[CMS Perm : 147996K->147835K(262144K)], 4.5743720 secs] [Times: user=4.57 sys=0.00, real=4.57 secs]
64906.588: [Full GC (System) 64906.590: [CMS: 1026456K->1568407K(4096000K), 5.0347600 secs] 3769961K->1568407K(7168000K),
[CMS Perm : 148004K->147903K(262144K)], 5.0373410 secs] [Times: user=5.02 sys=0.00, real=5.04 secs]
68512.160: [Full GC (System) 68512.161: [CMS: 1631217K->838700K(4096000K), 4.7239290 secs] 2552874K->838700K(7168000K),
[CMS Perm : 148017K->147829K(262144K)], 4.7261610 secs] [Times: user=4.72 sys=0.00, real=4.72 secs]
72117.421: [Full GC (System) 72117.423: [CMS: 905025K->1529502K(4096000K), 5.3562640 secs] 3556285K->1529502K(7168000K),
[CMS Perm : 148049K->147945K(262144K)], 5.3587790 secs] [Times: user=5.36 sys=0.00, real=5.36 secs]

我们看到是System.gc引起的Full GC,而老年代的GC时间到达了5秒多,它显示的是CMS,但是实际上不是CMS并发的收集器,而是CMS发生了concurrent mode fail之后退化成了Serial Old收集器,它是单线程的标记-压缩收集器,所以耗时非常的长。

最后再次强调一下结论:

1. Full GC == Major GC指的是对老年代/永久代的stop the world的GC

2. Full GC的次数 = 老年代GC时 stop the world的次数

3. Full GC的时间 = 老年代GC时 stop the world的总时间

4. CMS 不等于Full GC,我们可以看到CMS分为多个阶段,只有stop the world的阶段被计算到了Full GC的次数和时间,而和业务线程并发的GC的次数和时间则不被认为是Full GC

5. Full GC本身不会先进行Minor GC,我们可以配置,让Full GC之前先进行一次Minor GC,因为老年代很多对象都会引用到新生代的对象,先进行一次Minor GC可以提高老年代GC的速度。比如老年代使用CMS时,设置CMSScavengeBeforeRemark优化,让CMS remark之前先进行一次Minor GC

深入理解Major GC, Full GC, CMS的更多相关文章

  1. 【转】深入理解Major GC, Full GC, CMS

    声明:本文转自http://blog.csdn.net/iter_zc/article/details/41825395,转载务必声明. 很多人都分不清Major GC, Full GC的概念,事实上 ...

  2. 一次CMS GC问题排查过程(理解原理+读懂GC日志)

    这个是之前处理过的一个线上问题,处理过程断断续续,经历了两周多的时间,中间各种尝试,总结如下.这篇文章分三部分: 1.问题的场景和处理过程:2.GC的一些理论东西:3.看懂GC的日志 先说一下问题吧 ...

  3. [转]一次CMS GC问题排查过程(理解原理+读懂GC日志)

    这个是之前处理过的一个线上问题,处理过程断断续续,经历了两周多的时间,中间各种尝试,总结如下.这篇文章分三部分: 1.问题的场景和处理过程:2.GC的一些理论东西:3.看懂GC的日志 先说一下问题吧 ...

  4. Minor GC&Full GC&Major GC区别及触发条件

    Minor GC:从年轻代回收内存 触发条件 1.Eden区域满 ​ 2.新创建的对象大小 > Eden所剩空间 Full GC:清理整个堆空间,包括年轻代和老年代 触发条件 ​ 1.每次晋升到 ...

  5. 常见GC算法,CMS以及G1的垃圾回收过程,CMS的各个阶段哪两个是Stop the world的,CMS会不会产生碎片,G1的优势。

    常见GC算法 在C/C++中是由程序员自己去申请.管理和释放内存的,因此没有GC的概念.而在Java中,专门有一个用于垃圾回收的后台线程来进行监控.扫描,自动将一些无用的内存进行释放.下面介绍几种常见 ...

  6. minor gc和Major GC,Full GC的触发条件

    Minor GC Minor GC指新生代GC,即发生在新生代(包括Eden区和Survivor区)的垃圾回收操作,当新生代无法为新生对象分配内存空间的时候,会触发Minor GC.因为新生代中大多数 ...

  7. GC之一--GC 的算法分析、垃圾收集器、内存分配策略介绍

    一.概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计数器.虚拟机栈.本 ...

  8. Java GC机制中Minor GC/Full GC

    Minor GC Young GC Full GC Major GC https://blog.csdn.net/chenleixing/article/details/46706039 内存划分为 ...

  9. GC之八--GC 触发Full GC执行的情况及应对策略

    目录: GC之一--GC 的算法分析.垃圾收集器.内存分配策略介绍 GC之二--GC日志分析(jdk1.8)整理中 GC之三--GC 触发Full GC执行的情况及应对策略 gc之四--Minor G ...

随机推荐

  1. 如何配置Tomcat以使用Apache httpd?

    How to Connect Tomcat 6 to Apache HTTP Server 2 Tomcat can be run as a standalone server. Tomcat can ...

  2. div 隐藏显示各种例子

    <html><head><title>jquery show()</title><script type="text/javascrip ...

  3. 第七次实验:CC2530平台上多跳通信的TinyOS编程

    module  P2MM { uses interface Boot; uses interface Timer<TMilli> as Timer0; uses interface Spl ...

  4. Eclipse导入已有的项目后项目报错的解决办法

    第一种:jsp报错 选择windows-->preference-->列表找到Validation-->点击Disable All ->> Apply ->> ...

  5. 简单git使用命令

    // 查看分支:git branch // 创建分支:git branch <name> // 切换分支:git checkout <name> // 创建+切换分支:git ...

  6. collection和association的区别于关系

    比如同时有User.java和Card.java两个类 User.java如下: public class User{ private Card card_one; private List<C ...

  7. 新手入门HTML5有什么推荐的书籍?

    很多想迈入HTML5开发行列的人,都会问一个问题:要成为一个更好的开发人员,我应该读哪些书?有哪些HTML5开发的书籍推荐吗? 有人说开卷有益,读万卷书行万里路;有人说,书不在多,精益求精;有人说,书 ...

  8. win2008安装并配置zabbix3.4 agent

    agent 下载地址: https://www.zabbix.com/download_agents 下载解压后有2个文件夹,一个是bin,存放32位和64位执行程序,一个是conf目录存放着配置文件 ...

  9. Proxifier代理工具简介和下载

    Proxifier 是一款功能非常强大的socks5客户端,可以让不支持通过代理服务器工作的网络程序能通过HTTPS或SOCKS代理或代理链.支持64位系统,支持Xp,Vista,Win7,支持soc ...

  10. IO队列深度max_queue_depth对系统性能的影响

    前段时间,发生了一个问题引起了我对IO队列深度的研究. 存储服务器中linux kernel的mpt2sas驱动模块,将max_queue_depth设置为1024时,引起系统加载驱动时卡死,而调整为 ...