ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

08-JVM(三)垃圾回收

08-JVM(三)垃圾回收 《Java 面试八股精讲》系列第 8/14 篇。本系列是我对照开源项目 JavaGuidehttps://github.com/Snailclimb/JavaGuide复习时亲手整理的面试笔记力求把高频考点压成“能背、能讲、能画”的密度。如有错漏欢迎评论区指出。内存分配与回收原则对象优先在 Eden 区分配大多数情况下对象在新生代 Eden 区分配大对象直接进入老年代大对象是需要大量连续内存空间的对象如长字符串、大数组长期存活的对象将进入老年代死亡对象判断方法引用计数法给对象添加一个引用计数器每当有一个地方引用它计数器加 1引用失效计数器减 1计数器为 0 的对象就是不可能再被使用的。⚠️ 这个方法实现简单但主流 JVM 并没有选择它重要原因之一是它无法单独解决对象之间循环引用的问题。可达性分析算法基本思想通过一系列称为“GC Roots”的对象作为起点向下搜索走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时证明此对象不可用需要被回收。四种引用类型引用类型类比回收时机特点强引用必不可少的生活用品内存不足宁抛 OOM 也不回收最普遍如String s new String(abc)软引用可有可无的生活用品内存压力大时可能回收抛 OOM 前一定清理完所有仅软可达对象适合内存敏感的高速缓存弱引用更脆弱的用品下次 GC 时回收不保证立刻生命周期比软引用更短暂虚引用形同虚设不阻止回收get()恒返回null必须配合引用队列用于接收可达性变化通知、安排清理工作废弃常量与无用类的判定废弃常量假如字符串常量池中存在 “abc”当前没有任何 String 对象引用它它就是废弃常量。发生内存回收且有必要时“abc” 会被清理出常量池。无用的类需同时满足三个条件该类所有实例都已被回收Java 堆中不存在该类的任何实例加载该类的ClassLoader已被回收该类对应的java.lang.Class对象没有任何地方被引用无法通过反射访问该类的方法垃圾收集算法算法原理优点缺点适用标记-清除标记存活对象统一回收未标记对象最基础效率低产生大量内存碎片—复制内存分两块用完一块就把存活对象复制到另一块一次清理掉旧块无碎片、高效可用内存减半存活对象多时复制性能差新生代标记-整理标记后让存活对象向一端移动清理端边界外内存无碎片多了整理步骤效率不高老年代分代收集按对象存活周期分代各代选合适算法因地制宜并非所有收集器都分代早期 ZGC 非分代HotSpot 经典设计延伸面试问题HotSpot 为什么要分新生代和老年代本质上是让垃圾回收算法与对象的生命周期特征相匹配新生代 高死亡率 低存活率 →标记-复制算法高效清理大量垃圾老年代 低死亡率 高存活率 →标记-整理算法稳定管理长期存活对象这种因地制宜的策略使 HotSpot 能在保证回收正确性的前提下最大化平衡吞吐量与暂停时间。垃圾收集器如果说收集算法是内存回收的方法论那么垃圾收集器就是内存回收的具体实现。我们能做的就是根据具体应用场景选择适合自己的垃圾收集器。收集器线程模式特点适用目标Serial单线程最基础最悠久GC 时暂停所有工作线程Stop The World客户端模式、小内存ParNew多线程Serial 的多线程版本其余行为与 Serial 完全一样低延迟CMS 的最佳搭档Parallel Scavenge多线程标记-复制算法唯吞吐量论收集器高吞吐量CMS并发第一款真正意义上的并发收集器目标最短停顿注重用户体验的应用G1并行并发面向服务器大内存多核可预测停顿软目标兼顾停顿与吞吐ZGC并发停顿控制在几毫秒内不受堆大小影响最大支持 16TB超大堆、极低延迟CMS 收集器重点CMSConcurrent Mark Sweep是以获取最短回收停顿时间为目标的收集器是 HotSpot 第一款真正意义上的并发收集器——第一次实现了垃圾收集线程与用户线程基本上同时工作。四个步骤初始标记短暂停顿STW标记直接与 GC Roots 相连的对象并发标记GC 线程与用户线程同时运行用闭包结构记录可达对象。因用户线程可能不断更新引用域无法保证实时性会跟踪记录发生引用更新的地方重新标记修正并发标记期间因用户程序运行导致标记变动的那部分记录。停顿一般比初始标记稍长远短于并发标记并发清除开启用户线程同时 GC 线程对未标记区域做清扫优点并发收集、低停顿。三个明显缺点对 CPU 资源敏感无法处理浮动垃圾使用的标记-清除算法会产生大量空间碎片G1 收集器重点G1Garbage-First是面向服务器的垃圾收集器主要针对配备多颗处理器及大容量内存的机器以极高概率满足 GC 停顿时间要求的同时还具备高吞吐量性能特征。四个特点并行与并发充分利用多核硬件优势缩短 STW部分原本需要停顿 Java 线程的 GC 动作G1 可并发执行分代收集可独立管理整个 GC 堆仍保留分代概念空间整合整体基于标记-整理局部基于标记-复制无碎片可预测的停顿根据用户设置的停顿目标建立预测模型并选择回收集合软目标不保证每次都不超标运作步骤初始标记短暂 STW标记 GC Roots 直接可达的对象并发标记与应用并发运行标记所有可达对象可能持续较长时间最终标记短暂 STW处理并发标记结束后残留的少量引用变更筛选回收选择回收价值高的区域复制存活对象到新区域回收旧区域含一个或多个 STWZGC 收集器与 ParNew 和 G1 类似ZGC 也采用标记-复制算法但做了重大改进暂停时间可控制在几毫秒以内且不受堆内存大小影响STW 出现更少代价是牺牲一些吞吐量。ZGC 最大支持16TB堆内存。《Java 面试八股精讲》系列目录加粗为本篇Java 基础一JDK、JRE、JVM、JIT 与 AOTJava 基础二equals、hashCode 与 StringJava 基础三异常、反射、代理与序列化Java 基础四IO 模型、泛型擦除与值传递集合框架List、Set、Queue、Map 全景JVM一内存区域与对象创建JVM二Class 文件与类加载8. JVM三垃圾回收算法与收集器本篇Spring一基础与 IoCSpring二Bean 的声明、注入与生命周期Spring三AOP、MVC 与循环依赖Spring四事务详解与失效场景Spring五Spring Boot 与 Web 注解数据库基础与系统设计规范
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进