跟踪收集器采用的是集中式的管理方式,全局记录对象直接的引用状态,执行时从一些GC Roots的对象做为起点,从这些节点向下开始进行搜索所有引用链,当一个对象到GC Roots 没有任何引用链时,则证明此对象是不可用的。
可以作为 GC Roots 的对象包括:
- 虚拟机栈(栈帧中的本地变量表)中的引用对象。
- 方法区中的静态属性引用的对象。
- 方法区中的常量引用的对象。
- 本地方法中 JNI 的引用对象。
主要有标记清除、复制、标记-整理三种实现算法。
标记 - 清除算法
标记算法是最基础的收集算法,其他手机算法都是基于这种思想。标记-清除算法分为“标记” 和“清除”两个阶段,首先是标记出需要回收的对象,标记完成后统一清除对象。
缺点:- 标记和清除的过程效率不高。
- 标记清除之后会产生大量不连续的内存碎片。
复制算法
复制算法是将可用内存容量划分为大小相等的两块,每次只使用其中一块,当第一块使用完之后,将还存活在第一块上的对象复制到第二块上,把第一块使用的内存空间一次清除,等待第二块内存空间使用完后,可循环使用。每次只对其中一块内存进行内存回收,不会产生碎片,只要移动堆指针,按顺序分配内存即可,实现简单,运行高效。
缺点:
- 内存缩小为原来的一半
标记 - 整理算法
标记 - 整理算法与“标记 - 清楚”算法一致,后续操作不只是直接处理对象,而是在清理无用对象完成后让所有存活的对象都向一端移动,并更新引用其对象的指针,不会产生内存碎片。
缺点:
- 在标记 - 清除的基础上还需进行对象的移动,成本相对比较高。