JVM垃圾回收机制详解
发布时间:2026/9/7 3:47:53 锦皓数字建站

JVM垃圾回收机制详解1. 引言1.1 什么是垃圾回收机制垃圾回收Garbage CollectionGC是JVM自动管理内存的一种机制。它负责回收不再使用的对象所占用的内存空间避免内存泄漏确保程序能够高效运行。1.2 为什么需要垃圾回收在C/C等语言中开发者需要手动管理内存这容易导致内存泄漏忘记释放已分配的内存悬空指针访问已释放的内存双重释放重复释放同一块内存JVM通过垃圾回收机制自动管理内存大大降低了内存管理的复杂性。2. 垃圾回收的基本概念2.1 对象存活判定2.1.1 引用计数法原理为每个对象维护一个引用计数器优点实现简单判断效率高缺点无法解决循环引用问题// 循环引用示例classA{Bb;}classB{Aa;}2.1.2 可达性分析算法原理从GC Roots出发通过引用链遍历所有可达对象GC Roots包括虚拟机栈中引用的对象方法区中类静态属性引用的对象方法区中常量引用的对象本地方法栈中JNI引用的对象2.2 对象的引用类型引用类型回收条件使用场景强引用永远不会被回收普通对象引用软引用内存不足时回收缓存弱引用下次GC时回收缓存、监听器虚引用随时可能被回收跟踪对象回收事件2.3 对象的生命周期创建 → 可用 → 不可见 → 不可达 → 回收创建阶段对象被创建并初始化可用阶段对象被引用可以被程序访问不可见阶段对象的引用超出作用域不可达阶段对象不再被任何GC Root引用回收阶段垃圾回收器回收对象占用的内存3. 垃圾回收算法3.1 标记-清除算法Mark-Sweep3.1.1 算法原理标记阶段遍历所有对象标记存活的对象清除阶段遍历所有对象回收未标记的对象3.1.2 优缺点优点实现简单缺点效率问题标记和清除效率都不高空间问题产生大量内存碎片3.2 复制算法Copying3.2.1 算法原理将内存分为两块每次只使用其中一块GC时将存活对象复制到另一块内存清除当前使用的内存块3.2.2 优缺点优点没有内存碎片分配内存时只需移动堆顶指针效率高缺点内存利用率只有50%3.3 标记-整理算法Mark-Compact3.3.1 算法原理标记阶段标记所有存活的对象整理阶段将存活对象向内存一端移动然后清理边界外的内存3.3.2 优缺点优点没有内存碎片内存利用率高缺点移动对象需要更新引用效率较低3.4 分代收集算法Generational Collection3.4.1 堆内存分代JVM将堆内存分为三个区域新生代Young Generation新创建的对象存放在这里Eden区对象首先在这里创建Survivor区存放经过GC后存活的对象From SpaceTo Space老年代Old Generation经过多次GC后仍然存活的对象永久代Permanent Generation存放类信息、常量、静态变量JDK 8后被元空间取代3.4.2 各代GC策略新生代使用复制算法当Eden区满时触发Minor GC存活对象被复制到Survivor区对象每经过一次GC年龄加1年龄达到阈值默认15后晋升到老年代老年代使用标记-清除或标记-整理算法当老年代空间不足时触发Major GCMajor GC通常伴随Minor GCFull GC4. 垃圾收集器4.1 Serial收集器4.1.1 特点单线程收集收集时暂停所有用户线程Stop The World简单高效适合客户端模式4.1.2 工作流程用户线程 → GC暂停用户线程 → 用户线程 → GC暂停用户线程...4.2 ParNew收集器4.2.1 特点Serial收集器的多线程版本多个线程并行进行垃圾回收仍然需要暂停用户线程4.2.2 工作流程用户线程 → GC暂停用户线程多线程并行回收 → 用户线程...4.3 Parallel Scavenge收集器4.3.1 特点关注吞吐量用户代码运行时间 / 总时间自适应调节策略适合后台任务4.3.2 关键参数-XX:MaxGCPauseMillis最大GC停顿时间-XX:GCTimeRatioGC时间占比-XX:UseAdaptiveSizePolicy自适应调节策略4.4 Serial Old收集器4.4.1 特点Serial收集器的老年代版本单线程使用标记-整理算法4.5 Parallel Old收集器4.5.1 特点Parallel Scavenge的老年代版本多线程使用标记-整理算法4.6 CMS收集器Concurrent Mark Sweep4.6.1 特点以最短停顿时间为目标并发收集低停顿使用标记-清除算法4.6.2 工作流程初始标记STW → 并发标记 → 重新标记STW → 并发清除4.6.3 优缺点优点并发收集低停顿缺点对CPU资源敏感无法处理浮动垃圾产生内存碎片4.7 G1收集器Garbage-First4.7.1 特点面向服务端应用将堆划分为多个Region可预测的停顿时间整体使用标记-整理算法局部使用复制算法4.7.2 工作流程初始标记 → 并发标记 → 最终标记 → 筛选回收4.7.3 关键参数-XX:UseG1GC启用G1收集器-XX:MaxGCPauseMillis目标停顿时间-XX:G1HeapRegionSizeRegion大小4.8 ZGC收集器4.8.1 特点超低延迟停顿时间不超过10ms支持TB级堆内存使用着色指针和读屏障技术4.8.2 工作流程初始标记 → 并发标记 → 并发预备重分配 → 并发重分配 → 并发重映射5. 垃圾回收调优5.1 关键参数5.1.1 内存相关-Xms初始堆大小-Xmx最大堆大小-Xmn新生代大小-XX:SurvivorRatioEden与Survivor区比例-XX:NewRatio老年代与新生代比例5.1.2 收集器相关-XX:UseSerialGC使用Serial收集器-XX:UseParNewGC使用ParNew收集器-XX:UseParallelGC使用Parallel Scavenge收集器-XX:UseConcMarkSweepGC使用CMS收集器-XX:UseG1GC使用G1收集器-XX:UseZGC使用ZGC收集器5.1.3 GC日志-verbose:gc输出GC日志-XX:PrintGCDetails打印GC详细信息-XX:PrintGCDateStamps打印GC时间戳-Xloggc:gc.logGC日志输出文件5.2 调优原则5.2.1 选择合适的收集器客户端应用Serial收集器服务端应用G1收集器对延迟敏感ZGC收集器5.2.2 合理设置堆大小新生代大小堆的1/3到1/2老年代大小堆的1/2到2/3避免频繁Full GC5.2.3 监控GC活动使用JVisualVM、JConsole等工具分析GC日志监控堆内存使用情况5.3 常见问题5.3.1 频繁Full GC可能原因老年代空间不足大对象直接进入老年代内存泄漏解决方案增加老年代空间优化代码减少大对象创建检查内存泄漏5.3.2 GC停顿时间过长可能原因堆内存过大对象图结构复杂收集器选择不当解决方案选择合适的收集器如G1、ZGC调整GC停顿时间目标优化对象结构6. 总结6.1 垃圾回收机制的重要性自动管理内存降低开发复杂度避免内存泄漏和悬空指针提高程序稳定性和可靠性6.2 选择垃圾收集器的考虑因素延迟要求低延迟选G1或ZGC吞吐量要求高吞吐量选Parallel内存大小大内存选G1或ZGC应用类型客户端选Serial服务端选G16.3 未来发展趋势更智能的垃圾回收算法更低的停顿时间更好的内存利用效率与容器化技术的深度集成
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。