System.gc()收集仍由局部变量引用的对象 [英] System.gc() collects objects still referenced by local variables

查看:51
本文介绍了System.gc()收集仍由局部变量引用的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我运行以下程序时

public static void main(String[] args) {

    ArrayList<Object> lists = new ArrayList<>();
    for (int i = 0; i <200000 ; i++) {
        lists.add(new Object());
    }
    System.gc();
    try {
        Thread.sleep(Integer.MAX_VALUE);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

然后我丢了堆

jmap -dump:live,format=b,file=heap.bin 27648
jhat -J-Xmx2G heap.bin

缺少 ArrayList 和200000对象.

The ArrayList and the 200000 objects are missing.

我不知道为什么JVM知道将不使用对象以及JVM为何判断该GC根目录不是引用.

I don't know why the JVM knows that the objects will not be used and why the JVM judges that this GC root is not a reference.

推荐答案

局部变量本身不是GC的根.Java®语言规范定义:

Local variables are not GC roots per se. The Java® Language Specification defines:

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

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

很明显,它需要一个变量,该变量持有一个对象的引用,以便可以通过实时线程在潜在的连续计算"中对其进行访问,因此不存在此类变量可以用作易于实现的对象.-检查是否有对象无法到达.

It’s obvious that it requires a variable holding a reference to an object, to make it possible to access it in a "potential continuing computation" from a live thread, so the absence of such variables can be used as an easy-to-check sign that an object is unreachable.

但这并不排除其他工作来确定仍由局部变量引用的无法访问的对象.规范甚至明确指出

But this doesn’t preclude additional effort to identify unreachable objects which are still referenced by local variables. The specification even states explicitly

可以设计程序的优化转换,以将可到达的对象数量减少到少于天真的被认为可到达的对象数量.例如,Java编译器或代码生成器可能会选择设置将不再用于为null的变量或参数,以使此类对象的存储可能会尽快收回.

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. For example, a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.

在同一部分.

它是否确实如此,取决于当前执行模式之类的条件,即该方法是解释运行还是已经编译.

Whether it actually does, depends on conditions like the current execution mode, i.e. whether the method runs interpreted or has been compiled already.

从Java 9开始,您可以插入明确的障碍,例如

Starting with Java 9, you can insert explicit barriers, e.g.

public static void main(String[] args) {
    ArrayList<Object> list = new ArrayList<>();
    for (int i = 0; i <200000 ; i++) {
        list.add(new Object());
    }
    System.gc();
    try {
        Thread.sleep(Integer.MAX_VALUE);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Reference.reachabilityFence(list);
}

这将强制列表保持活动状态.

This will force the list to stay alive.

以前的Java版本的替代方法是同步:

An alternative for previous Java versions, is synchronization:

public static void main(String[] args) {
    ArrayList<Object> list = new ArrayList<>();
    for (int i = 0; i <200000 ; i++) {
        list.add(new Object());
    }
    System.gc();
    synchronized(list) {
        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

但是通常,您希望尽早收集未使用的对象.仅当您将 finalize()与有关可达性的幼稚假设一起使用时,才会出现问题.

But usually, you want unused objects to become collected as early as possible. Problems may only arise when you use finalize() together with naive assumptions about the reachability.

这篇关于System.gc()收集仍由局部变量引用的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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