Gonen I
Gonen I

Reputation: 6127

Object garbage collection after reference's scope expires

Firstly let me say I am aware that System.gc() is more of a suggestion to collect garbage than a command, and that collection is not guaranteed to finish, start, or collect a specific object. And yet...

With the following code , the a1 instance only gets collected if I explicitly put null in the reference. If a1 simply goes out of scope, it does not get collected.

class A {
    @Override
    protected void finalize() throws Throwable {
        System.out.println("Collecting A");
    }
}
public class Example {
    public static void main(String[] args) throws InterruptedException {
        try {
            A a1 = new A();
            //a1 = null; // a1 gets collected only if I uncomment this line
        }
        finally {
            System.out.println("Finally executed");
        }
        System.gc();
        Thread.sleep(1000);
    }
}

Why does a1 not get collected if it simply goes out of scope, when there are no strong references to it ? Is it because this scope does not constitute a separate stack frame?

Upvotes: 1

Views: 95

Answers (1)

Jorn Vernee
Jorn Vernee

Reputation: 33905

It's totally up to the JVM to decide when a1 gets collected or whether the finalizer runs.

For instance, a JVM might decide to run this in an interpreter which simply has a local variable table that holds every local variable in the method - similarly to how this works in the byte code - and variables don't really go 'out of scope' from the GC's perspective until the method exits.

But, for instance, a JIT compiler could be more aggressive with limiting the GC scope of locals (or rather, it simply doesn't keep track of what it doesn't need to). So, if you for instance run the program with -Xcomp (on the HotSpot JVM) which forces this code to be JIT compiled, you might (or might not) see the output:

Finally executed
Collecting A

Without setting a1 to null explicitly.

On the other hand, if you were to run this with Epsilon GC (which is a no-op GC) using the VM options: -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC (again on HotSpot), you might not see Collecting A in the output at all, even if you explicitly set a1 to null.

So, yeah, it's really up to the VM.

Upvotes: 5

Related Questions