题目
解释Java中对象何时会被垃圾回收?
信息
- 类型:问答
- 难度:⭐
考点
垃圾回收条件,可达性分析,GC Roots
快速回答
Java对象在满足以下条件时会被垃圾回收:
- 对象不再被任何强引用关联
- 从GC Roots出发无法访问到该对象
- 即使存在循环引用,只要整体不可达也会被回收
注意:调用System.gc()仅建议JVM回收,不保证立即执行。
解析
原理说明
Java垃圾回收的核心是可达性分析算法:从GC Roots对象作为起点,通过引用链遍历所有存活对象。未被遍历到的对象判定为可回收。GC Roots包括:
- 虚拟机栈中引用的对象(当前方法局部变量)
- 方法区中静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI引用的对象
代码示例
public class GCDemo {
public static void main(String[] args) {
// 对象obj1和obj2相互引用
Object obj1 = new Object();
Object obj2 = new Object();
obj1 = obj2;
obj2 = obj1;
// 切断外部引用
obj1 = null;
obj2 = null;
// 此时两个对象虽循环引用,但已不可达
System.gc(); // 建议JVM执行GC(实际回收时机不确定)
}
}此代码演示:即使obj1和obj2存在循环引用,当切断它们与GC Roots的连接后,仍会被回收。
最佳实践
- 及时置空引用:对不再使用的大对象显式赋
null(如集合对象) - 避免使用finalize():该方法可能导致对象复活且执行时机不确定
- 谨慎使用System.gc():多数场景无需手动触发,可能引发性能问题
常见错误
- 误认为循环引用会导致内存泄漏(Java可达性分析可正确处理)
- 过度依赖
System.gc()强制回收(实际由JVM决定执行时机) - 在finalize()中复活对象导致不可预测行为
扩展知识
- 引用类型:除强引用外,还有软引用(内存不足时回收)、弱引用(下次GC时回收)、虚引用(用于跟踪回收状态)
- 垃圾回收器:Serial、Parallel、CMS、G1等不同实现,适用于不同场景
- 触发条件:当新生代(Eden区)满时触发Minor GC,老年代满时触发Full GC