垃圾收集算法
垃圾收集算法涉及的程序细节很复杂,这里挑选一些基本的算法思想认识一下垃圾收集的手段与思想。
什么叫分代收集?
我们知道,大多数我们new出来的对象都是朝生夕灭的,生命周期极其短暂,而熬过越多次垃圾收集的对象就越难消亡。当然也得思考一下为什么它能熬过多次垃圾收集?如果将这两类对象混乱的放在一个堆里,每一次都需要区分回收对象的类型是朝生夕灭的那种还是老油条的那种?如果把朝生夕灭的对象放在一起,那么可以分区域进行高效的垃圾回收了!
分代理论即将堆中的对象分为"新生代"和"老年代"两类对象区域,每一次回收也根据回收范围分为了minorGC,majorGC,mixedGC,fullGC。
那么如果在新生代与老年代之间存在跨代引用的情况呢?首先新生代收集,时由于该新生代对象存在引用,所以它会活下来,躲过数次GC之后它的年龄也会提升,当它年龄成为老年代的年龄标准时,也就转移至老年代了,跨代引用也就自然消除了。这个思路也导致在垃圾收集时需要扫描老年代对象判定引用存在性,如果扫描整个老年代区域所耗费的时间会比较大,我们只需在新生代上建立一个全局的数据结构(记忆集),这个结构把老年代分为一个一个小块,标识哪一个小块存在跨代引用,此后的新生代垃圾收集,只有标识了存在跨代引用的老年代小块才会被扫描。
标记-清除算法
标记清除算法与它的名字一致,一般在新生代垃圾回收时采取这种算法,它的实现原理是:首先标记那些需要回收的对象,在对某一指定收集区域标记完成后,统一实现对这些标记对象的垃圾回收,但是!!!它回收之后的内存区域往往不带有重新整理的功能,会带有一片一片的内部碎片,难以存储需要连续空间较大的对象。
标记-复制算法
标记复制算法算是标记清除算法的一种进阶版,带有自动处理碎片的能力,实际上它将负责的内存区域采用半区复制清除的方法,浪费空间但是可以处理碎片,现在的HOTSTOP虚拟机采取的是1:9的比例进行标记复制算法的垃圾回收,它们分别是新生代区域中的两个servior区与一个Edn区,划分的新生代内存区域比例为1:1:8;在进行标记清理时,先将Edn与其中一个servior区存储的不需要回收的对象进行复制到另一个特殊的servior区中,再进行清理。如果它的内存小于需要复制进来的对象大小,就要进行对老年代区域的"分配担保"机制了,后面会提到。
注意:对于新生代与老年代等内存比例设置可以由参数设置。
标记-整理算法
标记整理算法则是处理老年代的垃圾回收算法,主要的实现方式是:通过标记清除算法的同时将存活对象向边界靠拢,顺带完成堆内存碎片的处理,要求垃圾回收器有较强的压缩整理功能了。