1.1 判断对象是否存活
1.1.1 引用计数算法:给每个对象添加一个引用计数器,当一个地方引用此对象时,该计数器值+1;当引用失效时,该计数器值-1;当此对象没有被引用时,该计数器的值为0。虽然此算法实现简单,效率高,但是很难解决两个对象之间相互循环引用的问题。
1.1.2 可达性分析算法:通过一系列称为"GC Roots"的对象作为起始点,从这些节点开始向下查找,查找走过的路径称为引用链,当一个对象到"GC Roots"之间没有任何引用链相连时,说明此对象不可用。可以作为GC Roots 的对象有虚拟机栈中引用的对象、方法区中静态属性引用的对象、方法区常量引用的对象和Native方法引用的对象。
1.2 垃圾收集算法
1.2.1 标记-清除算法:首先标记出需要回收的对象,然后统一回收所有标记的对象。此收集算法的不足之处:回收效率不高,清除时会产生大量碎片,不容易分配大对象。
1.2.2 复制算法:将可用容量划分为相等的两块,每次只使用其中的一块,当这块内存用完了,将存活的对象复制到另一块,然后把之前的内存空间清理掉。虽然效率高,但是浪费资源。商用虚拟机将新生代按8:1:1分为Eden空间:From Survior空间:To Survivor空间,每次只使用90%的空间,将存活的对象复制到To Survivor空间,清理掉之前的90%空间,遇到多余的存活对象,直接放到老年代。
1.2.3 标记-整理算法:标记和之前一样,整理时先让所有存活对象向一端移动,清理掉端边界以外的内存。
1.2.4 分代收集算法:首先将java堆分为新生代和老年代,新生代每次垃圾收集时有大量对象死亡,因此采用复制算法进行垃圾收集,老年代中对象存活率高,则采用“标记-清理”或“标记-整理”算法收集。