JVM 内存结构与垃圾回收

共 57 题
#

1. CMS GC 在 JDK 14 被完全移除后遗留项目的迁移路径与 G1/ZGC 的替代方案

A 迁移时应先移除 CMS 专属参数,再按业务停顿模型选择 G1 或 ZGC,并用压测验证 ✓ 正确答案
B CMS 在 JDK 14 被移除后,JDK 8 项目只能继续绑定旧版本,无法迁移
C ZGC 与 G1 的停顿模型完全相同,选哪个都可以
D 迁移只需要替换收集器参数,其余参数无需调整
#

2. CMS GC 的工作流程与问题(碎片、浮动垃圾)

A CMS 的浮动垃圾无法由本次 GC 回收,不整理内存会产生碎片,失败时退回 Serial 兜底 ✓ 正确答案
B CMS 并发阶段不会产生任何新垃圾
C CMS 采用标记-整理算法,能彻底消除内存碎片
D CMS 不需要预留空间,可以在堆满时才开始回收
#

3. Epsilon GC(No-Op GC)的测试价值

A Epsilon GC 会正常回收堆内存,适合生产环境
B Epsilon GC 是 JDK 8 的默认收集器
C Epsilon GC 只分配不回收,堆满即 OOM,用于测试中隔离 GC 开销和评估分配压力 ✓ 正确答案
D Epsilon GC 比 CMS 停顿更短,因此适合低延迟生产系统
#

4. Epsilon GC(No-Op GC,JEP 318)在性能测试与短生命周期应用的适用边界

A 适合所有长期运行的服务,因为零 GC 开销
B 适合性能测试与分配量确定且小于堆上限的短生命周期应用,堆满会 OOM,不适合长期服务 ✓ 正确答案
C 一旦堆满会自动退回 G1 继续回收
D 只能用于 JDK 8 及以下版本
#

5. 堆外内存(Direct Memory)不在 GC 管辖范围内,为何仍会出现 Direct Buffer OOM 及如何配合 MaxDirectMemorySize 治理

A 堆外内存不受任何限制,永远不会 OOM
B 设置 MaxDirectMemorySize 后 GC 会自动回收堆外内存
C DirectBuffer 的底层内存由 GC 直接回收,无需关注引用释放
D 累计分配超过 MaxDirectMemorySize 时会 OOM,需配合及时释放与 NMT 监控治理 ✓ 正确答案
#

6. Full GC 的危害与排查路径

A Full GC 只发生在新生代,停顿很短
B 只要调大 -Xmx 就一定能解决所有 Full GC
C Full GC 会造成全局 STW 停顿,需结合 GC 日志、堆 dump 与 MAT 定位根因 ✓ 正确答案
D Full GC 与内存泄漏无关,只与堆大小有关
#

7. G1 GC 的 Mixed GC 与并发标记(Concurrent Mark)

A 并发标记找出可回收的老年代 Region,Mixed GC 分批回收新生代与这些 Region,实现可预测停顿 ✓ 正确答案
B G1 的并发标记与 CMS 完全不同,不采用 SATB
C Mixed GC 一次性回收全部老年代,停顿最长
D Mixed GC 只回收新生代,不涉及老年代
#

8. G1 GC 的 Region 模型与 Mixed GC

A G1 用固定大小 Region 划分新生代与老年代,Mixed GC 回收新生代与存活率低的老年代 Region,配合 RSet 支持局部回收 ✓ 正确答案
B G1 将堆划分为固定大小的 Region,Region 无需记录跨区引用
C G1 的 Region 大小固定为 1MB,不可调整
D G1 没有 Humongous 专门区域,大对象直接进老年代
#

9. G1 中 Humongous 对象如何判定与分配(超过 Region 一半),它对 Mixed GC 与内存碎片有什么特殊影响

