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

4 回答 4

7

我认为不可以,因为仍然可以通过反射(使用setAccessible(true))访问该字段。

从理论上讲,编译器可以证明该字段永远不会被访问,并且可以B进行垃圾回收(来自JLS 12.6.1 实现终结):

可达对象是可以从任何活动线程的任何潜在持续计算中访问的任何对象。可以设计优化程序的转换,将可到达的对象的数量减少到比那些天真地认为是可到达的要少。例如,编译器或代码生成器可能会选择将不再使用的变量或参数设置为 null,以使此类对象的存储空间可能更快地被回收。

但我认为实际上编译器和 JVM 并不那么聪明

于 2012-09-28T08:17:22.587 回答
1

@Kuba您的意思是:类实例B字段中的类b实例可以被垃圾收集吗?不,不是 while不是由引用的。aAanullba

于 2012-09-28T08:19:45.457 回答
1

不,因为主线程有一条路径bthrough a

于 2012-09-28T08:20:15.987 回答
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());
    }
}

这段代码在极少数循环后抛出内存不足异常,所以原问题的答案肯定是否定的。

于 2012-09-28T08:27:00.773 回答