18

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.

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

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!

2
  • 1
    The basic rule for GC is that if GC'ing an object would affect your program, it doesn't happen. (Unless you're using the specialized tools that care about GC, but if you're using that, you'll know.) Commented May 16, 2013 at 23:39
  • You might want to read about "Midlife Crisis". Commented May 16, 2013 at 23:39

4 Answers 4

20

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.

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Ok thanks! But now I'm confused because two people have different answers. If ObjectVar was a subclass (or inner class) of SomeObject, the above code will make obj1 ineligible for GC?
@baekacaek ZyyaoWei's comment considered only static inner classes, in which case it does not matter indeed. Non-static inner classes and anonymous or named method-local classes can keep the host object from being garbage collected, but static inner classes cannot.
Thanks again for the clarification, and quick replies!
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..

4 Comments

Thanks, does the same apply if ObjectVar is an inner class of SomeObject?
Well that should not matter, since no matter what obj2 has a reference to that object.
If it's a static inner class, it doesn't matter indeed. However, when it's a non-static inner class, var has a "back reference" to the outer class, which may keep the owner alive for longer than one would expect.
@dasblinkenlight Thanks, did not though about that old object.
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.)

Comments

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.

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.

After the 4th line, it looks like this:

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.