A Humongous 对象会正常参与 Eden 晋升,不影响碎片
B Humongous 对象大小小于 Region 一半
C 超过 Region 一半大小的对象被判为 Humongous,直接分配到连续 Region 且绕过正常晋升,易造成碎片 ✓ 正确答案
D Humongous 对象能被 Young GC 正常回收
#

10. G1 回收 Humongous 对象依赖什么时机,为何频繁产生大对象会加速堆耗尽并触发 Full GC

A Humongous 对象在 Young GC 中即可被回收
B Humongous 对象不占 Region,对堆无影响
C 大对象会自动被整理压缩,不会产生碎片
D 大对象直接进老年代、依赖并发标记回收且需连续 Region,频繁产生会加速堆耗尽并触发 Full GC ✓ 正确答案
#

11. G1 的 MaxGCPauseMillis 与 -XX:InitiatingHeapOccupancyPercent

A MaxGCPauseMillis 是硬性停顿保证,IHOP 控制新生代大小
B IHOP 与 MaxGCPauseMillis 完全无关
C IHOP 决定何时触发并发标记,MaxGCPauseMillis 决定停顿目标,两者共同决定 G1 的回收节奏 ✓ 正确答案
D 设置的停顿目标越小,吞吐越高,无需权衡
#

12. GC 日志解读(GC 原因、暂停时间、内存变化)

A JDK 9+ 与 JDK 8 的 GC 日志格式完全相同
B GC 日志中的内存变化只反映堆大小,与泄漏无关
C 通过 GC 原因、暂停时间与各代内存占用变化,可判断是否泄漏、分配过快或停顿超目标 ✓ 正确答案
D GC 日志无法看到触发原因
#

13. GC 的基本算法(标记-清除、标记-整理、复制、分代)

A 复制算法适合存活率高的老年代
B 标记-清除不会产生碎片
C 标记-整理会移动存活对象消除碎片,但需更新引用,成本高 ✓ 正确答案
D 分代收集只用一种算法处理所有对象
#

14. GC 算法在容器/cgroup 下的内存算账

A 堆外内存不计入 -Xmx,但受 cgroup 总限制,需显式治理各项并预留余量,否则可能被 OOM-Kill ✓ 正确答案
B JDK 8 无法识别 cgroup,任何版本都无能为力
C -Xmx 就是容器可利用的全部内存
D 容器内无需设置 -XX:MaxMetaspaceSize
#

15. GC 调优的 -Xmx/-Xms 设置与堆外内存(Off-Heap)的综合考量

A 堆外内存占用 -Xmx 的配额,无需单独治理
B 生产宜将 -Xms 与 -Xmx 设为相同值,并综合考虑堆外、元空间等,避免总内存超限 ✓ 正确答案
C 堆外内存永远不占物理内存
D -Xmx 设得越大越好,堆外无关紧要
#

16. GC 调优的通用思路(减少分配、增大堆、调触发阈值)

A 先减少对象分配,再考虑增大堆与调整触发阈值,以 GC 日志为依据迭代 ✓ 正确答案
B 调优应优先增大堆,代码优化无关紧要
C 一次修改多个参数能更快找到最优解
D 触发阈值无需调整,总是默认值最好
#

17. JDK 9+ 的 -Xlog:gc* 统一日志如何替代 JDK 8 的 -XX:+PrintGCDetails 等参数,迁移时标签与输出文件如何对应

A 统一日志用标签选择器 + 输出 + 装饰器组织,可细粒度控制,并映射到 JDK 8 的旧参数 ✓ 正确答案
B -Xlog:gc* 与 JDK 8 的 PrintGCDetails 完全等价,标签无意义
C 统一日志只能输出到 stdout,不支持文件
D JDK 9+ 已完全移除 GC 日志能力
#

18. JEP 439 Generational ZGC 与 JEP 404 Generational Shenandoah 在 JDK 21/25 中如何根据业务延迟特征选型,弱代假说验证如何反映在分代模式

