私有字段的垃圾回收

7

给出以下代码。

class A {
    private B b;
    public A() {
        b = new B();
    }
}

class Main {
    public static void main(String[] args) {
        A a = new A(); // two objects are created (a and b)
        // <-- is B object, referenced only by private a.b eligible for garbage collection?
        keepAlive(a);
    }
}

在创建 A 对象后,B 对象可以被垃圾回收吗?
4个回答

7
我认为不行,因为仍然可以通过反射访问此字段(使用setAccessible(true))。
理论上,编译器可以证明此字段永远不会被访问,并且这将使B符合垃圾回收的条件(来自JLS 12.6.1 Implementing Finalization):
“可达对象是任何可以从任何活动线程中的任何潜在持续计算访问的对象。可以设计优化程序的转换,将可达对象的数量减少到比那些被天真地认为是可达的对象更少。例如,编译器或代码生成器可以选择将将不再使用的变量或参数设置为null,以使此类对象的存储更早地可能被回收。”
但我认为在实践中,编译器和JVM并不那么聪明。

1

标准编译器并不那么智能。

class A
{
    private Object[] array;

    public A()
    {
        array = new Object[10000000];
    }
}

public static void main(String[] args)
{
    LinkedList<A> list = new LinkedList<A>();
    while (true)
    {
        list.add(new A());
    }
}

这段代码在很少的循环后就会抛出内存不足异常,因此对于原始问题的答案肯定是否定的。


1
@Kuba 你的意思是:在类A的实例a中字段b中的类B的实例能够被垃圾回收吗?不可以。只要a不为null,b就会被a引用而无法被垃圾回收。

1
不行,因为主线程通过a有一条到b的路径。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接