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

本秂侑毒 提交于 2020-07-06 20:29:27

问题


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.)


回答1:


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.




回答2:


It is not quite true that all of the objects are in heap space; but it is generally true. Java has been extended to have stack-local objects, provided the JVM can detect that the object will live only as long as the stack frame.

Now for the objects on the heap, which have a local reference in a method. While the method is being processed, the stack frame associated with the method run contains the local variable references. As long as the reference can be used (which includes being still in the stack frame) the object will not be garbage collected.

Once the reference has been destroyed, and the object can no longer be reached by the running program (because there's no references that can reach it), then the garbage collector will collect it.



来源:https://stackoverflow.com/questions/54937469/does-jvm-garbage-collect-objects-being-referenced-by-local-variables-which-are-n

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!