GC主要可以分为2个步骤:
(1)垃圾确认
(2)垃圾回收算法
1.垃圾对象的确认:
(1)引用计数法:给对象添加一个计数器,每次对象进行引用,计数器计数加1,引用失效时,计数器计数减1,当计数器为0时,则认为该对象不再被使用,确认为垃圾对象。
在java中并不使用该种方式进行确认,java中存在对象的互相循环引用,计数器无法为0,会导致无法确认为垃圾对象。
(2)可达性分析:通过一系列称为GC Roots的对象作为起点,从对应的节点一步步向下搜索,搜索的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链时,该对象则是不可用的,确认为垃圾对象
2.垃圾回收算法:
(1) 标记-清除算法:
1)标记出所有活动的对象
2)清除所有未活动的对象
目前出现的还有一种解释: 1)标记出所有需要回收的对象 2)清除标记的对象主要的思想:对不在活动的对象进行清除,但是实现有所不同。
优点: 存活对象较多的情况下比较高效
适用于年老代(即旧生代)
缺点: 容易产生内存碎片,再来一个比较大的对象时(典型情况:该对象的大小大于空闲表中 的每一块儿大小但是小于其中两块儿的和),会提前触发垃圾回收
扫描了整个空间两次(第一次:标记存活对象;第二次:清除没有标记的对象)
(2) 复制算法:将内存区域划为2块区域,每次只使用其中的一块区域。当使用区域的内存全部使用,此时将存活的对象复制到另外一块区域,对当前区域的对象进行完全回收。
优点:存活对象较少的情况下比较高效
扫描了整个空间一次(标记存活对象并复制移动)
适用于年轻代(即新生代):基本上98%的对象是"朝生夕死"的,存活下来的会很少
缺点:需要一块儿空的内存空间
需要复制移动对象
(3) 标记-整理算法:与标记-清除类似,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的区域
优点:这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高
(4) 分代算法:分代收集是目前jvm普遍采用的算法,即新生代采用复制算法,因为有大量新生对象死去,只有少量存活;老年代采用标记-整理,因为老年代中对象存活率高,没有额外的空间对它进行担保