Files
examination/topics/gc-special/gc-deep-dive/true_false.json
T

118 lines
8.2 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"topic": "gc-deep-dive",
"type": "true_false",
"schema_version": "1.0.0",
"generated": "2026-09-03T00:00:00Z",
"questions": [
{
"id": "tf-001",
"type": "true_false",
"difficulty": 2,
"tags": ["gc", "语言对比", "自动内存管理"],
"question": "判断以下陈述是否正确:C/C++ 需要程序员手动分配和释放内存(如 malloc/free 或 new/delete);Rust 并没有采用传统 GC,而是通过所有权(ownership)与借用检查在编译期自动管理内存;而 Go 则依赖自动垃圾回收(GC)。",
"answer": true,
"explanation": "正确。C/C++ 是无 GC 语言,必须手动管理堆内存,容易造成泄漏与悬垂指针。Rust 不属于传统垃圾回收模型,其内存安全由所有权与生命周期系统在编译期保证,运行时并不寄生 GC。Go 则内置了 GC,由运行时负责回收不再使用的堆对象。",
"source": null,
"related": []
},
{
"id": "tf-002",
"type": "true_false",
"difficulty": 1,
"tags": ["gc", "lang", "go"],
"question": "判断以下陈述是否正确:Go 语言和 C/C++ 一样,运行时都没有自动垃圾回收机制,必须由程序员手动调用 free 等接口释放内存。",
"answer": false,
"explanation": "错误。Go 是带 GC 的语言,其 runtime 会自动回收不再引用的堆对象,程序员无需(也无法直接)手动调用 free。C/C++ 才是需要手动管理的。这也是 Go 通常被称为带自动 GC 语言的原因。",
"source": null,
"related": []
},
{
"id": "tf-003",
"type": "true_false",
"difficulty": 2,
"tags": ["gc", "代价", "stop-the-world"],
"question": "判断以下陈述是否正确:启用 GC 会引入运行时代价,包括发生 STW(stop-the-world)暂停、额外约 5%~20% 的内存开销,以及额外的 CPU 开销。",
"answer": true,
"explanation": "正确。GC 的核心代价来自三个方面:1) 标记/整理阶段常需要 STW 暂停用户线程;2) 分代/复制区等机制通常需要额外 5%–20% 左右的堆内存作为缓冲或预留;3) 标记、写屏障与并发更新等日常操作会消耗 CPU。这三项是评估 GC 开销的基本指标。",
"source": null,
"related": []
},
{
"id": "tf-004",
"type": "true_false",
"difficulty": 2,
"tags": ["gc", "mark-sweep", "碎片"],
"question": "判断以下陈述是否正确:标记-清除(Mark-Sweep)算法回收时不会移动存活对象,因此能保持内存紧凑、不会产生内存碎片。",
"answer": false,
"explanation": "错误。标记-清除算法只做标记与回收,并不移动对象,因此存活对象之间的空闲块会零散分布,产生大量内存碎片。这是 Mark-Sweep 的固有缺点,也是它不适合老年代等“大对象存活多”场景的原因;通常需要搭配压缩或内存合并策略来缓解。",
"source": null,
"related": []
},
{
"id": "tf-005",
"type": "true_false",
"difficulty": 4,
"tags": ["gc", "copying", "复制算法", "老年代"],
"question": "判断以下陈述是否正确:复制(Copying)算法即使把存活对象拷贝到另一半空间,其拷贝成本与存活对象数量无关,因此非常适合在老年代等存活率很高的区域使用。",
"answer": false,
"explanation": "错误。Copying 算法需要把存活对象全部复制到另一半空间,复制工作量与存活对象数量成正比。当对象存活率高(如老年代)时,复制开销巨大、几乎每个对象都要被搬移,因此复制算法通常只用于年轻代(存活率低的区域),不适合对象存活率高的老年代(那里多用标记-压缩)。",
"source": null,
"related": []
},
{
"id": "tf-006",
"type": "true_false",
"difficulty": 3,
"tags": ["gc", "mark-compact", "标记-压缩", "碎片"],
"question": "判断以下陈述是否正确:标记-压缩(Mark-Compact)算法在回收的同时移动存活对象使内存紧凑,从而彻底消除碎片,但代价是要移动对象并更新所有引用,因此速度比不移动对象的标记-清除慢。",
"answer": true,
"explanation": "正确。Mark-Compact 在标记存活对象后,将它们紧凑到一端并更新所有指向它们的引用,消除碎片、有利于大对象连续分配。但压缩本身的移动量与引用更新会产生额外开销,所以速度慢于不做移动的 Mark-Sweep。正因如此,压缩算法常用于存活率较高的老年代。",
"source": null,
"related": []
},
{
"id": "tf-007",
"type": "true_false",
"difficulty": 3,
"tags": ["gc", "分代", "minor-gc", "eden"],
"question": "判断以下陈述是否正确:分代收集器中,当年轻代的 Eden 区被填满时会触发 Minor GC,而这类针对年轻代的 Minor GC 通常是一个需要停顿(stop-the-world)的事件。",
"answer": true,
"explanation": "正确。分代 GC 会把新建对象优先分配进 Eden,Eden 满时触发 Minor GC,把仍存活的对象复制到 Survivor 区,超龄后再升入老年代。传统多数实现中,Minor GC 通常是一个 stop-the-world 事件(即使现代收集器如 G1 也会产生暂停),在这段时间内应用线程会被暂停。",
"source": null,
"related": []
},
{
"id": "tf-008",
"type": "true_false",
"difficulty": 3,
"tags": ["gc", "G1", "默认收集器", "region"],
"question": "判断以下陈述是否正确:G1(Garbage-First)自 JDK 8 起就成为 HotSpot 的默认收集器,并把堆划分为多个相同大小的 Region。",
"answer": false,
"explanation": "错误。G1 确实基于 Region 并把堆划分为若干相同大小的 Region,但它直到 JDK 9 才成为 HotSpot 的默认收集器;JDK 8 默认的仍是 Parallel 组合。因此“自 JDK 8 起即是默认”的说法不成立。G1 同时支持通过 -XX:MaxGCPauseMillis 设置可预测的停顿时间目标。",
"source": null,
"related": []
},
{
"id": "tf-009",
"type": "true_false",
"difficulty": 4,
"tags": ["gc", "CMS", "碎片", "concurrent-mode-failure"],
"question": "判断以下陈述是否正确:CMS 采用标记-清除算法因此不会产生内存碎片,也正因如此它不会出现 Concurrent Mode Failure 问题。",
"answer": false,
"explanation": "错误。CMS 正是基于 Mark-Sweep 的收集器,因此会保留内存碎片(碎片过多时后续 Full GC 需要额外的空间整理);同时,当并发标记阶段老年代空间被耗尽时,CMS 会降级回退到 Serial Old 的全量停顿 GC,这称为 Concurrent Mode Failure。因此两个说法都不成立。",
"source": null,
"related": []
},
{
"id": "tf-010",
"type": "true_false",
"difficulty": 5,
"tags": ["gc", "三色标记", "漏标", "GC-Root"],
"question": "判断以下陈述是否正确:在三色标记法中,“漏标”的危害大于“多标”——漏标可能把存活对象误当作死对象回收,从而引发程序崩溃;同时,只有静态变量、JNI 全局引用等根对象出发的可达对象才由 GC Roots 判定存活,而堆中普通对象之间的引用并不是 GC Roots。",
"answer": true,
"explanation": "正确。三色标记把对象分为白/灰/黑三类:白色表示尚未被扫描、可回收;黑色表示已扫描且其所有子对象都处理完毕、安全存活。若因并发或写屏障问题造成漏标,使存活对象仍保持白色,就会在清扫阶段被错误回收,导致程序崩溃,因此漏标比多标更危险(漏标会误回收活对象,而多标至多保留垃圾,不会破坏程序)。而 GC Roots 是堆外能直达堆的出发点,包括静态字段引用、JVM 栈帧(局部变量)持有的对象、JNI 全局引用等;堆中普通对象之间的引用只是对象图的一条边,本身不是 GC Roots。本题两个子命题均正确,故整体正确。",
"source": null,
"related": []
}
]
}