A 分代模式会显著增加暂停时间,不适合低延迟场景
B 两者都利用弱代假说,分代管理新生代与老年代,选型需结合延迟特征、堆规模与开销权衡 ✓ 正确答案
C 弱代假说只适用于 G1,与 ZGC/Shenandoah 无关
D Generational Shenandoah 在 JDK 21 就已转正为默认
#

19. JEP 514/515 AOT Command Line Ergonomics 与 GC 关联

A 它让 JVM 在选项较少时自动选择更协调的合理默认值,包括 GC 参数,减少误配 ✓ 正确答案
B 它与 GC 完全无关,只影响编译
C 它只影响 JDK 8 的旧参数
D 它要求用户必须显式指定所有 GC 参数
#

20. JVM 内存溢出(OOM)的分类(堆/栈/方法区)

A 堆 OOM 由无限递归引起,栈 OOM 由内存泄漏引起
B 堆 OOM 看对象与泄漏,栈溢出看递归/线程数,Metaspace OOM 看类加载器泄漏,需分别定位 ✓ 正确答案
C 所有 OOM 根因相同,用同一工具即可
D Metaspace OOM 与类加载器无关
#

21. JVM 安全点(Safepoint)与 GC 暂停

A GC 会抢占式中断线程,无需等待 Safepoint
B 线程在安全点指令上通过轮询进入 Safepoint,GC 暂停依赖所有线程到达 Safepoint ✓ 正确答案
C Safepoint 只用于 JIT 编译,与 GC 无关
D 线程无需到达 Safepoint 即可被 GC 扫描
#

22. JVM 运行时数据区(PC、栈、堆、方法区、直接内存)

A 堆与方法区是线程私有的
B 直接内存归 GC 管理,由 -Xmx 限制
C 方法区与堆完全相同,都是存放对象
D PC、虚拟机栈、本地方法栈是线程私有,堆与方法区是线程共享,直接内存为堆外 ✓ 正确答案
#

23. Java 堆(Young/Old)与分代假设

A 分代假设认为大多数对象存活时间很长
B 新生代与老年代完全无区别
C 弱代假说认为大多数对象朝生夕死,新生代用复制算法、老年代用整理算法,兼顾效率与空间 ✓ 正确答案
D 分代假设只适用于 CMS,不适用于 G1
#

24. Parallel GC 适用场景(吞吐优先)

A Parallel GC 的目标是亚毫秒停顿
B Parallel GC 是单线程回收,适合低延迟
C Parallel GC 多线程并行、吞吐优先,适合对延迟不敏感的计算密集型场景,单次停顿可能较长 ✓ 正确答案
D Parallel GC 是 JDK 21 的默认收集器
#

25. TLAB 与堆分配路径的协作,大对象绕过 TLAB 直接进入老年代的条件与影响

A 大对象总是先分配进 TLAB,再复制到老年代
B TLAB 是全局共享的分配缓冲
C 大对象可能绕过 TLAB 直接进老年代,虽省复制成本但易造成老年代碎片与膨胀 ✓ 正确答案
D 大对象直进老年代没有负面影响
#

26. G1 的 Young GC 与 Mixed GC 触发阈值如何由 IHOP 与停顿目标共同决定

A Young GC 由 IHOP 触发,Mixed GC 由 Eden 打满触发
B Mixed GC 与停顿目标无关
C IHOP 只影响 Young GC
D Young GC 由 Eden 不足触发,Mixed GC 由 IHOP 触发标记、停顿目标决定回收节奏 ✓ 正确答案
#

27. GC Roots 的枚举范围(栈、静态、JNI、活跃线程)如何决定可达性分析的起点与耗时

A GC Roots 只包括堆上的对象
B GC Roots 与可达性分析无关
C 根枚举永远不需要 STW
D GC Roots 包括栈、静态字段、JNI 与活跃线程等引用起点,其数量与引用链复杂度影响根枚举耗时 ✓ 正确答案
#

