如何判定对象是否该回收
1、引用计数法
计算对象被引用的次数,被引用一次就+1,在回收对象时,如果对象引用数为0,则回收。
缺点:无法判断互相引用的对象。
2、可达性分析算法
从GCRoot对象开始,根据引用关系标记,这样,被标记的都是存活的对象。
GCRoot对象:
-
虚拟机栈里的对象
-
方法区栈里的对象
-
方法区里的常量
-
方法区里的静态对象
垃圾回收算法
-
标记-清除:将存活的对象标记,清理掉未标记的对象
优点:处理逻辑简单
缺点:回收完成后,内存不连续,内存碎片较多
-
标记-复制:将内存分为两块,每次只用一块,当一块用满后,将存活的对象迁移到另一内存块,再清空当前内存块
优点:没有内存碎片
缺点:只能使用一半的内存
-
标记-整理:从内存的一端开始使用,清理的时候,将存活的对象移到另一端,然后清理掉其他的内存
优点:没有内存碎片
缺点:性能较 标记-复制 算法差
常见的垃圾回收器
-
Parallel Scavenge:
注重吞吐量的新生代回收器,采用多线程+标记复杂算法
Java8默认
-
Parallel Old
搭配Parallel Scavenge的老年代回收期,采用多线程标记整理算法
-
CMS
目标是最小的停顿时间,并发标记的老年代回收期,整个流程分为首次标记、并发标记、再次标记、并发清理四个阶段,在首次标记时,标记GCRoot时才暂停线程
-
G1
Java9开始的默认回收算法,将内存分为很多个小块,每块都可以作为年轻代和老年代,不仅如此,还有一个大对象块