【JVM虚拟机】垃圾回收GC:垃圾回收算法:标记-清除、标记-复制、标记-整理、分代收集(附《思维导图》+《面试高频考点清单》)
文章目录JVM垃圾回收算法 系统性知识体系总结一、垃圾回收基础概念1.1 垃圾回收的本质1.2 GC解决的三个核心问题1.3 对象存活判定算法二、四大核心垃圾回收算法详解2.1 标记-清除算法(Mark-Sweep)执行过程优点缺点适用场景2.2 标记-复制算法(Mark-Copy)执行过程优点缺点改进Appel式回收适用场景2.3 标记-整理算法(Mark-Compact)执行过程优点缺点与标记-清除的对比适用场景2.4 分代收集算法(Generational Collection)核心思想JVM分代模型对象晋升机制GC类型三、算法演进与组合使用3.1 算法组合的基本原则3.2 常见垃圾收集器与算法对应关系3.3 算法性能对比四、关键概念与注意事项4.1 Stop-The-World(STW)4.2 安全点(Safepoint)4.3 垃圾回收的性能指标4.4 常见误区五、总结JVM垃圾回收算法 面试高频考点问答清单一、垃圾回收基础概念Q1什么是垃圾回收(GC)它解决了什么问题Q2JVM如何判断一个对象是否存活Q3什么是循环引用为什么引用计数法无法解决二、四大核心垃圾回收算法Q4简述标记-清除算法(Mark-Sweep)的执行过程、优缺点和适用场景Q5简述标记-复制算法(Mark-Copy)的执行过程、优缺点和适用场景Q6什么是Appel式回收它解决了什么问题Q7简述标记-整理算法(Mark-Compact)的执行过程、优缺点和适用场景Q8标记-清除和标记-整理算法有什么区别三、分代收集算法Q9什么是分代收集算法它的核心思想是什么Q10JVM的分代模型是怎样的各代采用什么算法Q11对象什么时候会晋升到老年代Q12Minor GC、Major GC和Full GC有什么区别四、关键性能与机制概念Q13什么是Stop-The-World(STW)为什么会发生Q14什么是安全点(Safepoint)Q15垃圾回收的三个核心性能指标是什么它们之间有什么关系五、常见误区与调优基础Q16调用System.gc()会立即触发Full GC吗Q17为什么新生代GC比老年代GC快Q18标记-整理算法总是比标记-清除算法好吗六、垃圾收集器与算法对应关系Q19常见垃圾收集器分别采用什么核心算法Q20现代垃圾收集器G1、ZGC还基于分代思想吗JVM垃圾回收算法 一页纸速记版一、基础核心二、四大核心算法必考三、分代收集核心四、关键机制五、收集器与算法对应六、常见误区JVM垃圾回收算法 系统性知识体系总结一、垃圾回收基础概念1.1 垃圾回收的本质垃圾回收(Garbage Collection, GC)是JVM自动管理内存的核心机制负责识别并释放不再被使用的内存空间避免内存泄漏和OOM(OutOfMemoryError)。1.2 GC解决的三个核心问题哪些内存需要回收判断对象是否存活什么时候回收触发GC的时机如何回收垃圾回收算法的实现1.3 对象存活判定算法引用计数法给对象添加引用计数器引用1引用失效-1计数器为0则可回收优点实现简单判定效率高缺点无法解决循环引用问题JVM未采用可达性分析算法以GC Roots为起点向下搜索不可达的对象即为垃圾GC Roots包括虚拟机栈中引用的对象、方法区中类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中JNI引用的对象JVM主流实现采用此算法二、四大核心垃圾回收算法详解2.1 标记-清除算法(Mark-Sweep)最基础的垃圾回收算法其他算法均基于此改进而来执行过程标记阶段遍历所有GC Roots标记所有存活对象清除阶段遍历堆内存回收所有未被标记的对象优点实现简单不需要移动对象适用于存活对象多、垃圾少的场景缺点内存碎片化严重回收后产生大量不连续的内存碎片分配大对象时可能提前触发Full GC标记和清除过程效率都不高需遍历两次堆适用场景老年代垃圾回收的基础早期JVM版本的默认算法2.2 标记-复制算法(Mark-Copy)为解决标记-清除的内存碎片化问题而设计执行过程将内存划分为大小相等的两块区域From区和To区只使用其中一块(From区)进行对象分配当From区满时标记所有存活对象将存活对象完整复制到To区并按顺序排列清空整个From区交换From和To的角色优点无内存碎片化复制后对象连续排列分配内存时只需移动指针效率极高只需要遍历一次存活对象垃圾多时效率高缺点内存利用率低只能使用一半的内存空间存活对象多时复制开销大改进Appel式回收新生代采用1个Eden区2个Survivor区的划分方式(默认比例8:1:1)每次只使用Eden和一个Survivor区回收时将存活对象复制到另一个Survivor区内存利用率提升至90%适用场景新生代垃圾回收因为新生代对象朝生夕死存活对象少复制开销小2.3 标记-整理算法(Mark-Compact)结合了标记-清除和标记-复制的优点解决老年代的内存问题执行过程标记阶段与标记-清除相同标记所有存活对象整理阶段将所有存活对象向内存一端移动按顺序排列直接清理掉边界以外的所有内存优点无内存碎片化对象连续排列内存利用率100%不需要预留空间适合存活对象多的场景缺点需要移动对象STW(Stop-The-World)时间更长实现复杂需要更新所有引用地址与标记-清除的对比特性标记-清除标记-整理内存碎片严重无对象移动不需要需要执行效率中等低内存利用率高高适用场景存活对象少存活对象多适用场景老年代垃圾回收老年代对象存活时间长存活对象多2.4 分代收集算法(Generational Collection)不是一种独立的算法而是基于对象生命周期的组合策略核心思想根据对象的存活时间将堆内存划分为不同的代不同代采用不同的垃圾回收算法以提高整体效率JVM分代模型新生代(Young Generation)存放新创建的对象特点对象生命周期短存活率低回收算法标记-复制算法回收频率高每次回收时间短分为Eden区(80%)、Survivor0(10%)、Survivor1(10%)老年代(Old Generation)存放长期存活的对象特点对象生命周期长存活率高回收算法标记-清除或标记-整理算法回收频率低每次回收时间长方法区/元空间(Method Area/Metaspace)存放类信息、常量、静态变量等回收条件苛刻主要回收废弃常量和无用类回收频率极低对象晋升机制对象在Survivor区每熬过一次Minor GC年龄1默认年龄达到15岁时晋升到老年代大对象直接进入老年代避免在新生代频繁复制Survivor区空间不足时部分对象提前晋升GC类型Minor GC新生代垃圾回收触发条件Eden区满特点速度快STW时间短Major GC老年代垃圾回收触发条件老年代空间不足特点速度慢STW时间长Full GC整个堆内存的垃圾回收触发条件老年代满、方法区满、System.gc()显式调用特点STW时间最长应尽量避免三、算法演进与组合使用3.1 算法组合的基本原则新生代标记-复制算法存活对象少复制开销小老年代标记-清除或标记-整理算法存活对象多复制开销大3.2 常见垃圾收集器与算法对应关系收集器代核心算法特点Serial新生代标记-复制单线程简单高效ParNew新生代标记-复制Serial的多线程版本Parallel Scavenge新生代标记-复制吞吐量优先Serial Old老年代标记-整理单线程作为CMS的后备Parallel Old老年代标记-整理Parallel Scavenge的老年代版本CMS老年代标记-清除并发低延迟有内存碎片G1全堆标记-整理复制区域化分代式可预测停顿ZGC/Shenandoah全堆着色指针读屏障超低延迟几乎无STW3.3 算法性能对比算法标记效率清除/复制效率内存利用率内存碎片适用场景标记-清除低低高严重存活对象少标记-复制低高低无存活对象极少标记-整理低极低高无存活对象多分代收集高高高低通用场景四、关键概念与注意事项4.1 Stop-The-World(STW)GC执行时暂停所有用户线程的现象所有垃圾回收算法都会产生STW只是时间长短不同现代垃圾收集器的核心目标就是缩短STW时间4.2 安全点(Safepoint)用户线程执行过程中能够暂停的特定位置GC只能在安全点触发常见安全点方法调用、循环跳转、异常跳转4.3 垃圾回收的性能指标吞吐量用户代码执行时间/(用户代码执行时间GC时间)延迟GC导致的STW时间内存占用堆内存的使用效率这三个指标构成不可能三角无法同时最优4.4 常见误区误区1System.gc()会立即触发Full GC实际上只是建议JVM执行GCJVM可以选择忽略误区2新生代GC比老年代GC快这是因为新生代存活对象少而不是算法本身更快误区3标记-整理总是比标记-清除好当老年代碎片不多时标记-清除的STW时间更短五、总结垃圾回收算法是JVM内存管理的核心四种算法各有优劣标记-清除基础但有碎片标记-复制无碎片但内存利用率低标记-整理无碎片且内存利用率高但STW时间长分代收集结合前三种算法的优点是现代JVM的主流实现理解这些算法的原理和适用场景对于JVM调优和排查内存问题至关重要。随着JVM的发展新的垃圾收集器如G1、ZGC不断涌现但它们的核心思想仍然基于这四种基础算法。JVM垃圾回收算法 面试高频考点问答清单按面试提问频率排序答案提炼核心得分点加粗为必背关键词一、垃圾回收基础概念Q1什么是垃圾回收(GC)它解决了什么问题答GC是JVM自动管理堆内存的核心机制负责识别并释放不再被使用的内存空间。它解决了三个核心问题哪些内存需要回收对象存活判定什么时候回收GC触发时机如何回收垃圾回收算法实现Q2JVM如何判断一个对象是否存活答主流采用可达性分析算法以GC Roots为起点向下搜索不可达的对象即为垃圾。GC Roots包括虚拟机栈引用的对象、方法区静态属性引用的对象、方法区常量引用的对象、本地方法栈JNI引用的对象淘汰了引用计数法无法解决循环引用问题Q3什么是循环引用为什么引用计数法无法解决答两个对象互相引用对方导致它们的引用计数器永远不为0。例如AanewA();BbnewB();a.bb;b.aa;anull;bnull;此时两个对象已无法被访问但引用计数仍为1永远无法被回收。二、四大核心垃圾回收算法Q4简述标记-清除算法(Mark-Sweep)的执行过程、优缺点和适用场景答执行过程①标记阶段遍历GC Roots标记所有存活对象②清除阶段遍历堆回收所有未标记对象优点实现简单不需要移动对象缺点内存碎片化严重标记和清除都需要遍历整个堆效率不高适用场景老年代垃圾回收的基础适用于存活对象多、垃圾少的场景Q5简述标记-复制算法(Mark-Copy)的执行过程、优缺点和适用场景答执行过程将内存分为大小相等的两块每次只使用一块回收时将存活对象完整复制到另一块然后清空原块优点无内存碎片化分配内存只需移动指针效率极高垃圾多时效率高缺点内存利用率低只能用一半存活对象多时复制开销大适用场景新生代垃圾回收对象朝生夕死存活少Q6什么是Appel式回收它解决了什么问题答是标记-复制算法的改进将新生代划分为1个Eden区2个Survivor区默认比例8:1:1。每次只使用Eden和一个Survivor区回收时将存活对象复制到另一个Survivor区内存利用率从50%提升至90%是现代JVM新生代的标准实现Q7简述标记-整理算法(Mark-Compact)的执行过程、优缺点和适用场景答执行过程①标记阶段同标记-清除②整理阶段将所有存活对象向内存一端移动按顺序排列③清理边界外的所有内存优点无内存碎片化内存利用率100%缺点需要移动对象STW时间更长实现复杂需要更新所有引用地址适用场景老年代垃圾回收对象存活时间长存活多Q8标记-清除和标记-整理算法有什么区别答特性标记-清除标记-整理内存碎片严重无对象移动不需要需要STW时间较短较长实现复杂度低高适用场景存活对象少存活对象多三、分代收集算法Q9什么是分代收集算法它的核心思想是什么答不是独立算法而是基于对象生命周期的组合策略。核心思想根据对象存活时间将堆划分为不同的代不同代采用最适合的垃圾回收算法以提高整体效率是现代JVM的主流实现Q10JVM的分代模型是怎样的各代采用什么算法答新生代存放新创建的对象特点是生命周期短、存活率低划分Eden(80%) Survivor0(10%) Survivor1(10%)算法标记-复制算法回收频率高每次时间短老年代存放长期存活的对象特点是生命周期长、存活率高算法标记-清除或标记-整理算法回收频率低每次时间长元空间存放类信息、常量、静态变量等回收条件苛刻频率极低Q11对象什么时候会晋升到老年代答年龄达标对象在Survivor区每熬过一次Minor GC年龄1默认15岁晋升大对象直接晋升超过阈值的大对象直接进入老年代避免新生代频繁复制动态年龄判定Survivor区中相同年龄所有对象大小总和超过Survivor空间的一半年龄≥该年龄的对象直接晋升空间分配担保失败Minor GC时Survivor区放不下存活对象直接晋升到老年代Q12Minor GC、Major GC和Full GC有什么区别答Minor GC新生代垃圾回收触发条件Eden区满特点速度快STW时间短Major GC仅老年代垃圾回收触发条件老年代空间不足特点速度慢STW时间长Full GC整个堆新生代老年代元空间的垃圾回收触发条件老年代满、元空间满、System.gc()显式调用、空间分配担保失败特点STW时间最长应尽量避免四、关键性能与机制概念Q13什么是Stop-The-World(STW)为什么会发生答GC执行时暂停所有用户线程的现象。原因GC需要准确标记存活对象若用户线程同时运行会导致对象引用关系不断变化无法准确标记所有垃圾回收算法都会产生STW现代收集器的核心目标就是缩短STW时间Q14什么是安全点(Safepoint)答用户线程执行过程中能够暂停的特定位置。GC只能在安全点触发常见安全点方法调用、循环跳转、异常跳转设计原则让用户线程不会长时间运行不到安全点Q15垃圾回收的三个核心性能指标是什么它们之间有什么关系答三个指标构成GC不可能三角无法同时最优吞吐量用户代码执行时间/(用户代码执行时间GC时间)越高越好延迟GC导致的STW时间越短越好内存占用堆内存的使用效率越低越好吞吐量优先收集器Parallel Scavenge Parallel Old延迟优先收集器CMS、G1、ZGC五、常见误区与调优基础Q16调用System.gc()会立即触发Full GC吗答不会。System.gc()只是建议JVM执行Full GCJVM可以选择忽略。生产环境中应避免显式调用System.gc()可能导致不必要的Full GCQ17为什么新生代GC比老年代GC快答不是因为标记-复制算法本身更快而是因为新生代存活对象极少。标记-复制算法只需要处理存活对象垃圾越多效率越高老年代存活对象多无论是标记-清除还是标记-整理都需要处理大量对象所以速度慢Q18标记-整理算法总是比标记-清除算法好吗答不是。当老年代内存碎片不多时标记-清除的STW时间更短不需要移动对象当碎片积累到一定程度无法分配大对象时才需要执行标记-整理CMS收集器就是平时用标记-清除碎片过多时用Serial Old做标记-整理作为后备六、垃圾收集器与算法对应关系Q19常见垃圾收集器分别采用什么核心算法答收集器代核心算法核心特点Serial新生代标记-复制单线程简单高效ParNew新生代标记-复制Serial的多线程版本Parallel Scavenge新生代标记-复制吞吐量优先Serial Old老年代标记-整理单线程CMS后备Parallel Old老年代标记-整理Parallel Scavenge老年代版本CMS老年代标记-清除并发低延迟有碎片G1全堆标记-整理复制区域化分代可预测停顿ZGC/Shenandoah全堆着色指针读屏障超低延迟10msQ20现代垃圾收集器G1、ZGC还基于分代思想吗答G1仍然基于分代思想但采用区域化分代将堆划分为多个大小相等的Region每个Region可以动态扮演Eden、Survivor或老年代ZGC和Shenandoah是不分代的全堆收集器但它们的核心优化思想仍然源于四大基础算法特别是标记-整理和复制算法JVM垃圾回收算法 一页纸速记版加粗为必背关键词考前3分钟快速过一、基础核心GC本质自动识别并释放无用内存解决哪些/何时/如何回收对象存活判定主流可达性分析以GC Roots为起点不可达即垃圾GC Roots栈引用、静态属性、常量、JNI引用淘汰引用计数法无法解决循环引用二、四大核心算法必考算法核心过程核心优点核心缺点核心适用标记-清除标记存活→清除垃圾简单不移动对象内存碎片严重效率低老年代基础标记-复制分两块→复制存活→清空原块无碎片分配快内存利用率50%存活多则复制贵新生代朝生夕死标记-整理标记存活→移到一端→清理边界无碎片利用率100%需移动对象STW更长老年代存活多分代收集按存活时间分代→各代用最优算法综合效率最高实现复杂现代JVM主流Appel式回收新生代8:1:1Eden2Survivor利用率90%标准实现三、分代收集核心新生代Eden(80%)S0(10%)S1(10%)标记-复制Minor GC频繁且快老年代长期存活对象标记-清除/整理Major GC慢且少对象晋升年龄15岁、大对象、动态年龄判定、空间担保失败GC类型Minor GCEden满→新生代→STW短Full GC老年代/元空间满→全堆→STW最长尽量避免四、关键机制STWGC暂停所有用户线程所有算法都有目标是缩短时间安全点GC只能在此触发方法调用、循环、异常GC不可能三角吞吐量、延迟、内存占用无法同时最优吞吐量优先Parallel组合延迟优先CMS、G1、ZGC五、收集器与算法对应收集器代核心算法核心特点Serial/ParNew新生代标记-复制单/多线程Parallel Scavenge新生代标记-复制吞吐量优先CMS老年代标记-清除并发低延迟有碎片G1全堆标记-整理复制区域化分代可预测停顿ZGC全堆着色指针读屏障超低延迟(10ms)六、常见误区System.gc()只是建议GC不会立即执行新生代GC快是因为存活对象少不是算法本身快标记-整理不总是更好碎片少时标记-清除STW更短