判断对象已死
引用计数算法
给对象添加一个引用计数器,每当一个地方引用它时计数器加1;引用失效计数器减1,计数器为0说明不再引用
优点:实现简单,判定效率高
缺点:无法解决对象相互循环引用的问题
可达性分析算法
当一个对象到GC Roots没有引用链相连(GC Roots到这个对象不可达)时,证明此对象不可用
GC Roots种类
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中的静态属性引用的对象
方法区中的常量引用的对象
本地方法栈中JNI(Native方法)引用的对象
引用
强引用
Object object=new Object();
软引用
SoftReference<Object> object=new SoftReference<Object>(new Object());
弱引用
WeakReference<Object> object=new WeakReference<Object>(new Object());
虚引用
ReferenceQueue<String> referenceQueue = new ReferenceQueue<String>();PhantomReference<String> object=new PhantomReference<String>(new String(),referenceQueue);
finalize()
对象是否覆盖finalize方法
是:jvm执行finalize()方法
否:JVM回收对象
JVM是否执行过该对象的finalize方法
是:JVM回收对象(每个对象finalize方法只执行一次)
否:JVM执行finalize()方法
垃圾收集算法
标记清除算法
缺点:1、标记和清除效率都不高;2、标记、清除之后会产生大量不连续的内存碎片
复制算法(新生代)
Eden:Survivor:Survivor=8:1:1
分配担保:如果Survivor没有足够空间来存放上次新生代GC存活下来的对象,它们将通过分配担保机制进入老年代
缺点:对象存活率高时,复制效率较低
标记整理算法(老年代)
先执行标记-清除,让所有的存活对象都向一端移动,最后清理掉边界以外的内存
垃圾收集器
新生代
Serial
特点:单线程收集;标记-复制算法
场景:Client模式下默认新生代收集器;单核机器
ParNew
特点:多线程并行收集;标记-复制算法;其他特点与Serial相似
缺点:在单CPU场景效果不突出
场景:用户交互;配合CMS垃圾收集器
Parallel Scavenge
特点:目标在于达到可控吞吐量(吞吐量=用户代码运行时间/(用户代码运行时间+垃圾收集时间));标记-整理
场景:高效利用CPU,后台运算且不需要太多交互
老年代
CMS
特点:最短回收停顿时间;标记-清除
步骤
初始标记:标记GC Roots直接关联的对象,速度快
并发标记:GC Roots Tracing过程,好市场,与用户进程并发工作
重新标记:修正并发标记期间用户进程继续运行而产生变化的标记,耗时比初始标记长,但远小于并发标记
并发清除:清除标记的对象
缺点
对CPU资源敏感
无法回收浮动垃圾
标记-清除算法,会产生内存碎片,可以通过参数开启碎片的合并整理
Serial Old
特点:Serial的老年代版本,单线程;标记-整理
场景:1.5之前与Parallel Scavenge配合使用;作为CMS的后备预案
Parallel Old
特点:标记-整理;多线程
场景:为了替代Serial Old与Parallel Scavenge配合使用
G1
特点:将整个Java堆划分为多个大小相等的独立区域Region,跟踪各个Region里面的垃圾堆积的价值大小,在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region
步骤
初始标记:标记GC Roots直接关联的对象
并发标记:对堆中对象进行可达性分析,找出存活对象,耗时长,与用户进程并发工作
最终标记:修正并发标记期间用户进程继续运行而产生变化的标记
筛选回收:对各个Region的回收价值排序,然后根据期望的GC停顿时间制定回收计划
垃圾回收过程
分支主题
大多情况下对象在Eden分配,当Eden没有足够空间时将发起一次Minor GC
当Eden执行Minor GC后还不足以为对象分配空间,大对象直接进入老年代,可以用参数设置大对象直接进入老年代,避免频繁Minor GC
如果对象在Eden出生,发生MinorGC后仍然存活,且能被Survivor容纳,年龄加1,达到一定年龄进入老年代,默认15
占Survivor空间一半以上且年龄相等的对象,大于等于该年龄以上的对象直接进入老年代
发生Minor GC之前会先检查老年代最大可用连续空间是否大于新生代所有对象总空间,如果大于说明MinorGC安全;否则会判断是否允许担保失败,如果允许担保失败,判断老年代最大连续空间是否大于历次晋升到老年代对象的平均大小,如果大于则尝试MinorGC,否则执行FullGC