垃圾回收器ParNew+CMS
2021-04-19 22:18:41 0 举报
登录查看完整内容
垃圾回收
作者其他创作
大纲/内容
初始标记
第一阶段:CMS进行垃圾回收,会先执行初始标记阶段,这个阶段会让系统的工作线程全部停止,进入“Stop the World”状态。在初始阶段仅仅会通过“replicaManager”这个类的静态变量代表的GC Roots,去标记出来他直接引用的ReplicaManager对象,这就是初始标记的过程。他不会去管ReplicaFetcher这种对象,因为ReplicaFetcher对象是被ReplicaManager类的“replicaFetcher”实例变量引用的,方法的局部变量和类的静态变量是GC Roots。但是类的实例变量不是GC Roots第二阶段:是并发标记,这个阶段会让系统线程可以随意创建各种新对象,继续运行.在运行期间可能会创建新的存活对象,也可能会让部分存活对象失去引用,变成垃圾对象。在这个过程中,垃圾回收线程,会尽可能的对已有的对象进行GC Roots追踪。所谓进行GC Roots追踪,意思就是对类似“ReplicaFetcher”之类的全部老年代里的对象,他会去看他被谁引用了。比如这里是被“ReplicaManager”对象的实例变量引用了,接着会看“ReplicaManager”对象被谁引用了?会发现被“Kafka”类的静态变量引用了,那么此时可以认定“ReplicaFetcher”对象是被GC Roots间接引用的,所以此时就不需要回收他。第二个阶段,就是对老年代所有对象进行GC Roots追踪,其实是最耗时的。他需要追踪所有对象是否从根源上被GC Roots引用了,但是这个最耗时的阶段,是跟系统程序并发运行的,所以其实这个阶段不会对系统运行造成影响的。第三阶段:重新标记阶段。因为第二阶段里,你一边标记存活对象和垃圾对象,一边系统在不停运行创建新对象,让老对象变成垃圾,所以第二阶段结束之后,绝对会有很多存活对象和垃圾对象,是之前第二阶段没标记出来的,所以此时进入第三阶段,要继续让系统程序停下来,再次进入“Stop the World”阶段。这个重新标记的阶段,是速度很快的,他其实就是对在第二阶段中被系统程序运行变动过的少数对象进行标记,所以运行速度很快。第四阶段:并发清理。这个阶段其实是很耗时的,因为需要进行对象的清理,但是他也是跟系统程序并发运行的,所以其实也不影响系统程序的执行。
分配对象
新生代内存
垃圾回收线程
垃圾回收算法
阶段4-同时工作
Kafka静态变量:replicaManager
Survivor1区
系统程序
垃圾回收
阶段1-停止工作
方法区
Eden区800MB内存
ParNew:使用“-XX:+UseParNewGC”选项,只要加入这个选项,JVM启动后对新生代进行垃圾回收的,就是ParNew垃圾回收器了,默认设置的垃圾回收线程的数量就是跟CPU的核数是一样的。比如我们线上机器假设用的是4核CPU,或者8核CPU,或者16核CPU,那么此时ParNew的垃圾回收线程数就会分别是4个线程、8个线程、16个线程。
ReplicaFetcher(标记存活)
CMS垃圾回收器
并发标记
阶段2-同时工作
垃圾回收器ParNew
阶段3-禁止工作
老年代
并发清理
Survivor2区
ReplicaManager实例变量:replicaFetcher(标记存活)
存活对象(未标记)
垃圾对象
“-XX:CMSInitiatingOccupancyFaction”参数可以用来设置老年代占用多少比例的时候触发CMS垃圾回收,JDK 1.6里面默认的值是92%。也就是说,老年代占用了92%空间了,就自动进行CMS垃圾回收,预留8%的空间给并发回收期间,系统程序把一些新对象放入老年代中。那么如果CMS垃圾回收期间,系统程序要放入老年代的对象大于了可用内存空间,此时会如何?这个时候,会发生Concurrent Mode Failure,就是说并发垃圾回收失败了,我一边回收,你一边把对象放入老年代,内存都不够了。此时就会自动用“Serial Old”垃圾回收器替代CMS,就是直接强行把系统程序“Stop the World”,重新进行长时间的GC Roots追踪,标记出来全部垃圾对象,不允许新的对象产生。然后一次性把垃圾对象都回收掉,完事儿了再恢复系统线程。所以在生产实践中,这个自动触发CMS垃圾回收的比例需要合理优化一下,避免“Concurrent Mode Failure”问题。老年代的CMS采用“标记-清理”算法,每次都是标记出来垃圾对象,然后一次性回收掉,这样会导致大量的内存碎片产生。如果内存碎片太多,会导致后续对象进入老年代找不到可用的连续内存空间了,然后触发Full GC。所以CMS不是完全就仅仅用“标记-清理”算法的,因为太多的内存碎片实际上会导致更加频繁的Full GC。CMS有一个参数是“-XX:+UseCMSCompactAtFullCollection”,默认就打开了。意思是在Full GC之后要再次进行“Stop the World”,停止工作线程,然后进行碎片整理,就是把存活对象挪到一起,空出来大片连续内存空间,避免内存碎片。还有一个参数是“-XX:CMSFullGCsBeforeCompaction”,这个意思是执行多少次Full GC之后再执行一次内存碎片整理的工作,默认是0,意思就是每次Full GC之后都会进行一次内存整理。
0 条评论
回复 删除
下一页