📌 PDF :大白话说Java面试题 --- 02-JVM篇
第19题:并发标记过程中会出现什么问题
📚 回答:
- 核心概念 :
并发标记是垃圾回收中的一种重要机制,允许用户线程和 GC 线程同时运行。然而,这种并发性会带来两个主要问题:浮动垃圾 和 漏标问题。
1. 浮动垃圾(多标问题)
-
定义:
- 在并发标记过程中,GC 线程标记的对象可能由于用户线程的运行而变成垃圾对象。
- 这些对象无法在本次 GC 中被清理,只能等待下一次 GC 回收,因此被称为"浮动垃圾"。
-
示例说明:
javaclass User { String name; } public class FloatingGarbageDemo { public static void main(String[] args) { User user = new User(); // 对象被创建 // GC 线程标记 user 对象为存活 user = null; // 用户线程将引用置空,user 对象变成垃圾 // 此时 user 对象成为浮动垃圾,无法在本次 GC 中被回收 } } -
影响:
- 浮动垃圾会导致内存利用率降低,但对程序的正确性没有直接影响。
2. 漏标问题
-
定义:
- 漏标是指 GC 线程未能正确标记某些存活对象,导致这些对象被错误地回收。
- 漏标问题通常发生在用户线程修改对象引用关系时,例如:
- 用户线程将一个存活对象从 A 移动到 B。
- 如果 GC 线程只标记了 A 而未标记 B,则 B 中的对象会被错误地回收。
-
解决方法:
-
写屏障(Write Barrier):
- 当用户线程修改对象引用关系时,记录这些变化,确保 GC 线程能够感知到引用关系的变动。
-
重新标记阶段:
- 在并发标记完成后,增加一个短暂的重新标记阶段,修正用户线程对引用关系的修改。
💡 源码解析 :
CMS 和 G1 收集器通过写屏障和重新标记阶段解决了漏标问题。具体逻辑可以参考
ConcurrentMark模块中的相关代码。
-
3. 总结对比
| 问题 | 定义 | 影响 | 解决方法 |
|---|---|---|---|
| 浮动垃圾 | 标记过的对象因用户线程运行变成垃圾 | 内存利用率降低,无程序正确性影响 | 下次 GC 回收 |
| 漏标问题 | 存活对象未被标记,被错误回收 | 程序可能崩溃或数据丢失 | 写屏障 + 重新标记 |
💡 面试官视角:
- 面试官可能会问"如何避免漏标问题?"答:通过写屏障记录引用关系的变化,并在重新标记阶段修正这些变化。
- 面试官可能会追问"浮动垃圾会影响程序性能吗?"答:浮动垃圾会导致内存利用率降低,但不会直接影响程序的正确性。
觉得对您有帮助,麻烦 点点关注啦 ,您的关注是我创作的最大动力~ 🎯