予枫个人主页 个人专栏: 《Java 从入门到起飞》《读研码农的干货日常》《Java 面试刷题指南》 Debug 这个世界Return 更好的自己引言垃圾收集GC是JVM的核心能力之一也是Java面试的高频考点。日常开发中我们很少直接操作GC但理解其底层算法标记清除、标记复制、标记整理能帮我们写出更高效、更不易内存泄漏的代码还能轻松应对面试官的连环追问。本文将从原理、流程、优缺点、适用场景四大维度全面拆解这3种核心垃圾收集算法结合实例和流程图让新手也能吃透底层逻辑。文章目录引言一、垃圾收集算法核心前提如何判断“垃圾”二、3种核心垃圾收集算法全解析2.1 标记-清除算法Mark-Sweep最基础的GC算法2.1.1 核心原理2.1.2 算法流程图2.1.3 优缺点分析2.1.4 适用场景2.2 标记-复制算法Mark-Copy解决内存碎片的“优化版”2.2.1 核心原理2.2.2 算法流程图2.2.3 优缺点分析2.2.4 适用场景2.3 标记-整理算法Mark-Compact兼顾无碎片和高利用率2.3.1 核心原理2.3.2 算法流程图2.3.3 优缺点分析2.3.4 适用场景三、3种算法核心对比一目了然四、面试官追问环节实战必备五、总结一、垃圾收集算法核心前提如何判断“垃圾”在讲解具体算法前先明确一个核心问题JVM如何判断一个对象是“垃圾”即不再被使用可回收目前最主流的判断方式是可达性分析算法以“GC Roots”为起点如虚拟机栈中引用的对象、方法区中类静态属性引用的对象等遍历对象引用链若某个对象无法通过任何引用链到达GC Roots则判定为垃圾可被回收。小贴士这是所有垃圾收集算法的基础面试时大概率会先问这个前提建议牢记二、3种核心垃圾收集算法全解析2.1 标记-清除算法Mark-Sweep最基础的GC算法标记-清除算法是所有垃圾收集算法的基础核心分为“标记”和“清除”两个阶段流程简单易懂。2.1.1 核心原理标记阶段遍历所有对象标记出可回收的垃圾对象基于可达性分析清除阶段遍历整个堆内存将所有被标记为垃圾的对象直接回收释放内存空间。2.1.2 算法流程图开始遍历对象标记垃圾遍历堆内存清除垃圾释放内存结束2.1.3 优缺点分析✅ 优点实现简单无需移动对象执行效率高标记和清除阶段逻辑直接适用于对象存活率高的场景无需频繁复制对象。❌ 缺点内存碎片严重清除垃圾后内存会出现大量不连续的空闲块当需要分配大对象时即使总空闲内存足够也可能因无法找到连续内存而触发GC清除效率随垃圾数量增加而下降若堆内存中垃圾过多清除阶段需要遍历更多对象耗时变长。2.1.4 适用场景垃圾数量较少、对象存活率高的场景早期JVM的老年代老年代对象存活率高移动成本高标记-清除无需移动对象更适配对内存连续性要求不高的场景。2.2 标记-复制算法Mark-Copy解决内存碎片的“优化版”为了解决标记-清除算法的内存碎片问题标记-复制算法应运而生核心思路是“复制存活对象清空原区域”。2.2.1 核心原理划分内存将堆内存划分为两个大小相等的区域通常称为From区和To区同一时间只使用其中一个区域From区标记阶段遍历From区标记出所有存活的对象复制阶段将From区中所有存活的对象复制到To区按顺序连续存放清空阶段清空From区的所有内容交换From区和To区的角色完成一次GC。2.2.2 算法流程图开始划分From区和To区使用From区标记From区中存活对象将存活对象复制到To区清空From区交换From/To区角色结束2.2.3 优缺点分析✅ 优点无内存碎片存活对象被连续复制到To区空闲内存也是连续的分配大对象时不易触发GC清除效率高无需遍历整个堆内存只需清空From区即可耗时固定。❌ 缺点内存利用率低堆内存被划分为两个相等区域同一时间只能使用一半相当于浪费了50%的内存空间复制成本高若对象存活率高如老年代需要频繁复制大量存活对象耗时变长效率下降。2.2.4 适用场景对象存活率低的场景如新生代大部分对象朝生夕死复制成本低对内存连续性要求高的场景目前JVM新生代的主流算法如Serial GC、ParNew GC优化后采用“ eden区两个survivor区”并非严格的1:1划分提升内存利用率。小技巧点赞收藏本文后续遇到新生代GC相关问题直接对照这里的逻辑就能快速梳理2.3 标记-整理算法Mark-Compact兼顾无碎片和高利用率标记-整理算法结合了标记-清除和标记-复制的优点既解决了标记-清除的内存碎片问题又解决了标记-复制的内存利用率低问题适用于对象存活率高的场景。2.3.1 核心原理标记阶段与标记-清除算法一致遍历所有对象标记出可回收的垃圾对象整理阶段将所有存活的对象按内存地址从低到高连续移动集中到堆内存的一端清除阶段清空存活对象另一端的所有垃圾对象释放连续的内存空间。2.3.2 算法流程图开始遍历对象标记垃圾移动所有存活对象集中到堆的一端清空另一端的垃圾对象释放内存结束2.3.3 优缺点分析✅ 优点无内存碎片存活对象连续存放空闲内存也是连续的适配大对象分配内存利用率高无需划分多个区域整个堆内存都可充分利用没有浪费适配对象存活率高的场景如老年代无需频繁复制对象。❌ 缺点执行效率低相比标记-清除多了“整理”阶段移动存活对象移动对象时还需要更新对象的引用地址耗时更长移动成本高若存活对象数量多、体积大移动过程会占用大量CPU资源影响程序运行性能。2.3.4 适用场景对象存活率高的场景如老年代大部分对象长期存活移动成本低于复制成本对内存连续性和利用率都有要求的场景目前JVM老年代的主流算法如G1 GC的老年代回收、Parallel Old GC。三、3种算法核心对比一目了然为了方便大家记忆和面试作答整理了以下对比表格涵盖核心维度直接背即可算法类型核心优势核心缺点适用场景标记-清除实现简单、无需移动对象、效率高内存碎片严重、清除效率随垃圾增多下降老年代早期、垃圾少、存活率高标记-复制无内存碎片、清除效率固定内存利用率低、复制成本高新生代、存活率低标记-整理无内存碎片、内存利用率高执行效率低、移动成本高老年代、存活率高四、面试官追问环节实战必备这部分是面试高频考点比纯八股文更实用帮你提前应对面试官的连环追问建议重点记忆追问1标记-清除算法的内存碎片问题有什么解决方案答有两种核心方案① 采用标记-整理算法通过移动存活对象消除碎片② 采用内存池机制将内存划分为不同大小的块对应分配不同大小的对象减少碎片产生。追问2为什么新生代用标记-复制算法老年代用标记-清除/标记-整理算法答因为新生代对象“朝生夕死”存活率极低通常不到10%标记-复制算法的复制成本低且无内存碎片适配新生代需求而老年代对象存活率高通常90%以上若用标记-复制算法复制成本极高且内存利用率低因此用标记-清除无需移动或标记-整理无碎片更适配。追问3标记-整理算法中移动存活对象后如何处理对象的引用地址答JVM会采用“记忆集”Remembered Set和“卡表”Card Table记录对象的引用关系移动对象后会遍历所有引用该对象的地方更新引用地址确保程序能正常访问移动后的对象。追问43种算法中哪种算法的执行效率最高哪种最适合生产环境的老年代答执行效率标记-清除 标记-复制 标记-整理仅考虑执行速度不考虑后续影响生产环境老年代最常用标记-整理算法兼顾无碎片和高内存利用率避免大对象分配失败。五、总结本文全面拆解了JVM核心的3种垃圾收集算法标记-清除基础、有碎片、标记-复制无碎片、利用率低、标记-整理无碎片、利用率高从原理、流程、优缺点到适用场景结合流程图和面试追问帮大家吃透底层逻辑。核心结论算法的选择本质是“权衡效率、内存利用率、内存连续性”新生代优先选标记-复制老年代优先选标记-整理具体需结合JVM的GC收集器如G1、ZGC灵活适配。