当前位置: 首页 > 知识库问答 >
问题:

gc()收集仍然被局部变量引用的对象[重复]

池照
2023-03-14
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个对象。

我不知道为什么JVM知道这些对象不会被使用,也不知道为什么JVM判断这个GC根不是引用。

共有1个答案

柴凌
2023-03-14

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

可达对象是指可以在任何活动线程的任何潜在的持续计算中访问的任何对象。

很明显,它需要一个包含对象引用的变量,以使它能够在“潜在的持续计算”中从活动线程访问它,所以没有这样的变量可以用作一个容易检查的标志,表明一个对象是不可访问的。

它是否真的执行,取决于诸如当前执行模式之类的条件,即该方法是否运行已解释或已编译。

从Java9开始,您可以插入显式屏障,例如。

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);
}

这将强制列表保持活力。

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();
        }
    }
}
 类似资料:
  • Java对象是在堆中创建的,为了在Java中进行垃圾收集,堆被分为三个部分或三代,它们被称为堆的年轻一代、终身或老一代和永久区域。新一代被进一步划分为三个部分,称为伊甸园空间、幸存者1和幸存者2空间。当第一次在堆中创建的对象在Eden space内的新一代中创建时,如果对象幸存,则在后续的次要垃圾收集之后,在主要垃圾收集将该对象移动到旧代或终身代之前,将其移动到幸存者1,然后移动到幸存者2。 阅读

  • 问题内容: 我是一名进入Java世界的C ++程序员。而且我不能摆脱必须让Java垃圾收集器进行清理的不良感觉。 例如,此代码在Java中的行为如何? 当myFunction()退出时,是否将删除局部变量对象? 我是否必须在退出之前将object设置为null,否则它将超出范围并被GC删除?或者,在最坏的情况下,它会像在C ++中那样泄漏吗? 问题答案: 不再使用后 ,将 在某个时候 将其收集 为

  • 问题内容: 我想知道你们是否可以提供帮助。我试图做一个简单的视图,它将用户发送到客户端创建表单,但是我一直收到此错误: 赋值之前引用的局部变量“ form” 查看我的代码,看不到有什么问题。 有人告诉我我哪里出问题了吗? 问题答案: 这是正在发生的事情: 没有输入该块。 变量未定义。 然后,你尝试在语句中引用变量。 至于解决方法,这确实是你要决定的。解决的方法取决于你希望代码执行的操作(如果请求方

  • 假设我有下面的类:每次Meow调用时,都会在堆上创建一个新的随机对象。 我是否应该将随机对象从Meow方法中取出,并像这样将它从局部变量改为实例变量?因此,每次Meow调用相同的随机对象时,将使用在堆上创建的cat对象,而不是像上面的方法那样使用一个新的对象。 我试图理解第二种方法是否是一个最佳实践,因为即使我的程序很小,它也不会是一个大问题,也许以后如果程序变大了,它会帮助我防止性能问题。

  • 我没有发现这段代码中有任何错误,但是eclipse告诉我变量没有初始化。这只是一个警告,但编译后也不起作用。我根本找不到错误,这段代码是100%正确的。请注意,此代码的结构不容易更改,因为下面提供的代码经过简化,因此您没有那么多要阅读的内容;-)

  • 问题内容: 给定以下程序: 您是否希望在run方法中的while循环仍在执行且局部变量test仍在范围内时调用finalize? 更重要的是,此行为在任何地方都有定义吗?Sun有什么声明它是实现定义的吗? 这与以前人们在主要关注内存泄漏的SO上提出此问题的方式相反。在这里,我们让GC积极地对变量感兴趣的变量进行GC处理。您可能会因为测试仍在“范围内”而不会被GC,所以您可能会期望这样做。 作为记录