Re: Garbage collection problem

From: John C. Bollinger (jobollin_at_indiana.edu)
Date: 03/02/04


Date: Tue, 02 Mar 2004 14:41:14 -0500

dontrango wrote:

> "John C. Bollinger" <jobollin@indiana.edu> wrote in message
> news:c225j9$719$1@hood.uits.indiana.edu...
>
>>dontrango wrote:
>>
>>
>>>I have a garbage collection problem below. After line 15, why would the
>>>object referenced by a is eligible for garbage collection whereas that
>>>referenced by b is not?
>>>
>
>
> 1 class TestA {
> 2 TestB b;
> 3 TestA ( ) { b = new TestB (this); }
> 4 }
> 5
> 6 class TestB {
> 7 TestA a;
> 8 TestB (TestA a) { this.a = a; }
> 9 }
> 10
> 11 class TestAll {
> 12 public static void main (String [ ] args) {
> 13 new TestAll.makeThings ( );
> 14 // ... code
> 15 }
> 16
> 17 void makeThings ( ) { testA test = new TestA ( ); }
> 18 }
>
> here is my thread of thought:
>
> line 13 creates an instance of TestAll class and calls its makeThings
> method, without keeping a reference to it.
> line 17 instantiates a TestA object, calling its constructor. In the
> process, this calls the constructor of class B that sets
> the instance variable of TestB object a to the TestA object.
>
> looks like an island of isolation but not quite; they are instances of
> different classes.
>
> so I disagree with the statement 'After line 15, the object referenced by a
> is eligible for
> garbage collection whereas that referenced by b is not?' since both should
> be eligible ( the current thread has no access to
> both objects ).
>
> What is your opinion on that?

My opinion is that you have judged correctly, at least with regard to
the Java GC model. In Java an object is eligible for GC if it is not
reachable from a live thread via a chain of strong references. In the
example, every TestA instance is paired with a TestB instance such that
each holds a strong reference to the other. Therefore, if one is
strongly reachable then so is the other, and the two always have the
same eligibility for GC. With the precise code above, it would be
possible to break the relationship after construction of the TestA and
TestB instances by directly modifying their instance variables, but no
such thing is actually done. Both instances created during an
invocation of TestAll.makeThings() in fact become eligible for GC as
soon as makeThings() exits.

There are some subtleties involved in determining eligibility for GC in
Java, the most notable being "hidden" local variables. Hidden local
variable arise because Java does not actually have nested local variable
scopes at the VM level -- only at the Java source level. To the VM all
local variables are treated equally. Therefore, a local reference
variable that goes out of scope in the Java sense sticks around until
the method in which it is declared terminates, no matter how long that
may be. Any object it refers to remains strongly reachable until that time.

That there are other GC models where the answer might be a bit
different, perhaps including some in which the problem is not a trick
question. For Java, however, the bottom line answer is "there is no
such reason."

John Bollinger
jobollin@indiana.edu



Relevant Pages