面试必答:标记-清除算法为何导致内存不连续

作者:袖梨 2026-07-27
标记-清除算法仅清空死亡对象空间而不移动存活对象,导致内存碎片化、空闲块孤立且无法合并,尤其老年代易因长期运行而严重碎片化。

因为它只“清空位置”,从不“挪动东西”。

存活对象原地不动,间隙永久保留

标记-清除算法在清除阶段不做任何移动操作:所有存活对象保持原有内存地址不变,仅把死亡对象占用的空间标记为空闲。这些空闲空间就像散落在固定骨架之间的缝隙,彼此孤立、大小随机。时间一长,堆就变成蜂窝状——空洞密布,但无法拼接。

清除动作不合并,空闲块各自为政

算法本身不检查相邻空闲区域是否可合并。两个紧挨着的64KB空闲块,在空闲链表里仍是两条独立记录,不会自动合成128KB大块。分配器遍历时只能逐个匹配,根本看不到“连续性”。

高频分配加速碎片淤积

循环中反复创建小对象(如临时String、HashMap.Entry),会不断在存活对象之间切分、填充、再释放,导致小碎片快速累积。就像往固定格子的抽屉里不停塞不同尺寸的纸片,越塞越乱,最终连一张完整A4都铺不开。

老年代尤其容易“积碎成疾”

年轻代用复制算法,每轮Minor GC都会把存活对象集中搬运,天然归整;老年代对象多、存活率高、没备用空间可复制,只能就地清理。CMS这类纯标记-清除收集器长期运行后,碎片雪球越滚越大,大对象一来就卡住。

相关文章

精彩推荐