Learner
Learner

Reputation: 1634

How Many Objects Are Eligible For Garbage Collection?

1.  public class Tahiti {
2.      Tahiti t;
3.      public static void main(String[] args) {
4.          Tahiti t = new Tahiti();
5.          Tahiti t2 = t.go(t);
6.          t2 = null;
7.          // more code here
8.      }
9.      Tahiti go(Tahiti t) {
10.         Tahiti t1 = new Tahiti(); Tahiti t2 = new Tahiti();
11.         t1.t = t2; t2.t = t1; t.t = t2;
12.         return t1;
13.     }
14. }

When line 7 is reached, how many objects are eligible for garbage collection?

as per the answer given for this question, there is no object eligible for GC at line 11; but according to me at least one object, t2, which is set to point null at line 6, should be eligible for garbage collection.

Upvotes: 7

Views: 11283

Answers (5)

desaiankitb
desaiankitb

Reputation: 1052

Heap Stack Diagram is the best way to determine which objects are eligible for garbage collection:

Following is the heap stack diagram of above code:

HEAP

1000x: TahitiObj: t:2000x

2000x: TahitiObj: 5000x

3000x: TahitiObj: t: 4000x

4000x: TahitiObj: 5000x

5000x: TahitiObj: t: 6000x

6000x: TahitiObj: 3000x

Stack

Main_Stack

args = null

t = 1000x

t2 = null

Although Go_Stack will be removed from memory after its execution is completed. For completeness I have kept it here.

Go_Stack

t = 1000x

t1 = 3000x

t2 = 5000x

By looking at the Main_Stack and HEAP it can be observed that we can reach to all the objects in either direct or indirect way.

So no object is eligible for garbage collection when code execution reaches line number 7 in side main method.

Upvotes: 0

Oak
Oak

Reputation: 26868

You can just draw a table that maps between lines and the list of access paths pointing to each object immediately after the line, like so:

╔════════════╦═══════════════════════╦════════════════╦═══════════════════╗
║ After Line ║ Pointers to o1        ║ Pointers to o2 ║ Pointers to o3    ║
╠════════════╬═══════════════════════╬════════════════╬═══════════════════╣
║          3 ║ not allocated         ║ not allocated  ║ not allocated     ║
║          4 ║ main:t                ║ not allocated  ║ not allocated     ║
║          9 ║ main:t, go:this, go:t ║ not allocated  ║ not allocated     ║
║         10 ║ main:t, go:this, go:t ║ go:t1          ║ go:t2             ║
║         11 ║ main:t, go:this, go:t ║ go:t1, o3.t    ║ go:t2, o2.t, o1.t ║
║          5 ║ main:t                ║ main:t2, o3.t  ║ o2.t, o1.t        ║
║          6 ║ main:t                ║ o3.t           ║ o2.t, o1.t        ║
╚════════════╩═══════════════════════╩════════════════╩═══════════════════╝

With o1, o2 and o3 being the actual objects getting allocated. It can easily be calculated at every point how many objects can be reclaimed; in this case, after line 6 o1 is accessible from a root, o3 is accessible from o1 and o2 accessible from o3, so no object can be reclaimed.

As a side note, I noticed you wrote "but according to me at least one object, t2, ...". If this is the kind of problems you need to solve, I recommend ditching the habit of naming objects by variables pointing to them; instead give an imaginary id to each object, as I have done above with the o<n>, and treat variables as pointers to those objects instead of their names. That is because, like pointers and unlike names, an object may have more or less than one variables associated with it, and that list of associated variables can change all the time.

Upvotes: 3

Eelke
Eelke

Reputation: 21993

The variable t2 on line 6 is not the only reference to the object. There is a reference from t to the object t2 which was created in the function go which in turn holds a reference to t1 which is the same object that was returned by the function go. So line 6 merely reduces the number of references but there still are live references to the object.

EDIT: Let's try a more elaborate explanation, first I reworked the code a bit to make explaining easier. One statement per line and less confusing variable names + I identified the three relevant objects with the letters A, B and C.

1.  public class Tahiti {
2.      Tahiti u;
3.      public static void main(String[] args) {
4.          Tahiti t = new Tahiti(); // object A
5.          Tahiti t2 = t.go(t);
6.          t2 = null;
7.          // more code here
8.      }
9.      Tahiti go(Tahiti s) {
10.         Tahiti s1 = new Tahiti(); // object B
11.         Tahiti s2 = new Tahiti(); // object C
12.         s1.u = s2;
13.         s2.u = s1;
14.         s.u = s2;
15.         return s1;
16.     }
17. }

On line 4: variable t is initiliazed to reference a new object. Let's call that object itself A (it normally has no name in java but for the sake of this explanation it is easier if it does).

On line 5: t is passed to the function go so we go to line 9

On line 9: the parameter s references the object A which was created on line 4

line 10: initializes variable s1 to point to object B

line 11: initializes variable s2 to refer to object C

line 12: s1.u is set to refer to s2 which means object B gets a reference to C

line 13: s2.u is set to refer to s1 so object C get's a reference to B

line 14: s.u is set to refer s2 which means object A get's a reference to C note that C also has a reference to B so at this point there is a chain from A to B

line 15 return object B and return to line 5

line 5: t2 is set to reference object B (B is now referred to two times once directly by t2 and once because t refers to object A which refers to C which refers to B)

line 6: the reference t2 is set to null so B looses one reference but t is still live which point to A refers to C refers to B

Upvotes: 8

Gnietschow
Gnietschow

Reputation: 3180

At line 5 you're calling the method Tahiti.go(), so the program jumps from line 5 to 10 and reaches 11 for 6.

Upvotes: 2

someone
someone

Reputation: 6572

line number 11 execute before line number 6

Upvotes: 1

Related Questions