G1 垃圾回收:复制算法(标记整理)与撤离失败 G1 垃圾回收复制算法与撤离失败一、G1 的复制算法G1 将堆划分为等大的 Region在 Young GC 和 Mixed GC 时使用复制算法evacuation进行回收选定本次要回收的 Region 集合Collection Set将其中的存活对象复制到空闲 Region复制完成后原 Region整体清空不产生内存碎片效率高但前提是有足够的空闲 Region 存放存活对象。二、没有空间存放存活对象时怎么办当空闲 Region 耗尽时触发Evacuation Failure撤离失败也叫To-Space Exhausted。处理链路阶段G1 的行为结果① 尝试扩展堆如果堆上下限允许申请新的 Region可能解决问题② 撤离失败搬不动的对象就地保留垃圾也不回收本次 GC 效率骤降③ Full GC退化到 Mark-Sweep-Compact标记-清除-整理算法单线程整理全堆STW 极长最后保底手段Full GC 用的不是复制算法而是整理算法。这是 G1 的保底方案。三、撤离失败是全部还是部分是部分失败不是全部。撤离是一个逐对象、逐 Region的过程空间耗尽那一刻是断流式的Collection Set本次要回收的 Region 集合 ├── Region A ──复制──► 空闲 Region X ✅ 成功 ├── Region B ──复制──► 空闲 Region Y ✅ 成功 ├── Region C ──复制──► 空闲 Region Z ✅ 成功Z 快满了 ├── Region D ──复制──► ❗ 找不到空闲 Region 了 │ ├── 对象 d1 ── 已复制到 Z ✅ │ ├── 对象 d2 ── 复制失败留在原地 ❌ │ └── 对象 d3 ── 没轮到留在原地 ❌ └── Region E ── 根本没开始留在原地 ❌各部分的状态区域状态已完成复制的 RegionA、B、C正常清空回收 ✅正在复制时断流的 RegionD已搬走的不受影响剩下的就地保留 ❌还没轮到的 RegionE原封不动这次不碰 ❌失败 Region 的后续处理撤离失败的 Region 中存活对象和垃圾对象都留下本次 GC 对这些 Region 无效下次 GC 时这些 Region 会被优先加入 Collection Set优先回收四、实践建议撤离失败通常意味着堆太小或分配速率过高解决方向增大堆内存调大-XX:G1MaxNewSizePercent给年轻代更多空间降低对象分配速率排查内存泄漏、大对象分配关注 GC 日志中的to-space exhausted/evacuation failure关键字