BenMansourNizar
BenMansourNizar

Reputation: 1628

Strange behavior of JAVAGC

i have the following code :

public class MyOjbect {
public Integer z = 111;
@Override
protected void finalize() throws Throwable {
    System.out.println("invoking GC in MyOjbect");
    super.finalize();
         }
     }
      public class GC {
private MyOjbect o; 
private void doSomethingElse(MyOjbect obj) {
    o = obj;
}
@SuppressWarnings("unused")
public void doSomething() throws InterruptedException {
    System.out.println("Start");
    MyOjbect o = new MyOjbect();        
     doSomethingElse(o);        
     o = new MyOjbect();
     doSomethingElse(null);
     System.gc();
    // System.out.println("checking "+o.z);
}
public static void main(String[] args) throws InterruptedException {
    GC gc = new GC();
    gc.doSomething();
       }
}

I wonder why the GC garbage the o variable after executing the doSomethingElse method. Even the o variable is not yet null. In fact, when i debug the code o after doSomethingElse is not null but the GC garbage it. In addition if i uncomment the last line, GC print the o.z variable and after that invoke the GC.

Updated : For people who asks why the local variable is the same as the field.I have just copied a question from the SCJP Test Exam as it is

Upvotes: 0

Views: 71

Answers (1)

Pierre Laporte
Pierre Laporte

Reputation: 1215

Lots of subjects to discuss here !

First, as Gyro said, The GC does not collect variables. It collects instances of dead objects. A dead object is an object that has no strong reference (variable) that leads to it. Note that there are more subtle cases (Weak references, Soft references, Phantom references, ...), but let's focus on the most common case :-) You can find more information about this here : https://weblogs.java.net/blog/2006/05/04/understanding-weak-references

If you uncomment the last line, "111" gets printed since o is the local variable that references an instance of MyObject you created with o = new MyOjbect();.

Now, the trickiest thing : you have two different instances of MyObject. However, your program only print once the "invoking GC in MyObject". It becomes evident if you transform your "MyObject" class like this :

public class MyOjbect {
    public Integer z = 111;

    public MyOjbect() {
        System.out.println("Creating MyObject " + hashCode());
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("invoking GC in MyOjbect " + hashCode());
        super.finalize();
    }
}

You program now prints two MyObjects creation but only one that is recovered by the GC. This is because there is absolutely no guarantee that the finalize() method will be called. According to the JLS and the javadoc of finalize() :

The Java programming language does not guarantee which thread will invoke the finalize method for any given object

In your case, the end of the application makes every object dead. No need to run a GC since the heap will be completely recovered once the JVM exits.

Upvotes: 1

Related Questions