标准答案
- 常见 Roots 包括活动线程栈中的引用、静态字段、JNI 引用和被 JVM 认为活跃的类加载器等。
- 从 Roots 可达的对象暂时不能回收,不可达对象进入回收候选。
- 循环引用如果没有外部 Root 仍可回收,这是可达性分析优于单纯引用计数的原因。
- 软引用、弱引用和虚引用有不同的回收语义,不能当作普通强引用理解。
题目解析
垃圾收集器从 GC Roots 遍历对象图,能从 Roots 到达的强引用对象不能回收;局部变量是否仍是活跃 Root 还受到字节码生命周期和 JIT 优化影响。变量名离开作用域不等于对象立刻回收。
可达性分析能处理循环引用:一组对象即使互相引用,只要没有外部 Root,整体仍可成为回收候选。软、弱、虚引用则提供不同的生命周期协作,不能把它们当作强引用。
判断泄漏要看对象持续存活、引用链和业务生命周期,并结合堆转储多次对比。GC 频繁不一定是泄漏,也可能是正常高分配或缓存策略。
常见误区
- 误区:认为有引用就永远不会回收。改正:区分强引用和特殊引用,并判断是否仍从 GC Roots 可达。
- 误区:认为循环引用一定泄漏。改正:没有外部 Root 的循环对象仍可被可达性分析回收。
- 误区:把弱引用当作普通缓存保护。改正:弱引用可能在 GC 时被清除,缓存必须能处理缺失和重建。