Does JVM garbage collect objects being referenced by local variables which are no longer used?

ParkCheolu :

As far as I know, a method's local variable is located in a stack frame in an executing thread and a reference type of a local variable only has a objects' reference, not the object itself. All of objects in JVM are located in a heap space.

I want to know that objects referenced by local variables in a method being executed are never garbage collected until the end of the method execution. (without using java.lang.ref.WeakReference and SoftReference.)

Are they garbage collected? or never? Is there compiler's optimization to this type of stuff?

(If they are never garbage collected, this means it may be needed to assign null to variables no longer used when executing big methods which take long time.)

Holger :

As elaborated in Can java finalize an object when it is still in scope?, local variables do not prevent the garbage collection of referenced objects. Or, as this answer puts it, scope is a only a language concept, irrelevant to the garbage collector.

I’ll cite the relevant part of the specification, JLS §12.6.1 again:

A reachable object is any object that can be accessed in any potential continuing computation from any live thread.

Further, I extended the answer’s example to

class A {
    static volatile boolean finalized;

    Object b = new Object() {
        @Override protected void finalize() {
            System.out.println(this + " was finalized!");
            finalized = true;
        }
        @Override public String toString() {
            return  "B@"+Integer.toHexString(hashCode());
        }
    };
    @Override protected void finalize() {
        System.out.println(this + " was finalized!");
    }

    @Override public String toString() {
        return super.toString() + " with "+b;
    }

    public static void main(String[] args) {
        A a = new A();
        System.out.println("Created " + a);
        for(int i = 0; !finalized; i++) {
            if (i % 1_000_000 == 0)
                System.gc();
        }
        System.out.println("finalized");
    }
}
Created A@59a6e353 with B@6aaa5eb0
B@6aaa5eb0 was finalized!
finalized
A@59a6e353 with B@6aaa5eb0 was finalized!

which demonstrates that even the method with the variable in scope may detect the finalization of the referenced object. Further, being referenced from a heap variable doesn’t necessarily prevent the garbage collection either, as the B object is unreachable, as no continuing computation can access it when the object containing the reference is unreachable too.


It’s worth emphasizing that even using the object does not always prevent its garbage collection. What matters, is whether the object’s memory is needed for the ongoing operation(s) and not every access to an object’s field in source code has to lead to an actual memory access at runtime. The specification states:

Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. […]

Another example of this occurs if the values in an object's fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage.

This is not only a theoretical option. As discussed in finalize() called on strongly reachable object in Java 8, it may even happen to objects while a method is invoked on them, or in other words, the this reference may get garbage collected while an instance method is still executing.

The only ways to prevent an objects garbage collection for sure, are synchronization on the object if the finalizer also does synchronization on the object or calling Reference.reachabilityFence(object), a method added in Java 9. The late addition of the fence method demonstrates the impact of the optimizers getting better from version to version on the issue of earlier-than-wanted garbage collection. Of course, the preferred solution is to write code that does not depend on the time of garbage collection at all.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=109201&siteId=1