16

我已经在线阅读了一些 Java 垃圾收集指南,但我仍然有点不清楚,并想确保我的代码中没有内存泄漏。

Java GC 是否收集丢失了引用的对象,但它的变量仍然有引用?

所以假设我有 SomeObject:

public class SomeObject {
    public ObjectVar var;

    public SomeObject() {
        var = new ObjectVar();
    }
}

我的代码:

SomeObject obj1 = new SomeObject();
SomeObject obj2 = new SomeObject();
obj2.var = obj1.var;
obj1 = null;

所以 obj1 的 var 有引用,但是 obj1 不再有任何引用。那么,GC 会破坏 obj1,但保持 var 存活吗?(我假设是这样;只是想确定一下)。谢谢!

4

4 回答 4

18

这是将要发生的事情(请参阅下面的评论)

// obj1 and obj1.var get created
SomeObject obj1 = new SomeObject();
// obj2 and obj2.var get created
SomeObject obj2 = new SomeObject();
// old obj2.var becomes eligible for GC
obj2.var = obj1.var;
// obj1 becomes eligible for GC
obj1 = null;

最后,剩下的两个对象没有得到 GCd -obj2前者obj1.var现在被引用为obj2.var.

注意:在ObjectVarclass 是 的非静态内部类的特殊情况下SomeObject,保留对的引用obj1.var也会保留obj1。这是因为SomeObject.ObjectVar该类内部有一个类型为隐藏的变量SomeObject,它引用了内部类的外部对象。

于 2013-05-16T23:37:35.663 回答
3

是的当然。

请记住,您在var字段中存储的内容实际上是对对象的引用,而不是对象本身。因此,当 GC 收集时obj1var对象未被触及(不得被触及),特别是因为它有来自 的引用obj2,它仍然存在并且很好。

于 2013-05-16T23:33:37.140 回答
0

是的 - 行为如您所描述。垃圾回收的一般规则是,只有当您无法通过任何硬引用访问它们时,对象才符合条件。因此,您可以通过这种方式访问​​的任何对象都不会被垃圾收集(软/弱引用除外。)

于 2013-05-16T23:38:46.590 回答
0

简单地说,如果一个对象仍然可以通过引用路径到达,那么它就可以保证在集合中存活下来。如果没有这样的路径,则无法再访问该对象,并且可以安全地收集该对象。

在前两行之后,内存如下所示:

o1  --> SomeObj#1 --> ObjectVar#1
o2  --> SomeObj#2 --> ObjectVar#2

可以到达所有 4 个对象,如果此时发生垃圾收集,则不会收集它们。

在第 3 行之后,它看起来像这样:

o1  --> SomeObj#1 --> ObjectVar#1
                      ^
o2  --> SomeObj#2 -----    ObjectVar#2

现在,只能到达 3 个对象;垃圾收集器可能会删除 ObjectVar#2。

在第 4 行之后,它看起来像这样:

o1      SomeObj#1 --> ObjectVar#1
                      ^
o2  --> SomeObj#2 -----   ObjectVar#2

只有两个对象仍然可以到达;垃圾收集器可以删除 SomeObj#1 和 ObjectVar#2,但必须保留 SomeObj#2 和 ObjectVar#1。

于 2013-05-16T23:51:55.590 回答