标记完成后,我们就开始进行压缩了,将活对象压缩到“堆区”的一段,然后将剩余的部分进行清除。下方就是将1和3这两个活对象进行了压缩。压缩后,将下方的空间进行Clean。也就是说Clean的部分,就可以分配新的对象了。
下方截图是标记-压缩清理后的状态。标记-压缩式垃圾回收可充分利用堆区的空间,当垃圾比较少时,这种处理方式效率还是比较高的,如果垃圾太多碎片化严重时,移动的“活对象”较多,效率比较低。这种方式可以与“复制式”结合使用,根据当前堆区的垃圾状态来选择哪种回收方式。正好与“复制式”形成优势互补。将“复制式”、“标记-压缩式”的回收方式进行整合的算法,就是“分代式”垃圾回收机制,下方会详细介绍到。
4、分代式垃圾回收
“分代”即根据对象易产生垃圾的状态或者对象的大小将其分为不同的代,可分为“年轻代”、“年老代”和“永久代”。“永久代”不在堆中,再次先不做讨论。根据分代垃圾回收的特点,画了下方的简图。
在堆中,主要把区域分为“年轻代”、“年老代”。位于“年轻代”的对象内存创建的时间不长,更新比较快,易产生“内存垃圾”,所以“年轻代”的垃圾回收使用“复制式”回收方式效率比较高。“年轻代”又可分为两个区,一个是Eden Space(伊甸园)和Survivor Sprace(幸存者区)。Eden Space去主要存放那些初次被创建的对象,而Survivor Sprace存放的是从Eden Space幸存下来的“活对象”。在Survivor Sprace(幸存者区)中又分为form和to两块,用于相互复制对象来进行垃圾清理。
而“年老代”中存放的是一些“大对象”以及从Survivor Sprace中存活下来的“对象”,一般到“年老代”的对象比较稳定,产生垃圾较少,针对这种情况,使用“标记-压缩”式回收效率比较高。“分代垃圾回收”主要是分而治之,根据不同对象的特点将其分类,根据分类的特点来具体选择合适的垃圾回收方案。