28. Shenandoah GC 的 Brooks 指针与并发整理

A Brooks 指针只用于标记,不参与整理
B Shenandoah 使用染色指针,与 Brooks 指针无关
C Brooks 指针用于记录对象移动后的位置,配合读屏障实现并发整理,对应用透明 ✓ 正确答案
D Shenandoah 并发整理必须 STW
#

29. System.gc() 的建议禁用与 -XX:+DisableExplicitGC

A System.gc() 只会触发 Minor GC,无停顿风险
B System.gc() 会触发 Full GC 造成停顿,生产环境宜用 -XX:+DisableExplicitGC 禁用 ✓ 正确答案
C 禁用后无法回收任何对象
D DisableExplicitGC 只影响 G1,不影响其他收集器
#

30. TLAB(Thread Local Allocation Buffer)

A TLAB 是全局共享的,需加锁访问
B TLAB 只用于老年代分配
C TLAB 与 GC 无关
D TLAB 为每个线程分配 Eden 私有缓冲,降低分配竞争,剩余空间不足时按策略处理 ✓ 正确答案
#

31. Metaspace 内存回收与类加载器泄漏的关系,动态生成类为何会导致元空间持续增长

A Metaspace 回收单个类,与类加载器无关
B Metaspace 以类加载器为回收单元,只有类加载器不可达其类才可卸载,动态生成类不释放会致元空间增长 ✓ 正确答案
C 设置 MaxMetaspaceSize 后元空间永不会增长
D 动态生成类不占用元空间
#

32. Young GC 与 Full GC 的触发条件

A Young GC 由 Eden 不足触发,Full GC 由老年代/Metaspace 不足、显式 gc 或晋升失败等触发 ✓ 正确答案
B Young GC 由老年代不足触发,Full GC 由 Eden 不足触发
C 两者触发条件完全相同
D Full GC 只回收新生代
#

33. ZGC 在 JDK 21+ 的分代模式下,转发表与内存多重映射的开销相比非分代模式如何变化

A 分代模式完全移除了转发表与多重映射
B 分代模式通过切分新生代与老年代减少重复扫描,使转发表与多重映射的整体开销更低,同时保持亚毫秒暂停 ✓ 正确答案
C 分代模式显著增加暂停时间
D 分代模式与弱代假说无关
#

34. ZGC 的 Sub-millisecond 暂停实现

A ZGC 暂停时间与堆大小成正比
B ZGC 需要每次 GC 全量 STW
C ZGC 用染色指针 + 读屏障实现并发标记与整理,STW 只做极小根操作,暂停与堆大小解耦 ✓ 正确答案
D ZGC 暂停时间随 GC 频率增长
#

35. ZGC 的染色指针与并发标记

A ZGC 必须锁定对象才能并发标记
B 染色指针与对象地址对齐无关
C ZGC 并发标记需要 STW
D 染色指针把标记信息编码进指针高位,配合读屏障自愈实现并发标记 ✓ 正确答案
#

36. ZGC 的染色指针与转发表(forwarding table)如何实现并发整理,多重映射会带来怎样的堆外内存开销

A 多重映射使物理内存占用翻倍
B ZGC 通过转发表记录新地址,读屏障自愈实现并发整理,多重映射主要增加虚拟地址空间与页表开销 ✓ 正确答案
C ZGC 并发整理必须 STW
D 转发表只在 Full GC 使用
#

37. jstat -gc 与 jcmd GC.heap_info 的关键指标

A 两者输出完全相同
B jstat -gc 提供空间与 GC 计数的时间序列,jcmd GC.heap_info 提供细粒度堆快照,两者结合可诊断分配与泄漏 ✓ 正确答案
C jcmd 无法查看堆信息
D jstat -gc 只能看 CPU,与内存无关
#

38. 分代收集中分配担保(HandlePromotionFailure)机制如何在晋升失败时触发 Full GC,JDK 8 前后规则有何变化

