MST

星途 面试题库

面试题:深入理解Java垃圾回收机制中的对象引用与回收判定

在Java垃圾回收机制中,从对象引用类型(强引用、软引用、弱引用、虚引用)的角度,分析对象何时会被判定为可回收对象。当存在复杂对象图结构且对象间存在多种引用关系时,垃圾回收器是如何准确判定哪些对象可以被回收的,结合具体代码示例说明。
47.9万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1. 对象引用类型与可回收判定

  • 强引用(Strong Reference)
    • 只要对象有强引用指向,垃圾回收器永远不会回收它。只有当强引用被释放(例如将引用变量赋值为 null),对象才可能被回收。
    • 示例代码:
Object strongRef = new Object();
// strongRef 指向对象,对象不会被回收
strongRef = null;
// 此时对象失去强引用,可能会被回收
  • 软引用(Soft Reference)
    • 在系统内存充足时,软引用指向的对象不会被回收;当系统内存不足时,垃圾回收器会回收软引用指向的对象。常用于实现对内存敏感的缓存。
    • 示例代码:
SoftReference<Object> softRef = new SoftReference<>(new Object());
Object obj = softRef.get();
if (obj != null) {
    // 使用 obj
} else {
    // 内存不足时,obj 可能已被回收
}
  • 弱引用(Weak Reference)
    • 只要垃圾回收器扫描到弱引用指向的对象,不管当前系统内存是否充足,都会回收该对象。弱引用常被用于解决内存泄漏问题,例如 WeakHashMap
    • 示例代码:
WeakReference<Object> weakRef = new WeakReference<>(new Object());
Object obj = weakRef.get();
// 可能 obj 已经被回收,返回 null
  • 虚引用(Phantom Reference)
    • 虚引用对对象的生命周期没有影响,无法通过虚引用来获取对象实例。设置虚引用的唯一目的是在对象被回收时,收到一个系统通知。常用于对象销毁前的一些资源清理操作。
    • 示例代码:
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);
Object obj = phantomRef.get();
// obj 始终为 null
// 当对象被回收时,虚引用会被放入 ReferenceQueue

2. 复杂对象图结构下垃圾回收判定

  • 在复杂对象图结构中,垃圾回收器使用可达性分析算法。从一系列被称为 “GC Roots” 的对象作为起始点,通过引用关系向下搜索,所走过的路径称为引用链。如果一个对象到 GC Roots 没有任何引用链相连,则证明此对象是不可达的,会被判定为可回收对象。
  • 示例代码:
class Node {
    Node next;
    public Node(Node next) {
        this.next = next;
    }
}
public class ComplexGraph {
    public static void main(String[] args) {
        Node head = new Node(null);
        Node node1 = new Node(null);
        Node node2 = new Node(null);
        head.next = node1;
        node1.next = node2;
        // head 到 node2 有引用链
        head = null;
        // 此时 head 失去引用,若没有其他引用到 head 及其后续节点,这些节点都可能被回收
    }
}

在上述代码中,当 head 被赋值为 null 后,如果没有其他地方持有对 node1node2 的引用,那么从 GC Roots 出发无法到达这些节点,它们就会被判定为可回收对象。垃圾回收器会在合适的时候回收这些对象所占用的内存。