如果实例变量仍然有引用,Java GC是否会销毁对象?

时间:2021-12-14 20:06:16

I've read through some of the Java garbage collection guides online, but I'm still a bit unclear and wanted to make sure so that I don't have memory leaks in my code.

我已经在网上阅读了一些Java垃圾收集指南,但我仍然有些不清楚,希望确保代码中没有内存泄漏。

Does Java GC collect objects that lost its reference, but its variables still have reference?

Java GC收集失去引用但其变量仍有引用的对象吗?

So let's say I have SomeObject:

假设我有一个对象

public class SomeObject {
    public ObjectVar var;

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

And my code:

和我的代码:

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

So obj1's var has reference, but obj1 no longer has any reference. So, will the GC destroy obj1, but keep var alive? (I'm assuming so; just wanted to make sure). Thanks!

obj1的var有引用,但obj1不再有引用。那么,GC会破坏obj1,但会保留var吗?(我假设;只是想确定)。谢谢!

4 个解决方案

#1


13  

Here is what is going to happen (see comments below)

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

// 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;

In the end, two objects remain that do not get GCd - obj2 and the former obj1.var which is now referenced as obj2.var.

最后,仍然有两个对象没有得到GCd - obj2和前一个obj1。var现在被引用为obj2。var。

Note: In a special case of ObjectVar class being a non-static inner class of SomeObject, keeping a reference to obj1.var would also keep obj1 around. This is because internally the SomeObject.ObjectVar class has a hidden variable of type SomeObject, which references the outer object of the inner class.

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

#2


3  

Yes of course.

当然是的。

Remember, what you store in the var field is actually reference to the object, not the object itself. So when GC collects obj1, the var object is untouched (must not be touched), especially since it has a reference from obj2, which is still alive and well..

记住,在var字段中存储的实际上是对对象的引用,而不是对象本身。因此,当GC收集obj1时,var对象没有受到影响(不能被碰),特别是因为它有来自obj2的引用,而obj2仍然是活跃的。

#3


0  

Yes - the behaviour is as you describe. The general rule for garbage collection is that objects only become eligible when you cannot reach them through any hard reference. Any objects you can reach this way will thus never be garbage collected (with the exception of soft / weak references.)

是的——行为就像你描述的那样。垃圾收集的一般规则是,对象只有在无法通过任何硬引用访问它们时才有资格使用。因此,可以通过这种方式访问的任何对象都不会被垃圾收集(软/弱引用除外)。

#4


0  

Simply put, if an object is still reachable by a path of references, it is guaranteed to survive collection. If there is no such path, the object can no longer be accessed, and may safely be collected.

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

After the first two lines, the memory looks like this:

在前两行之后,记忆是这样的:

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

All 4 objects can be reached, if a garbage collection were to occur at this time, none of them would be collected.

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

After the 3rd line, it looks like this:

在第三行之后,它是这样的:

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

Now, only 3 objects can be reached; the garbage collector may remove ObjectVar#2.

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

After the 4th line, it looks like this:

在第4行之后,是这样的:

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

Only two objects are still reachable; the garbage collector may remove SomeObj#1 and ObjectVar#2, but must keep SomeObj#2 and ObjectVar#1.

只有两个对象是可访问的;垃圾收集器可以删除SomeObj#1和ObjectVar#2,但必须保留SomeObj#2和ObjectVar#1。

#1


13  

Here is what is going to happen (see comments below)

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

// 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;

In the end, two objects remain that do not get GCd - obj2 and the former obj1.var which is now referenced as obj2.var.

最后,仍然有两个对象没有得到GCd - obj2和前一个obj1。var现在被引用为obj2。var。

Note: In a special case of ObjectVar class being a non-static inner class of SomeObject, keeping a reference to obj1.var would also keep obj1 around. This is because internally the SomeObject.ObjectVar class has a hidden variable of type SomeObject, which references the outer object of the inner class.

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

#2


3  

Yes of course.

当然是的。

Remember, what you store in the var field is actually reference to the object, not the object itself. So when GC collects obj1, the var object is untouched (must not be touched), especially since it has a reference from obj2, which is still alive and well..

记住,在var字段中存储的实际上是对对象的引用,而不是对象本身。因此,当GC收集obj1时,var对象没有受到影响(不能被碰),特别是因为它有来自obj2的引用,而obj2仍然是活跃的。

#3


0  

Yes - the behaviour is as you describe. The general rule for garbage collection is that objects only become eligible when you cannot reach them through any hard reference. Any objects you can reach this way will thus never be garbage collected (with the exception of soft / weak references.)

是的——行为就像你描述的那样。垃圾收集的一般规则是,对象只有在无法通过任何硬引用访问它们时才有资格使用。因此,可以通过这种方式访问的任何对象都不会被垃圾收集(软/弱引用除外)。

#4


0  

Simply put, if an object is still reachable by a path of references, it is guaranteed to survive collection. If there is no such path, the object can no longer be accessed, and may safely be collected.

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

After the first two lines, the memory looks like this:

在前两行之后,记忆是这样的:

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

All 4 objects can be reached, if a garbage collection were to occur at this time, none of them would be collected.

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

After the 3rd line, it looks like this:

在第三行之后,它是这样的:

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

Now, only 3 objects can be reached; the garbage collector may remove ObjectVar#2.

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

After the 4th line, it looks like this:

在第4行之后,是这样的:

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

Only two objects are still reachable; the garbage collector may remove SomeObj#1 and ObjectVar#2, but must keep SomeObj#2 and ObjectVar#1.

只有两个对象是可访问的;垃圾收集器可以删除SomeObj#1和ObjectVar#2,但必须保留SomeObj#2和ObjectVar#1。