A 晋升失败时 JVM 直接忽略,不影响后续
B 分配担保只影响字符串
C 晋升需要老年代空间足够容纳存活对象,不足则触发 Full GC,JDK 8 后规则趋向简化 ✓ 正确答案
D JDK 8 前后规则完全一样
#

39. 对象在堆中的内存布局(对象头、实例数据、对齐填充)

A 对象只包含实例数据,无对象头
B 对象由对象头(Mark Word + Klass Pointer)、实例数据、对齐填充组成,对齐为寻址与压缩指针服务 ✓ 正确答案
C 对象头只存哈希码
D 对齐填充是纯浪费,可完全移除
#

40. G1 与 ZGC 的停顿模型差异,什么场景下 ZGC 的收益最大?

A 两者停顿都随堆大小线性增长
B G1 停顿随堆增长,ZGC 停顿与堆大小解耦,ZGC 在大堆 + 对延迟敏感场景收益最大 ✓ 正确答案
C ZGC 只适合小堆
D G1 停顿总是比 ZGC 更短
#

41. 分代 GC 如何用卡表(Card Table)与记忆集(Remembered Set)记录跨代引用,写屏障(Write Barrier)在对象引用变更时如何标记脏卡,G1 的 Refinement 线程又如何把脏卡合并进 RSet 并用于 Young GC 根扫描

A Minor GC 必须全堆扫描老年代找跨代引用
B RSet 不参与 Young GC 根扫描
C 卡表由 GC 线程在回收时全量重建
D 写屏障在引用变更时标记脏卡,G1 的 Refinement 线程把脏卡合并进 RSet,Young GC 根扫描据此定位老年代跨代引用 ✓ 正确答案
#

42. 三色标记(Tri-color Marking)中黑/灰/白对象的判定标准是什么,并发标记阶段应用线程修改引用为何会产生漏标,CMS 的增量更新(Incremental Update)与 G1 的 SATB 分别通过拦截新增还是删除引用来修补

A 黑色对象永远不再被扫描,无需处理
B 三色标记不需要区分黑白灰
C CMS 的增量更新拦截新增引用(黑变灰),G1 的 SATB 拦截删除引用保留旧引用,避免漏标 ✓ 正确答案
D SATB 与增量更新完全相同
#

43. CompressedClassPointers 与元空间关系

A 压缩类指针与元空间完全无关
B 压缩类指针只影响字符串
C 压缩类指针会扩大对象头
D 压缩类指针指对象头指向类元数据的指针,依赖元空间紧凑地址空间,减少对象头占用 ✓ 正确答案
#

44. G1 的 SATB(Snapshot At The Beginning)

A SATB 与增量更新完全相同
B SATB 拦截新增引用
C SATB 记录并发开始时的引用快照,保留被删除引用的对象,防止漏标 ✓ 正确答案
D SATB 不用于并发标记
#

45. JEP 516 AOT Object Caching with Any GC(JDK 26)

A 它只与 ZGC 兼容
B 它禁止对象被 GC 回收
C 它只优化运行期吞吐
D 它缓存 AOT 加载的对象图以加快启动,并兼容任意 GC,不牺牲运行期 GC 功能 ✓ 正确答案
#

46. JEP 522 G1 GC Throughput Improvement(JDK 26)

A 它通过优化 G1 回收内部开销提升吞吐,同时维持可预测停顿 ✓ 正确答案
B 它只影响 ZGC
C 它让 G1 彻底放弃分代
D 它会显著增加停顿时间
#

47. Shenandoah GC(OpenJDK)在 JDK 25 中与 ZGC 的低暂停时间对比

A Shenandoah 用 Brooks 指针、ZGC 用染色指针,都是低暂停,选型看堆规模、暂停目标与内存开销 ✓ 正确答案
B ZGC 暂停随堆增长,Shenandoah 与堆解耦
C Shenandoah 无法并发整理
D 两者实现机制完全相同
#

