对象存活判断和垃圾回收机制
判断对象是否存活
引用计数算法
算法思路
- 给对象中添加一个计数器, 如果有一个地方引用, 计数器 +1, 引用失效 -1
- 当计数器为0 时说明对象没有地方子引用, 既可以判定这个对象已经消亡
缺点
不能解决对象间相互循环引用的问题 对象A = 对象B 对象B = 对象A
可达性分析算法
通过一系列的 GC Roots 的对象作为起始点, 根据 根搜索算法(GC Roots Tracing)判断对象是否存活
算法思路
- 从GC Roots节点开始向下搜索, 搜索所走的路径称为引用链,当一个对象到GC Roots没有任何引用链相连接时, 则证明此对象是不可用的
可以作为GC Roots 的对象
- 虚拟机栈中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中引用的对象
垃圾回收机制算法
标记-清除算法
首先标记出来需要回收的对象, 在标记完之后统一进行回收
缺点
- 效率不高,标记和清除都不是一个效率高的操作
- 空间问题, 大量的不连续的空间内存碎片, 会导致之后分配大对象的内存时, 无法找到连续的可分配空间,提前触发一次GC
复制算法
复制算法主要应用在新生代中,以新生代为例:
- 将内存分为多块,Eden区和两份大小相同的survive区,先使用 Eden 区
- 第一次发生Minor Gc的时候,将Eden存活的对象放入其中一块survive区中,这时候该survive区叫做名义上的 From-survive区,另一块叫做 To-survive区
- 第二次发生Minor Gc的时候,将Eden区和From-survive区存活的对象复制到To-survive区,然后To变为From,From 变为To
优点
减少空间碎片化
缺点
存活率高的时候需要操作复制对象的就会很多, 效率很低
标记-整理算法
让所有的存活对象向一边移动, 然后清理掉边界外的内存
分代收集算法
- 新生代使用复制算法较多
- 老年代使用标记-整理算法较多