• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

GC: WATCH OUUUUUTTT -- Examples

 
Ranch Hand
Posts: 154
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is in response to the "GC: WATCH OUUUUUTTT" thread that Alfred had started. I agree with alfred that there were questions in the exam where re-wording is very much desirable.
Kathy had yet again given a beautiful explanation in this post, like her previous posts. I just thought of giving examples by quoting some statements from Kathy's response. This is just my way of saying thanks to this marvellous site - especially to Valentin, Thomas, Jim and Kathy.
Please ignore the optimizations of the compiler in these methods (I learnt that the latest compiler doesn't even create the objects in the methods if it determines that the objects are not used).


Originally posted by Kathy Sierra:
We have two ways to know an object is no longer referenced:
1) The reference is deliberately nulled or reassigned, and it is the only live reference (i.e. reachable from a live thread)


Consider the following method
1.void method() {
2.List list1 = new ArrayList();
3.List list2 = new Vector();
4.list1 = null; // nulled
5.list2 = new Stack(); // reassigned
6.} // end of scope
The object referenced by variable 'list1' is eligible for GC at the end of line 4. This is because the reference is explictly set to null. Therefore there is no reference to the object created on line 2 and is thus eligible for GC after line 4.
The object referenced by variable 'list2' created on line 3 is eligible for GC at the end of line 5. This is because the reference is explictly re-assigned to another object on line 5. Therefore there is no reference to the object created on line 3 and is thus eligible for GC after line 5.


Originally posted by Kathy Sierra:
We have two ways to know an object is no longer referenced:
2) The reference goes out of scope.


Considering the same code snippet,
The java.util.Stack object created on line 5 and referenced by variable list2 goes out of scope at the end of the method (i.e., after line 6). Therefore, this object is eligible for GC only after the method completes execution.
How to verify this? use "javap -c" ...


To understand the opcodes shown, remember that every method has a local variable stack and a java stack (I think this is also calles an operand stack). Local variable stack is used to pass the arguments to the method and also the implicit reference to the object itself ('this') at position 0 of the stack.
For a good explanation about the opcodes, read this article about byte code basics
astore_<pos> - pops an object reference from the java stack to the local variable stack at position <pos>.

- "7 astore_1" => pop & store the ArrayList object reference at position 1 of the local variable stack
- "15 astore_2" => pop & store the Vector object reference at position 2 of the local variable stack
- "16 aconst_null" => pushes a null object reference onto to the stack
- "17 astore_1" => pop & store the store the null object reference at position 1 of the local variable stack - NULLED. Therefore line1 object is eligible for GC.
- "25 astore_2" => pop & store the java.util.Stack object reference at position 2 of the local variable stack - REASSIGNED. Therefore line2 object is eligible for GC.
- "26 return" => end of the method - therefore the line5 java.util.Stack object goes out of scope and is therefore eligible for GC.

-----------------------------------------------------------------------------------------------------------


Originally quoted by Kathy Sierra:
Again, you ARE expected to know when, in a method, objects become eligible, but NOT because the reference went out of scope "early",...


Therefore the above example sums up the requirements for the SCJP exam. The below is just a continuation of the discussion not required for the exam.
There was discussion in another thread about a code snippet that went something like this ...

How many objects are eligible for GC at the end of line 5? Ans: 10
How? The objects created and referenced by the local variable myList are no longer in scope. so Why not 11?
Again, javap -c gives the following output...

Method void method()
0 bipush 10
2 istore_1
3 goto 17
6 new #2 <Class java.util.ArrayList>
9 dup
10 invokespecial #3 <Method java.util.ArrayList()>
13 astore_2 // store the object ref. at pos 2 on local variable stack
14 iinc 1 -1
17 iload_1
18 ifge 6
21 getstatic #4 <Field java.io.PrintStream out>
24 ldc #5 <String "end of method">
26 invokevirtual #6 <Method void println(java.lang.String)>
29 return

Between instructions 6 and 18 of the opcodes, 11 objects are created. All the objects created are referenced at position 2 on the local variable stack.
Therefore, at the end of the for loop, there is still a live reference to the last object created on the local variable stack. This reference exists even after the end of the print statement - therefore answer is 10.
Had the question been stated as follows - How many objects are eligible for GC at the end of method call? Ans: 11
The local variable stack gets destroyed after the method call returns and therefore the last object created too is eligible for GC.
Now, what happens if you modify the code a little bit? Create another variable at the of the for loop at line 5...

How many objects are eligible for GC,
(1) after line 4
(2) after line 5
(3) after line 6
The opcodes are...

Method void method()
0 bipush 10
2 istore_1
3 goto 17
6 new #2 <Class java.util.ArrayList>
9 dup
10 invokespecial #3 <Method java.util.ArrayList()>
13 astore_2
14 iinc 1 -1
17 iload_1
18 ifge 6
21 bipush 10
23 istore_2
24 getstatic #4 <Field java.io.PrintStream out>
27 ldc #5 <String "end of method">
29 invokevirtual #6 <Method void println(java.lang.String)>
32 return

Now you see that creating another variable (local variable int i) at the end of the for loop occupies the position 2 on the local variable stack. This position was previously occupied by the last object created inside the for loop. Therefore, this object becomes eligible for GC since there are no more references to it.
Ans:
(1) after line 4 - 10
(2) after line 5 - 11
(3) after line 6 - 11
This is where the confusion arises -

If java recognises that a variable is out of scope and therefore its position can be occupied by another variable, why isn't the object referenced by the out-of-scope variable eligible for GC?

Thankfully, these type of questions are not asked in the exam.
Bartenders, Please feel free to correct me. I wouldn't want to mislead anybody.
[ November 19, 2002: Message edited by: Vin Kris ]
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic