上QQ阅读APP看书,第一时间看更新
2.3.3 标记压缩算法
标记清除算法的内存利用率虽然比较高,但是有一个重要的缺点:内存碎片化严重。内存碎片化可能会导致无法满足应用大内存块的需求。另外一种GC算法是标记压缩算法,其本质是就地压缩内存空间,而不是像复制算法那样需要一个额外的空间。算法可以分为以下4步:
1)遍历内存空间,标记内存空间的活跃对象。
2)遍历内存空间,计算所有活跃对象压缩后的位置,“压缩后”是指如果遇到死亡对象,则直接将其覆盖。
3)遍历内存空间,更新所有活跃对象成员变量压缩后的位置。
4)遍历内存空间,移动所有活跃对象到第二步计算好的位置,此时由于对象内部的成员变量已经完成更新,因此移动对象后所有的引用关系都是正确的。
在一些实现中,第二步和第三步可以借助额外的数据结构合并成一步。总体来说,标记压缩算法需要遍历3~4次内存空间,虽然内存利用率更高,并且GC执行后不存在内存碎片的问题,但是因为多次遍历内存空间,故算法的执行效率不高。
仍然以图2-4的内存状态为例,标记压缩算法执行结束后的示意图如图2-9所示。
图2-9 标记压缩算法执行后内存示意图
由于标记压缩算法执行效率不高,因此通常作为GC的兜底算法。标记压缩在JVM中也有多种实现,分别是串行实现、并行实现。在第3~5章中都会介绍标记压缩算法。