对象是否存活的算法:
- 引用计数法:无法解决循环引用的问题。
- 可达性分析法:GCRoots 可达。
GCRoots对象:
虚拟机栈中的引用对象
方法去静态变量
方法区中的常量
本地方法(JNI)栈中的引用对象
垃圾回收算法:
- 标记清理:根据可达性分析,标记不再引用的对象(标记过程会stop the world),然后再进行清除操作。空间碎片的问题。
- 复制算法:一般用于年轻代,数据较小的区域。存活率较高时,需要进行较多的复制操作;还有空间浪费等问题。
- 标记整理:标记,然后整理对齐,处理空间碎片的问题,存活对象都移动向一端,然后直接清理掉端边界意外的内存。
- 分代手机算法:年轻代使用复制算法;老年代使用标记清理或标记整理
堆的分代
- 年轻代:年轻代又分为一个 Eden区和两个Survivor区
- 老年代
垃圾回收的整个过程:
- 如果设置了 -XX:MaxTenuringThreshold, 会先判断对象是否大于该值,大于就直接放到老年代。
- 看 Eden 区是否能放下,能放下直接放Eden区;
- Eden 区放不下会触发一 YoungGC(MinorGC),存活的对象会被放到 survivor 的 to 区,对象头中的 age 加 1,MinorGC还同时会对 from 区的对象进行标记,存活对象 age 等于 15 的会被移动到老年代,存活且年龄小于15的会被放到 to 区,age加 1;此时 from 区所有对象都被转移,清空 from 区,然后 from 和 to 区域互换。
- 对象放到老年代,若空间不足会触发 FullGC
- 分配担保,在进行 MinorGC 前会先比较当前年轻代对象总大小是否小于当前老年代最大可用连续空间大小,若小于会认为此次 MinorGC 为安全的;若大于,会认为 MinorGC 有一定风险,此时会比较老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小,若大于,会尝试进行一次 MinorGC,若小于改为进行一次 FullGC。