JVM是否会垃圾回收由不再使用的局部变量引用的对象? [英] Does JVM garbage collect objects being referenced by local variables which are no longer used?

查看:150
本文介绍了JVM是否会垃圾回收由不再使用的局部变量引用的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,方法的局部变量位于执行线程的堆栈框架中,局部变量的引用类型仅具有对象的引用,而没有对象本身. JVM中的所有对象都位于堆空间中.

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.

我想知道被执行方法中的局部变量引用的对象永远不会被垃圾收集,直到方法执行结束为​​止. (不使用java.lang.ref.WeakReference和SoftReference.)

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?

(如果从不对它们进行垃圾回收,这意味着可能需要在执行耗时的大型方法时将null分配给不再使用的变量.)

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

推荐答案

中详细说明的对象范围?,局部变量不会阻止对引用对象的垃圾回收.或者,如此答案所述,范围是唯一的语言概念,与垃圾收集器无关.

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:

reachable 对象是可以从任何活动线程进行任何潜在的连续计算中访问的任何对象.

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!

表明即使在范围内具有变量的方法也可以检测到所引用对象的完成.此外,由于B对象不可访问,因此从堆变量中进行引用也不一定会阻止垃圾回收,因为当包含引用的对象也无法访问时,将无法继续进行计算.

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.

这不仅是理论上的选择.如 finalize()在Java 8中对强可访问对象的调用中所讨论的那样,在调用方法时对象甚至可能发生这种情况在它们上,换句话说,当实例方法仍在执行时,this引用可能会被垃圾回收.

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.

这篇关于JVM是否会垃圾回收由不再使用的局部变量引用的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