垃圾收集
垃圾回收算法包括标记-复制算法、标记-清除算法和标记整理算法。
- 标记-复制算法(Mark-Sweep)
算法执行过程:算法分为“标记”和“清除”两个阶段:首先标记所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象;也可以反过来,标记存活的对象,统一回收所有未被标记的对象。标记过程就是对象事发后属于垃圾的判定过程。
算法主要缺点:第一执行效率 不稳定,如果Java堆中存在大量需要被回收的对象,必须进行大量的标记和清除动作,只想效率会随着对象数量增加而降低。第二内存空间的碎片化问题,标记、清除之后产生大量不连续的内存碎片,碎片太多可能导致在以后程序运行过程中需要分配较大对象时无法找到足够连续的内存而不得不提前触发另一次垃圾收集动作。
回收后的状态:
存活对象(#26dc22) | 回收对象(#58686a) | 未用空间(#f9f6fd) |
- 标记-复制算法
- 半区复制(Semispace Copying):将可用内存按容量划分为大小相等的两块。每次只使用其中一块,当 一块内存用完,就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理。这种算法存在两个缺点,第一个是可用空间缩小一半,空间浪费;第二个如果多数对象存活,这种算法会产生大量内存间复制的开销。
- Appel式回收:把新生代分为一块较大的Eden(占比80%)和两块较小的Survivor(10%)空间,每次分配内存只使用Eden和其中一块Survivor。发生垃圾搜集时,将Eden和Survivor中仍然存活的对象一次性复制到另外一块Survivor空间上,然后直接清理Eden和Survivor。还有一个充当罕见情况的“逃生门”的安全设计,当Survivor空间不足以容纳一次Minor GC之后存活的对象时,就需要依赖其他内存区域(实际上大多就是老年代)进行分配担保(Handle Promotion)。
Eden | Survivor | Survivor | |||||||
回收后状态:
Eden | Survivor | Survivor | |||||||
存活对象(#26dc22) | 回收对象(#58686a) | 未用空间(#f9f6fd) | 保留区域(#88abdc) |
- 标记-整理算法:针对老年代对象的存亡特征,提出针对性的“标记-整理”(Mark-Compact)算法,其中的标记过程仍然与“标记-清除”算法一样,但是后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存。标记-清除算法与标记-整理算法本质差异在于前者是一种非移动式的回收算法,而后者是移动式的。整理过程对象移动操作必须全程暂停用户应用程序才能进行,这种停顿被描述为“Stop The World”。
回收类型分为部分收集(新生代收集、老年代收集和混合收集)、整堆收集。标记-清除算法
- 部分收集(Partial GC):指目标不是完整收集整个Java堆的垃圾收集。
- 新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。
- 老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集器。目前只有CMS收集器会有单独收集老年代的行为。
- 混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。
- 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix