问:Java 对象头的核心组成与作用是什么?

答:

  1. 第一部分是 Mark Word,动态存储锁状态、哈希码、GC 分代年龄等运行时数据
  2. 第二部分是类型指针,指向对象对应的 Class 类元数据,确定对象所属类型
  3. 数组对象额外存储数组长度,保障数组访问的边界安全
  4. Mark Word 是 JVM 实现锁优化、GC、哈希计算的核心数据基础

记忆口诀:Mark Word 加类型指针


问:实例数据和对齐填充的核心规则是什么?

答:

  1. 实例数据按字段类型与继承关系存储,相同宽度字段会被分配到一起
  2. 父类字段优先于子类字段存储,保障继承体系的字段布局规范
  3. 对齐填充非必须,仅当对象总大小不是 8 字节整数倍时补充占位
  4. 8 字节对齐是 HotSpot 的内存管理规则,提升内存访问的寻址效率

记忆口诀:实例存字段,对齐 8 字节

问:常见的垃圾收集算法有哪些,核心特点是什么?

答:

  1. 标记 - 清除:先标记存活对象,再批量清除未标记垃圾,实现简单灵活但会产生内存碎片
  2. 标记 - 复制:将内存均分两块,回收时把存活对象复制到空闲区,无内存碎片但需额外内存空间
  3. 标记 - 整理:标记存活对象后,将其紧凑移动到内存一端再清理边界外垃圾,无碎片但有对象移动开销
  4. 分代回收:按对象生命周期划分分代,不同分代适配对应算法,是当前 JVM 的核心回收策略

记忆口诀:清除复制整理分代四大算法


问:分代回收算法的核心逻辑是什么,不同分代适配什么算法?

答:

  1. 核心逻辑:根据对象存活周期将堆分为新生代、老年代,不同分代采用匹配的回收算法,兼顾回收效率与内存利用率
  2. 新生代:新创建对象生命周期短、大量对象朝生夕灭,适配标记 - 复制算法
  3. 老年代:对象存活时间长、存活率高,适配标记 - 整理、标记 - 清除算法
  4. 是 HotSpot 虚拟机的默认回收策略,完美适配绝大多数业务场景的对象生命周期特征

记忆口诀:新生代复制,老年代整理清除


问:三大基础垃圾收集算法的核心优缺点对比?

答:

表格

算法

核心优点

核心缺点

标记 - 清除

实现简单,无需移动对象,适配复杂内存结构

产生内存碎片,内存利用率低,STW 停顿时间长

标记 - 复制

无内存碎片,回收效率高,无需遍历全堆

需要预留额外内存,存在内存空间浪费

标记 - 整理

无内存碎片,内存利用率高,无需预留空间

需移动存活对象,回收耗时增加,不适用于存活对象多的场景

记忆口诀:清除简单有碎片,复制高效费空间,整理无碎片耗时间

问:如何判断 Java 对象仍然存活?

答:

  1. 主流判定方案分为引用计数法、可达性分析法两种
  2. 引用计数法:给对象维护引用计数器,被引用计数 + 1,引用失效计数 - 1,计数为 0 判定为可回收
  3. 可达性分析法:以 GC Roots 为根节点遍历引用链,可被访问到的对象判定为存活,不可达对象判定为可回收
  4. 引用计数法无法解决循环引用问题,现代 JVM 均采用可达性分析法作为核心判定方案

记忆口诀:计数看引用数,可达看 GC Roots


问:引用计数法的核心缺陷是什么?

答:

  1. 无法解决对象间循环引用的问题,互相引用的对象无外部引用时,引用计数仍不为 0,无法被回收
  2. 会导致内存泄漏,对象占用的堆内存无法被 GC 释放
  3. 存在额外的引用计数维护开销,现代 JVM 均不采用该方案

记忆口诀:循环引用计数失效


问:什么是 GC Roots,常见的 GC Roots 有哪些?

答:

  1. GC Roots 是可达性分析的起点根对象,是 JVM 判定必须存活的对象,不会被 GC 回收
  2. 常见 GC Roots 包括:虚拟机栈局部变量引用的对象、本地方法栈 JNI 引用的对象、方法区静态属性引用的对象、方法区常量引用的对象、活跃线程中的引用对象
  3. 只有从 GC Roots 出发可遍历到的对象,才会被判定为存活对象

记忆口诀:栈静态常量线程是根

问:能详细说一下 CMS 收集器的垃圾收集过程吗?

答:CMS 全称 Concurrent Mark Sweep,是一款以低延迟、最小化 STW 停顿为核心目标的老年代垃圾收集器,基于标记 - 清除算法实现,核心设计是将绝大多数耗时操作与用户线程并发执行,大幅降低 GC 对业务响应的影响,其完整回收流程分为 5 个核心阶段:

  1. 初始标记(STW):仅标记 GC Roots 直接可达的对象,不做全堆遍历,执行速度极快,仅产生非常短暂的 STW 停顿,是回收流程的第一次 Stop The World。
  2. 并发标记(与用户线程并发):从初始标记的对象出发,全堆遍历追踪引用链,标记所有可达的存活对象。该阶段是整个回收流程中耗时最长的环节,但全程与用户线程并行执行,不会产生 STW 停顿。
  3. 重新标记(STW):修正并发标记期间,因用户线程持续运行导致的对象引用状态变化(新增对象、引用失效等),完成最终的存活对象标记。该阶段会触发 STW,停顿时间长于初始标记,但远短于并发标记阶段。
  4. 并发清理(与用户线程并发):基于标记结果,批量清理所有未被标记的垃圾对象,释放对应的内存空间,全程与用户线程并行执行,无 STW 停顿。
  5. 并发重置(与用户线程并发):重置 CMS 收集器的内部状态、数据结构,为下一次垃圾回收循环做准备,耗时极短,全程与用户线程并行执行。

核心特点:仅初始标记、重新标记两个阶段触发 STW,绝大多数耗时操作均与用户线程并发,可显著降低 GC 的停顿时间,适配对响应时间敏感的业务场景。

记忆口诀:初始标记 STW,并发标记全堆扫,重新标记修正错,并发清理重置好


问:CMS 收集器的核心优缺点是什么?

答:核心优点

  1. 低延迟:绝大多数操作与用户线程并发,STW 停顿时间极短,对业务响应影响极小
  2. 并发执行:核心耗时环节不阻塞业务运行,适合互联网、电商等对响应时间敏感的场景

核心缺点

  1. 内存碎片:基于标记 - 清除算法实现,回收后会产生内存碎片,长期运行可能导致提前触发 Full GC
  2. CPU 资源占用:并发阶段会占用 CPU 核心资源,抢占业务线程的计算资源
  3. 并发失败风险:回收过程中用户线程持续产生新对象,若老年代内存提前耗尽,会触发 Concurrent Mode Failure,退化为 Serial Old 单线程 Full GC,产生长时间 STW
  4. 浮动垃圾:并发清理阶段用户线程产生的新垃圾,只能等到下一次 GC 才能清理

记忆口诀:低延迟是优势,碎片 CPU 是劣势


问:CMS 收集器的哪些阶段会触发 STW 停顿?

答:CMS 整个回收流程中,仅两个阶段会触发 Stop The World:

  1. 初始标记阶段:仅标记 GC Roots 直接可达对象,停顿时间极短
  2. 重新标记阶段:修正并发标记期间的引用变化,停顿时间略长于初始标记,但仍远低于传统 Full GC 的停顿时间其余并发标记、并发清理、并发重置三个阶段,均与用户线程并发执行,不会触发 STW 停顿。

记忆口诀:初始重新两阶段 STW

问:G1 垃圾收集器了解吗?

答:G1 全称 Garbage-First,是 JDK9 及以后 HotSpot 虚拟机的默认垃圾收集器,核心设计目标是在用户可设定的停顿时间范围内,最大化回收效率与系统吞吐量,专为大堆内存、低延迟要求的服务端应用设计,解决了 CMS 内存碎片、整堆回收长停顿的核心缺陷。

它的核心特点如下:

  1. 区域化分代布局:打破传统分代的连续内存限制,将整个 Java 堆划分为多个大小相等的 Region,每个 Region 可动态扮演 Eden 区、Survivor 区、老年代 Old 区、大对象专属 Humongous 区,灵活适配不同的内存分配需求。
  2. 垃圾优先回收策略:Garbage-First 的核心逻辑,根据每个 Region 的垃圾占比、回收耗时计算回收价值,优先回收垃圾最多的 Region,用最小的停顿时间换取最大的内存释放量。
  3. 可预测的停顿模型:内置停顿预测算法,用户可设置最大 GC 停顿时间,G1 会根据历史回收数据,选择最优的 Region 回收组合,严格控制单次 GC 的 STW 时长。
  4. 并行与并发结合:STW 阶段多线程并行执行提升效率,耗时最长的标记、统计阶段与用户线程并发执行,平衡低延迟与业务吞吐量。
  5. 混合回收模式:不仅回收新生代,还会选择性回收部分高价值老年代 Region,避免整堆回收的长停顿,均衡处理全堆内存,大幅降低 Full GC 的触发频率。

记忆口诀:Region 分块垃圾优先,停顿可控复制无碎片


问:G1 垃圾收集器的完整回收流程是什么?

答:G1 的核心回收流程分为 4 个阶段,其中 2 个短时间 STW 阶段,2 个核心并发阶段,最终的回收环节为可控 STW:

  1. 初始标记(STW):仅标记 GC Roots 直接可达的对象,执行速度极快,仅产生非常短暂的 STW 停顿,该阶段会同步触发一次新生代的 Minor GC。
  2. 并发标记(与用户线程并发):从初始标记的对象出发,全堆遍历引用链,标记所有可达的存活对象,同时统计每个 Region 的存活对象占比与回收价值。该阶段是耗时最长的环节,但全程与用户线程并行执行,无 STW 停顿。
  3. 最终标记(STW,也叫重新标记):修正并发标记期间,因用户线程持续运行导致的对象引用状态变化,完成最终的存活对象标记。该阶段会触发 STW,停顿时间远短于传统 Full GC,也优于 CMS 的重新标记阶段。
  4. 筛选回收(STW):G1 的核心特色阶段。根据用户设定的停顿时间目标,筛选出回收价值最高的 Region,将其中的存活对象复制到新的空 Region 中,再清空被回收的 Region。该阶段为多线程并行执行的 STW,因仅回收部分 Region,停顿时间完全可控,同时通过复制实现了内存整理,无内存碎片问题。

记忆口诀:初始标记 STW,并发标记全堆扫,最终标记修正错,筛选回收控停顿


问:G1 垃圾收集器的核心优缺点与适用场景是什么?

答:核心优点

  1. 停顿时间可控可预测,用户可自定义最大停顿目标,完美适配对响应时间敏感的业务场景
  2. 基于 Region 复制回收,从根本上解决了 CMS 的内存碎片问题,内存利用率更高
  3. 混合回收模式兼顾新生代与老年代,大幅降低 Full GC 的触发频率与停顿时长
  4. 专门的 Humongous 区优化大对象存储,避免了传统分代收集器大对象提前触发 Full GC 的问题
  5. 堆内存越大优势越明显,完美适配 4G 以上的大堆服务端应用

核心缺点

  1. 内存占用与运行额外开销高于 CMS,需要维护每个 Region 的记忆集,会占用更多的堆内存
  2. 小堆内存场景下,因 Region 管理的额外开销,性能表现可能不如 CMS
  3. 并发阶段会占用 CPU 核心资源,与业务线程抢占计算资源
  4. 大量跨 Region 引用的场景下,记忆集的维护开销会显著增加,可能影响回收效率

适用场景:大堆内存、对 GC 停顿时间敏感的服务端应用,如互联网电商、金融交易系统,是 JDK9 及以后 JVM 的默认垃圾收集器。

问:Java 对象一定分配在堆中吗?

答:

  1. 不一定。Java 对象默认会分配在堆内存中,但经过 JIT 编译器的逃逸分析优化后,无逃逸的对象可以不进入堆内存,实现栈上分配、标量替换。
  2. 核心前提是逃逸分析:JIT 会分析对象引用的作用域,判断对象是否会逃出当前方法 / 线程,只有完全无逃逸的对象,才能被优化为非堆分配。
  3. 栈上分配:无方法逃逸的对象,可直接分配在虚拟机栈的栈帧中,方法执行结束栈帧出栈时,对象随之一同销毁,无需 GC 回收,大幅降低堆内存压力与 GC 开销。
  4. 标量替换:无逃逸的对象可被进一步拆解为基础类型的标量,直接在栈上分配其成员变量,完全不需要在堆中创建完整的对象实例,是更极致的优化。

记忆口诀:默认堆分配,无逃逸可栈上存


问:什么是逃逸分析,逃逸分为哪几种类型?

答:

  1. 逃逸分析是 JIT 编译器的动态优化技术,核心是分析对象引用的动态作用范围,判断对象是否会被方法外部、其他线程访问,以此决定是否可以执行优化。
  2. 方法逃逸:对象引用被传递到方法外部,比如作为方法返回值、赋值给全局静态变量、作为入参传递给其他方法,对象可被方法外的代码访问。
  3. 线程逃逸:对象引用被传递到其他线程访问,比如赋值给跨线程共享的实例 / 静态变量,是更严重的逃逸级别,对象可被多线程同时访问。
  4. 只有完全无逃逸(既无方法逃逸,也无线程逃逸)的对象,才能被 JIT 执行栈上分配、标量替换的极致优化。

记忆口诀:方法逃逸出方法,线程逃逸跨线程


问:逃逸分析的核心优化收益有哪些?

答:

  1. 栈上分配 + 标量替换:无逃逸对象不进入堆内存,随方法栈帧销毁,完全避免 GC 的回收开销,减少堆内存占用,提升程序执行效率。
  2. 同步消除(锁消除):若逃逸分析判定对象无线程逃逸,不存在线程竞争,会自动消除对象上无用的 synchronized 同步锁,去掉无意义的加锁解锁性能开销。
  3. 标量替换还可进一步触发寄存器优化,减少内存访问次数,进一步提升代码执行速度。

记忆口诀:栈分配免 GC,锁消除提性能


补充说明:

  • 逃逸分析是 JIT 的运行时动态优化,不是 javac 静态编译期的优化;
  • JDK 6u23 及以上版本,HotSpot 虚拟机默认开启逃逸分析(-XX:+DoEscapeAnalysis),同时默认开启标量替换、锁消除优化;
  • 若对象发生逃逸,就无法被栈上分配优化,依然会分配在堆内存中。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