1、存活判定算法
引用计算算法,给对象添加一个引用计数器,每一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。(主流JVM里没有选用,主要原因是它很难解决对象间相互引用的问题)
可达性分析算法,主要思想就是通过一系列称为“CG Roots”的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到CG Roots没有任何引用链相连接时则证明该对象是不可用的。
要真正回收一个对象,至少要经历两次标记过程。
2、垃圾收集算法
标记-清除算法,首先标记出所有需要被回收的对象,在标记完成后统一回收所有被标记的对象。但标记和清除的两个过程效率不高。标记清除后会产生大量不连续的内存碎片,导致以后需要分配占用空间较大的对象时无法找到足够的连续内存而不得不触发另一次垃圾收集动作。
复制算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块,当这一块内存用完了,就将还存活的对象复制到另一块上面,然后再把已使用过的内存空间一次清理掉。
现代商业虚拟机都是采用复制算法来回收新生代的。但并不是1:1分配内存空间,而是将内存分为一块Eden和两块Survivor(空间大小为8:1),回收时将Eden和其中一块Survivor中还存活着的对象复制到另一块Survivor上(如果另一块Survivor空间没有足够空间存放,这些对象将直接通过分配担保机制进入老年代)。标记-整理算法,标记的过程与标记清除算法一样,但后续则是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
3、垃圾收集器
Serial收集器,新生代,单线程收集器,复制算法,它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束。
ParNew收集器,新生代,复制算法,其实就是Serial收集器的多线程版本,除了Serial收集器外,只有它能与CMS配合工作。
Parallel Scavenge收集器,新生代收集器,也是一个使用复制算法的并行多线程收集器。Parallel Scavenge收集器的目标是达到一个可控制的吞吐量(吞吐量 = 运行用户代码时间/(运行用户代码时间 + 垃圾收集时间))
Serial Old收集器,Serial收集器的老年代版本,使用“标记-整理”算法。
Parallel Old收集器,Parallel Scavenge收集器的老年代版本,使用“标记-整理”算法。
CMS收集器,老年代,是基于“标记-清除”算法的一种以获取最短回收停顿时间 为目标的收集器。整个过程分为初始标记、并发标记、重新标记、并发清除。但它有以下三个明显缺点:
1)对CPU资源非常敏感
2)无法收集浮动垃圾
3)由于是基于“标记-清除”算法,收集结束后会有大量的空间碎片G1收集器,大概分为:初始标记、并发标记、最终标记、筛选回收四个步骤,且具有以下特点:
1)并行与并发
2)分代收集,使用G1时,Java堆的分布与使用其他收集器时有很大差别,它将整个堆分为多个大小相等的独立区域(Region),虽然还保留新生代和老年代的概念,但它们不再是物理隔离的了,都是一部分Region的集合。
3)空间整合,从整体看是基于“标记-整理”算法,从两个Region之间看是基于复制算法。
4)可预测的停顿,G1跟踪各个Region里面的垃圾堆积的价值大小,在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region