我已经在线阅读了一些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存活吗? (我假设是这样;只是想确定)。谢谢!
答案 0 :(得分:16)
以下是将要发生的事情(见下面的评论)
// 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
。
注意:在ObjectVar
类是SomeObject
的非静态内部类的特殊情况下,保留对obj1.var
的引用也会保留obj1
。这是因为SomeObject.ObjectVar
类内部有一个类型为SomeObject
的隐藏变量,它引用了内部类的外部对象。
答案 1 :(得分:3)
当然可以。
请记住,您在var
字段中存储的内容实际上是对象的引用,而不是对象本身。因此,当GC收集obj1
时,var
对象不受影响(不得触及),尤其是因为它有来自obj2
的引用,它仍然存在好吧..
答案 2 :(得分:0)
是 - 行为如您所述。垃圾收集的一般规则是,只有当您无法通过任何硬引用访问它们时,对象才有资格。因此,您可以通过这种方式访问的任何对象都不会被垃圾回收(软/弱引用除外。)
答案 3 :(得分: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。