48. UseStringDeduplication 在 G1 中的实现

A 它能修改字符串内容
B 它适用于所有 GC,包括 Serial
C 它会把不同内容的字符串合并
D 它是 G1 特有的字符串去重特性,通过共享相同的 char[] 减少重复字符串内存占用 ✓ 正确答案
#

49. 内存泄漏与内存溢出的诊断(MAT、LeakCanary)

A 内存泄漏与内存溢出是同一回事
B 泄漏无法通过堆 dump 分析
C MAT 用支配树与 GC Roots 路径分析堆 dump 定位泄漏,LeakCanary 自动检测 Android 生命周期对象泄漏 ✓ 正确答案
D 只需调大堆即可解决泄漏
#

50. 分代 Shenandoah 的内存收益与吞吐影响

A 分代会增加全堆扫描,降低吞吐
B 分代与单代完全一样
C 分代 Shenandoah 无法低暂停
D 分代 Shenandoah 利用弱代假说聚焦新生代回收,减少全堆扫描,内存与吞吐通常优于单代 ✓ 正确答案
#

51. 对象晋升阈值(-XX:MaxTenuringThreshold)与动态年龄判定的机制?

A 晋升只由静态阈值决定,无动态机制
B 对象年龄在 Full GC 期间递增
C 对象达到 MaxTenuringThreshold 年龄后晋升,且 JVM 还会根据 Survivor 空间比例动态提前晋升 ✓ 正确答案
D 动态判定与 Survivor 空间无关
#

52. 如何用 JDK Flight Recorder + Async Profiler 定位 CPU 高与 GC 频繁问题?

A JFR 无法采集 GC 事件
B 两者只用于查看 GC,无法定位 CPU
C Async Profiler 提供 CPU 火焰图,JFR 提供 GC 与分配事件,结合可区分应用 CPU 高与 GC 频繁并归因到热点 ✓ 正确答案
D 只能选其一,不能结合
#

53. 虚拟线程批量创建对 GC 的影响,栈块(StackChunk)缓存与堆占用

A 虚拟线程栈块在堆中,通过 StackChunk 缓存复用降低分配,但海量存活虚拟线程仍增加堆占用 ✓ 正确答案
B 虚拟线程不在堆中占空间
C 虚拟线程栈固定且不可复用以避免 GC
D 虚拟线程与 GC 完全无关
#

54. JDK 25 的 GC 演进全景(JEP 521 Generational Shenandoah 转正)

A JDK 25 移除了 G1
B Shenandoah 仍为实验性
C JEP 521 让 Generational Shenandoah 转正,与 ZGC/G1 一样分代化,低延迟收集器普遍采用分代 ✓ 正确答案
D 分代会显著增加暂停
#

55. 对象晋升(Promotion)与年龄阈值

A 对象只在 Eden 分配,永不晋升
B 对象在新生代创建后,每次 Minor GC 存活则年龄 +1,达到阈值或在 Survivor 空间紧张时晋升老年代 ✓ 正确答案
C 晋升只发生在 Full GC
D 年龄阈值与晋升无关
#

56. JDK 25 中 jcmd GC.heap_dump 与 JFR 事件 jdk.GCPhase 的诊断价值

A GC.heap_dump 只能看元空间
B 两者都只输出 CPU 信息
C jdk.GCPhase 无法记录阶段耗时
D GC.heap_dump 看堆内容,jdk.GCPhase 看 GC 各阶段耗时,两者配合可定位内存与 GC 根因 ✓ 正确答案
#

57. 堆外内存(DirectBuffer)的回收机制与常见泄漏排查方法?

A DirectBuffer 底层内存由 GC 直接释放,无需 Cleaner
B DirectBuffer 永不释放底层内存
C DirectBuffer 在堆引用被回收时通过 Cleaner 释放底层内存,泄漏常源于引用未释放,可用 NMT 排查 ✓ 正确答案
D NMT 与堆外内存无关