2026/3/29 4:27:12
网站建设
项目流程
如何进行课程中心网站建设,出售全国精准客户电话号码,建站快车的功能介绍,网站建设宗旨是指深入 JVM 入门核心#xff1a;垃圾回收器#xff08;GC#xff09;原理、算法与实战调优全解析#xff08;Java 实习生必修课#xff09;
适用人群
计算机科学与技术、软件工程等专业的在校本科生或研究生#xff0c;正在学习 JVM 相关课程#xff1b;Java 初级开发者…深入 JVM 入门核心垃圾回收器GC原理、算法与实战调优全解析Java 实习生必修课适用人群计算机科学与技术、软件工程等专业的在校本科生或研究生正在学习 JVM 相关课程Java 初级开发者或实习生希望系统掌握内存管理与垃圾回收机制准备 Java 后端岗位面试需深入理解 GC 原理、常见回收器及调优策略对系统性能优化、线上故障排查感兴趣的开发者。本文假设读者已了解 Java 基础语法、对象生命周期、堆栈内存模型等概念。内容由浅入深兼顾理论深度与工程实践适合从“会写 Java”迈向“懂 Java”的进阶学习者。关键词JVM、垃圾回收、GC、Garbage Collection、内存管理、堆内存、新生代、老年代、GC 算法、标记-清除、复制、标记-整理、分代收集、Serial GC、Parallel GC、CMS、G1、ZGC、Shenandoah、Stop-The-World、GC Roots、可达性分析、内存泄漏、OOM、Java 实习生、计算机专业核心课、JVM 入门、GC 调优、jstat、jmap、VisualVM。引言为什么 Java 程序员必须理解垃圾回收在 Java 开发中我们享受着“自动内存管理”的便利——无需手动free()内存对象用完即弃。然而这种便利的背后是垃圾回收器Garbage Collector, GC在默默工作。当程序出现卡顿、内存溢出OOM、CPU 飙升等问题时若不了解 GC 机制将束手无策。作为计算机专业学生和 Java 实习生掌握 GC 不仅是 JVM 入门的核心内容更是理解 Java 性能瓶颈的关键面试中高频考察的技术点参与高并发、低延迟系统开发的基础能力。本文将系统讲解JVM 内存布局、GC 判定原理、主流回收算法、经典垃圾回收器演进、实战调优技巧并辅以真实案例与工具使用助你构建完整的 GC 认知体系。一、JVM 内存布局回顾GC 的作用域垃圾回收主要发生在堆Heap区域。JVM 运行时数据区如下┌───────────────────────────────┐ │ Method Area │ ← 类信息、常量、静态变量JDK 8 称 Metaspace ├───────────────────────────────┤ │ Heap (GC 主战场) │ ← 对象实例分配于此 │ ┌───────────┬─────────────┐ │ │ │ Young Gen │ Old Gen │ │ │ │ (Eden │ │ │ │ │ Survivor)│ │ │ │ └───────────┴─────────────┘ │ ├───────────────────────────────┤ │ Stack (线程私有) │ ← 局部变量、方法调用栈不参与 GC ├───────────────────────────────┤ │ PC Register │ ├───────────────────────────────┤ │ Native Method Stack │ └───────────────────────────────┘✅关键点堆 新生代Young Generation 老年代Old Generation新生代 ≈ Eden Survivor0 Survivor1默认 8:1:1GC 主要针对堆内存方法区Metaspace也可回收类卸载。二、如何判定对象“已死”GC Roots 与可达性分析2.1 引用计数法Reference Counting为何被弃用早期语言如 Python使用引用计数对象被引用一次计数1引用失效计数-1计数为 0 则回收。致命缺陷无法解决循环引用问题。classA{Bb;}classB{Aa;}AobjAnewA();BobjBnewB();objA.bobjB;objB.aobjA;// objA 和 objB 互相引用但外部无引用 → 应被回收// 引用计数法两者计数均为 1永不回收❌ Java未采用引用计数法。2.2 可达性分析算法Reachability AnalysisJVM 采用可达性分析从一组GC Roots出发向下搜索引用链。不可达的对象即为“垃圾”。GC Roots 包括类型示例虚拟机栈中局部变量引用的对象方法参数、局部变量本地方法栈中 JNI 引用的对象native 方法中的引用方法区中静态变量引用的对象static Object obj方法区中常量引用的对象public static final String STR hello;图解GC Roots → A → B → C ↘ D E ← F孤立对象 结果A、B、C、D 存活E、F 可回收2.3 对象的“死亡”两次确认finalize() 机制即使对象不可达JVM 也不会立即回收。它会经历两次标记第一次标记可达性分析发现不可达筛选判断是否有必要执行finalize()若对象重写了finalize()且未被调用过则将其放入F-Queue队列第二次标记若对象在finalize()中重新与 GC Roots 建立联系则“复活”否则回收。⚠️注意finalize()不保证执行线程优先级低不应依赖finalize()释放资源推荐 try-with-resources 或显式 closeJDK 9 已标记为deprecated。三、垃圾回收算法四大经典策略3.1 标记-清除Mark-Sweep步骤标记从 GC Roots 出发标记所有存活对象清除统一回收未标记对象。优点实现简单。缺点效率低标记和清除过程耗时内存碎片回收后产生大量不连续空闲块可能导致大对象分配失败触发 Full GC。适用场景老年代如 CMS 的并发清除阶段。3.2 复制Copying思想将内存分为两块每次只使用一块。GC 时将存活对象复制到另一块然后清空原内存。JVM 优化版新生代将新生代分为Eden Survivor0 Survivor1对象首先分配在 EdenGC 时将 Eden From Survivor 中的存活对象复制到 To Survivor交换 From/To 角色。优点无碎片目标区域连续分配高效只需移动存活对象新生代“朝生夕死”存活率低。缺点空间浪费始终有一块 Survivor 空闲不适合老年代存活率高复制成本大。✅默认比例Eden:Survivor 8:1可通过-XX:SurvivorRatio调整。3.3 标记-整理Mark-Compact步骤标记同标记-清除整理将所有存活对象向一端移动清理直接清理边界外的内存。优点无碎片适合老年代存活率高整理比重置更高效。缺点整理过程耗时较长。适用场景Serial Old、Parallel Old。3.4 分代收集Generational Collection核心思想不同年龄对象的生命周期不同应采用不同回收策略。新生代对象“朝生夕死”适合复制算法老年代对象存活率高适合标记-清除或标记-整理。分代假说弱分代假说绝大多数对象朝生夕死强分代假说熬过多次 GC 的对象未来更可能存活。四、主流垃圾回收器详解从 Serial 到 ZGCJVM 提供多种 GC 实现可组合使用新生代 老年代。下表总结各回收器特性回收器作用区域算法线程数STW适用场景Serial新生代复制单线程是客户端模式、单核 CPUParNew新生代复制多线程是配合 CMS 使用Parallel Scavenge新生代复制多线程是吞吐量优先后台计算Serial Old老年代标记-整理单线程是Client 模式、CMS 备用Parallel Old老年代标记-整理多线程是配合 Parallel ScavengeCMS老年代标记-清除多线程部分低延迟Web 应用G1整堆标记-整理 复制多线程可预测大堆、低延迟ZGC整堆并发标记 并发整理多线程极短10ms超大堆TB 级Shenandoah整堆并发标记 并发整理多线程极短低延迟Red Hat 主导STWStop-The-WorldGC 过程中暂停所有用户线程导致应用卡顿。下面我们重点解析CMS、G1、ZGC三大现代回收器。4.1 CMSConcurrent Mark Sweep低延迟的先驱目标最小化 STW 时间适合 Web 应用。工作流程四阶段初始标记Initial MarkSTW标记 GC Roots 直接关联对象速度快。并发标记Concurrent Mark与用户线程并发遍历整个对象图可能产生浮动垃圾标记期间新死亡的对象。重新标记RemarkSTW修正并发标记期间的变动比初始标记慢但远快于 Full GC。并发清除Concurrent Sweep与用户线程并发清除垃圾不整理内存→ 产生碎片。缺点内存碎片长期运行后大对象分配失败触发 Full GCSerial OldCPU 敏感并发阶段占用 CPU 资源吞吐量下降JDK 14 已废弃推荐迁移到 G1/ZGC。启用方式-XX:UseConcMarkSweepGC4.2 G1Garbage-First面向服务端的大堆解决方案目标在大堆4GB上实现可预测的停顿时间默认 200ms。核心思想将堆划分为多个 Region默认 2048 个每个 Region 可扮演 Eden/Survivor/Old/Humongous大对象角色优先回收垃圾最多的 RegionGarbage-First使用Remembered SetRSet记录跨 Region 引用避免全堆扫描。工作流程初始标记STW标记 GC Roots并发标记并发遍历对象图最终标记STW处理 SATBSnapshot-At-The-Beginning缓冲区筛选回收EvacuationSTW选择部分 Region 复制存活对象。优势可预测停顿通过-XX:MaxGCPauseMillis设定目标无内存碎片采用复制整理支持大堆Region 机制灵活管理内存。调优参数-XX:G1HeapRegionSizeRegion 大小1~32MB-XX:G1MixedGCCountTarget混合 GC 次数-XX:G1HeapWastePercent允许的堆浪费比例默认回收器JDK 9-XX:UseG1GC4.3 ZGCZ Garbage Collector超低延迟的未来目标停顿时间不超过 10ms支持TB 级堆。核心技术并发标记与用户线程并发并发重定位Relocation移动对象时通过Load Barrier重写指针Colored Pointers利用 64 位指针的高位存储元数据如 mark0/mark1/relocating。优势停顿极短通常 1ms堆大小几乎不影响停顿时间高吞吐并发执行。限制JDK 11实验JDK 15 正式支持仅 Linux/Windows 支持macOS JDK 17。启用方式-XX:UseZGC五、GC 日志分析与监控工具实战5.1 开启 GC 日志JDK 8 及之前-XX:PrintGC# 打印基本 GC-XX:PrintGCDetails# 打印详细信息-XX:PrintGCTimeStamps# 打印时间戳-Xloggc:/path/to/gc.log# 指定日志文件JDK 9统一日志框架-Xlog:gc*:filegc.log:time,tags# 等效于 PrintGCDetails5.2 解读 GC 日志以 Parallel GC 为例[GC (Allocation Failure) [PSYoungGen: 1024K-128K(2048K)] 1024K-256K(4096K), 0.0012345 secs] [Full GC (Ergonomics) [PSYoungGen: 128K-0K(2048K)] [ParOldGen: 2048K-2000K(4096K)] 2176K-2000K(6144K), 0.0123456 secs]字段解析PSYoungGen: 1024K-128K(2048K)新生代 GC 前 1024KGC 后 128K总容量 2048K1024K-256K(4096K)堆总使用量变化0.0012345 secsSTW 时间。5.3 常用监控工具工具功能jstat实时监控 GC 统计jstat -gc pidjmap生成堆转储jmap -dump:formatb,fileheap.hprof pidjconsole / VisualVM图形化监控内存、线程、GCGCViewer可视化分析 GC 日志Arthas线上诊断dashboard、vmtool️jstat 示例jstat -gc123451000# 每秒输出一次 PID12345 的 GC 信息S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT512.0512.00.0256.04096.01024.010240.05000.0...1000.521.01.5YGC/YGCTYoung GC 次数/总耗时FGC/FGCTFull GC 次数/总耗时重点关注 FGC 频率频繁 Full GC 表示内存压力大。六、常见 GC 问题与调优策略6.1 内存泄漏Memory Leak现象堆内存持续增长最终 OOM。排查步骤用jmap生成 heap dump用Eclipse MAT或VisualVM分析查找Dominating Tree中占用内存最大的对象检查是否因静态集合、缓存未清理、监听器未注销导致。MAT 技巧使用 “Leak Suspects Report” 自动生成可疑对象。6.2 频繁 Young GC原因Eden 区太小对象分配速率过高Survivor 区过小对象过早晋升老年代。调优增大新生代-Xmn2g调整 Eden/Survivor 比例-XX:SurvivorRatio4Eden:Survivor4:1启用TLABThread Local Allocation Buffer-XX:UseTLAB默认开启。6.3 频繁 Full GC原因老年代空间不足内存泄漏System.gc() 被显式调用。调优增大堆内存-Xmx8g -Xms8g建议 XmsXmx 避免动态扩容禁用显式 GC-XX:DisableExplicitGC切换到 G1/ZGC-XX:UseG1GC。6.4 GC 停顿过长策略低延迟场景选用 G1/ZGC设定停顿目标-XX:MaxGCPauseMillis100G1避免大对象减少 Humongous 对象分配G1 中 Region 50%。七、GC 在框架与生产环境中的应用7.1 Spring Boot 默认 GC 策略JDK 8Parallel GC吞吐量优先JDK 9G1 GC平衡吞吐与延迟。建议Web 应用低延迟显式指定 G1批处理任务高吞吐保留 Parallel GC。7.2 大厂 GC 实践阿里G1 为主ZGC 试点美团G1 自研 GC 日志分析平台Twitter早期 Shenandoah 用户。指标监控Young GC 频率 1次/秒Full GC 频率 0理想状态GC 停顿 P99 100ms。八、学习建议与扩展阅读8.1 动手实验清单模拟 OOM创建 List 不断 add 对象观察 GC 日志对比 GC 性能用 JMH 测试 Parallel vs G1 的吞吐/延迟分析 heap dump用 MAT 找出内存泄漏点调优实战调整-Xmx、-XX:NewRatio观察 GC 行为变化。8.2 推荐资料《深入理解 Java 虚拟机第3版》— 周志明第3章“垃圾收集器与内存分配策略”是中文领域最权威的讲解。Oracle GC Tuning Guide官方调优指南涵盖所有回收器。Bilibili 视频尚硅谷《JVM 从入门到精通》R大RednaxelaFXGC 技术分享8.3 面试高频问题GC 如何判断对象可回收新生代为什么用复制算法CMS 和 G1 的区别如何排查内存泄漏ZGC 为什么能做到低延迟九、总结垃圾回收器是 JVM 自动内存管理的核心引擎。理解其原理与调优方法是 Java 开发者从“功能实现”走向“性能卓越”的必经之路。本文系统讲解了GC 判定原理可达性分析与 GC Roots四大回收算法标记-清除、复制、标记-整理、分代收集主流回收器演进从 Serial 到 ZGC适应不同场景需求实战调优技巧日志分析、工具使用、常见问题解决生产环境实践框架默认策略与大厂经验。最后寄语不要满足于“程序不崩”而要追求“流畅如丝”。从今天起开启 GC 日志用 jstat 监控你的应用你将真正掌握 JVM 的脉搏。欢迎在评论区交流 你在项目中是否遇到过 GC 相关的性能问题 对哪种回收器最感兴趣点赞 收藏 关注获取更多 JVM 与 Java 底层原理干货