一、判断对象是否是垃圾
1、引用计数法
GC线程不定时回收时,如果对象被引用的话,年龄会加1,被回收掉一个对象就会减去1,当年龄为0岁,就会被垃圾回收机制认为是不可达对象,会被清理。
循环依赖问题: 有两个对象A和B,当A = B;B = A ; A = null; B = null; 此时这两个对象就不知道到底为不为0,导致对象无法被回收。该方法已被淘汰。
2、可达性分析(根搜索法(GC Roots))
由GC Root出发,开始寻找,看看某个对象是否可达。
可以作为GCRoots的对象包括,类加载器、Thread、本地变量表、static成员、常用引用、本地方法栈中的变量等。
二、垃圾回收算法
1、标记清除
垃圾回收机制遍历堆内存中标识为不可达对象,进行清理。
缺点:
1)内存碎片化(明明有内存空间,但是由于不连续,申请稍微大一些的对象无法做到)。
2)回收时,应用要挂起。
3)效率不高,尤其是在扫描的对象比较多的时候。
应用场景:老年代
图解:蓝色为存活对象,灰色为待回收对象,白色为未使用的空间
标记:
清除:
2、 复制
在堆里的S0和S1区进行,当S0区有对象不可达时,则会将其他可达对象拷贝到S1区,然后清除整个S0区,并且下次从EDEN区过来的对象也会相应的存放到S1区,当S1区有不可达对象,同样将S1区其他可达对象拷贝到S0区,再清除整个S1区,EDEN区过来的对象就又会存放在S0区(S0和S1必须有一个为空的),就是来回倒腾
缺点:浪费一定的空间
优点:解决碎片化、快速
应用场景:新生代
图解
蓝色为存活对象,灰色为待回收对象,白色为未使用的空间,绿色为保留空间
标记:
复制:
3、标记整理
和标记清除算法很像,就是在标记清除算法的基础上,将可达和不可达对象进行排序,方便一次性删除不可达对象。
应用场景:老年代
图解
标记:
整理:
三、分代收集算法
Young区:复制算法
Old区:标记清除或标记整理
四、垃圾收集器分类
1、串行收集器
Serial、Serial Old
特点:只能有一个垃圾回收线程执行,用户线程暂停。
应用场景:适用于内存比较小的嵌入式设备。
2、并行收集器(吞吐量优先)
Parallel Scanvenge、Parallel Old
特点:多条垃圾收集线程并行工作,但此时用户线程仍然属于等待状态。
应用场景:适用于科学计算、后台处理等交互场景
3、并发收集器(停顿时间优先)
CMS、G1
特点:用户线程和垃圾收集线程同时执行(但并不一定是并行的,可能是交替执行的),垃圾收集线程在执行的时候不会停顿用户线程的运行。
应用场景:适用于相对时间有要求的场景,如Web。
垃圾收集器的使用情况:
五、吞吐量和停顿时间
停顿时间:
垃圾收集器进行垃圾回收终端应用执行响应的时间。
停顿时间越短就越适合需要和用户交互的程序,良好的响应速度能提升用户的体验。
吞吐量:
运行用户代码时间/(运行用户代码时间+垃圾收集时间)。
吞吐量则可以高效地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。
小结:这两个指标也是评价垃圾回收器的好坏的标准,其实调优也就是观察这两个变量。