一、理解JVM日志
从深入理解JVM书上的例子开始,各个收集器的日志格式不同,但是都维持一定的共性:
33.125:[GC[DefNew:3324K->152K(3712K),0.0025925secs]3324K->152K(11904K),0.0031680 secs]
100.667:[FullGC[Tenured:0K->210K(10240K),0.0149142secs]4603K->210K(19456K),[Perm:2999K->2999K(21248K)],0.0150007 secs][Times:user=0.01 sys=0.00,real=0.02 secs]
①:第一个数值(33.125、100.667)代表GC发生的时间,从虚拟机启动起来后经历的秒数
②:第二个GC、FullGC代表这次垃圾收集的停顿类型。如果FullGC代表是stop-the-world【不是用于区分GC发生在新生代或老年代】
③DefNew(新生代)、Tenured(老年代),Perm(永久代)表示GC发生的区域,区域名根据垃圾收集器的不同而不同,如Serial收集器新生代命名为DefNew(Default New Generation)。ParNew收集器新生代命名ParNew(Parallel New Generation)。Parallel Scavenge收集器 新生代命名PSYoungGen。 老年代和永久代同理,名称也由收集器决定
④第四个3324K->152K(3712K)代表GC前用量->GC后用量(该内存区域重量)
⑤方括号外3324K->152K(11904K),0.0031680 secs]表示GC前JAVA堆已使用容量->GC后JAVA堆使用量(java堆总量)
⑥0.0031680 secs代表GC占用的时间
二、新生代复制算法
目前大部分垃圾收集器对于新生代都采取Copying算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。
三:其他回收规则
①长期存活对象进入老年代规则:如果对象在Eden区出生并经过第一次MinorGC后仍然存活,并且被Survivor容纳的话,就会被移动到Survivor空间,并将对象年龄设为1,对象每在Survivor熬过一次Minor GC,年龄就增加一岁,到达一定年龄就被移动到老年代
②动态年龄判定:如果Survivor区相同年龄对象大小大于Survivor区一半,就可直接移动到老年代,无需到达指定年龄
③空间分配担保:在MinorGC前,虚拟机会检查老年代最大连续可用空间是否大于新生代所有对象空间,如果成立则MinorGC确保安全。如果不成立则虚拟机会检查是否允许担保失败。如果允许,那么会检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小,如果大于则尝试进行MinorGC,如果小于或者不允许担保失败则进行FullGC