这里整理一下自己对jvm内存垃圾回收的一点认识,不一定详细也不一定就正确,只是自己的经验积累只谈而已。
jvm标记查找方式:ROOT Search即可达根查找法
jvm垃圾回收算法:标记,复制,标记压缩 (新生代采用复制算法,老年代采用标记或标记压缩都比较耗时,但是标记压缩避免了内存碎片)
jvm垃圾收集器各厂商不同而不同,主要分为单例,并行,并发(CMS,jdk1.8默认),G1(1.9默认),ZGS等,如下逐一介绍:
单例:绝对的STOP WORLD,一个单线程回收,垃圾查找及回收过程都需要业务线程stop,大内存情况下非常耗时
并行:绝对的STOP WORLD,多个线程回收,垃圾查找及回收过程都需要业务线程stop,依然避免不了大内存垃圾的耗时
CMS并发:
多个垃圾回收线程和业务工作线程可以同时工作,CMS理论上为了解决stop world问题,但是它采用的三色标记算法存在漏标的现象
(引用发生变化正好此垃圾回收线程被cpu挂起又开始执行这段时间里),CMS为了解决漏标的问题采用了remark操作,就是最后再进行一次全面的从新查找,这样在内存巨大的时候依然会发生严重的stop world现在。
G1:
G1为了解决CMS的问题,采用了在引用发生变化的时候将那个消失的指针向量记录到垃圾回收线程的堆栈里(内存屏障里的写屏障实现),当垃圾回收线程重新获取cpu执行时间时候会先去这个堆栈里将里面的记录的那个没有引用的对象找出来,然后以它为root进行反查找(不是标记)看有没有对象指向它,若有说明它不是垃圾,若没有就说明它确实是垃圾。
G1物理上采用了region分区的方式,虽然它逻辑上依然采用了分段内存,但是物理上是没有分段的,这个是很大的区别,它把整个jvm内存分为多个小的region物理逻辑,在并发垃圾回收里就可以很快的对各个小的region进行标记回收等动作,而且对回收的region动态作用于新生代或老年代对象存储。
总之:1.G1即避免了CMS里remark操作的Stop World现象(垃圾回收线程里写入因变化而消失的指针)
2.物理上的region分区,可以提高并发垃圾回收情况下的效率。
补充:
1.三色标记算法:
白色-》没有被标记(可能是垃圾)
灰色-》部分引用的子对象被标记了,部分还没来的急标记,它自己也不是垃圾,垃圾回收线程再回来标记的时候需要从此位置继续标记
黑色-》所有引用的子对象都已经被标记过了,就认为此对象已经标记了不是垃圾,垃圾回收线程再回来标记的时候不需要从此位置标记
2.漏标:
