2

list 类型的对象,占用内存,什么时候有资格进行垃圾回收,另外,保存对 list 的引用的变量在哪里?在下面的代码的情况下,没有分配给它的变量。

情况1:

for (Integer i : returnList()) { 
    System.out.println(i);
}

如果是这样的代码:

案例二:

List list = returnList();
for (Integer i : list) { 
    System.out.println(i);
}
   list = null;

我们可以控制 GC,在没有分配变量的第一种情况下,有什么方法可以解决这个问题吗?

总结一下:

  1. 引用的机制是什么,没有引用变量来列出是案例 1?

  2. 弹出堆栈帧时列表是否有资格进行 GC?

  3. 有什么方法可以加快获得 GC'ing 的资格吗?

4

4 回答 4

3

引用的机制是什么,没有引用变量来列出是案例 1?

有一个对列表的隐式引用。这可以通过理解这样的增强for被翻译成:

for(Iterator e = returnList().iterator(); e.hasNext(); ) {
    Integer i = (Integer)e.Next();
    System.out.println(i);
}

在这里,e有一个对 on 的迭代器的引用returnList,它本身也对returnList. 因此,returnList只要e是有根的,它就是根的,这仅在控制处于循环中时才成立。for当控制离开for身体时,e有资格收集,所以returnList才有资格收集。

当然,这一切都是假设

  1. 的所有者returnList没有维护对其返回值的引用。
  2. 相同的列表尚未返回给另一个调用者,并且其他调用者没有维护对同一列表的引用。

弹出堆栈帧时列表是否会被 GC 处理?

不必要。当 JVM 可以确定引用对象没有对它的根引用时,它将有资格被收集。请注意,它不一定会立即被收集。

在情况 1 中加快 GC 的任何方法。

它不能在控制离开for循环之前被收集。它可能在控制离开for循环后被收集。让 JVM 担心这一点。

请注意,您可以通过以下方式尝试手动垃圾收集

System.gc();

但请注意,这可能会表现出更糟糕的行为,因为如果它触发垃圾收集,它可能完整的垃圾收集。请注意,JVM 可以忽略此请求。您可能在这里浪费了大量的 CPU 周期。请注意,在具有无限内存的系统上,垃圾收集器永远不需要运行。在这样的系统上,如果垃圾收集器服从您的请求,那么请求垃圾收集器可能会完全浪费 CPU 周期。

让 JVM 管理垃圾收集。它的算法经过高度调整。

于 2013-08-12T19:52:00.300 回答
0

来自SCJP 第 256-257 页

垃圾收集器会执行一些神奇的、未知的操作,当它发现任何活动线程都无法访问的对象时,它会认为该对象符合删除条件,甚至可能在某个时候将其删除。(你猜对了;它也可能永远不会删除它。)当我们谈论到达一个对象时,我们实际上是在谈论有一个可到达的引用变量来引用所讨论的对象。如果我们的 Java 程序有一个引用变量指向一个对象,并且该引用变量可用于活动线程,那么该对象被认为是可访问的。

将对象设置为 NULL 可能有助于在 GC 删除对象时加快速度,但也可能不会,您无法控制它。当 JVM 检测到内存不足时,它会运行 GC,您可以手动要求它这样做,但没有任何保证。

于 2013-08-12T19:51:51.833 回答
0

您无法控制 GC。它由 JVM 管理。您可以管理的是哪些对象应该可用于垃圾收集。虽然,您可以使用 finalize 方法找出垃圾收集器何时运行。它总是在对象被删除之前调用

public class Demo{    

   static  void create()
     {
         Demo o = new Demo();
     }
     public void finalize()
       {
          System.out.println("GC called");
       }

    public static void main (String ...ar)
     {

       for (long  i=1;i<900000;i++)  //Try changing values here
            {
               create();
            }
    }
}

方法内部创建的对象在方法返回时可用于 GC(就像局部变量存在于方法的持续时间一样)。但是,如果方法返回一个对象,它将无法用于垃圾回收

public class Demo{    

   public void getDate()
     {
        Date o = new Date();
        StringBuffer d = new StringBuffer(o.toString());
        System.out.println(d);
        return o;
     }
    public static void main (String ...ar)
     {
            Date x= getDate();
    }
}

在上面的代码中,当方法返回时,对象 d 可用于 GC。但是对象 o 将无法收集

于 2013-08-12T20:30:54.923 回答
0

引用的机制是什么,没有要列出的引用变量是案例 1?

看下一个答案。

弹出堆栈帧时列表是否会被 GC 处理?

该列表是在堆上创建的——但如果对它的唯一引用是在堆栈上,则它有资格被 GC 收集。但这并不意味着它会很快发生。

在情况 1 中加快 GC 的任何方法。

你不能“加速”GC,即使System.gc();你只是在“建议”GC 可以完成它的工作——同样,它不一定会很快发生。

这背后也有很多意义:假设您的程序有 2GB 内存可供使用,而当前仅使用 2KB - 它不能证明 GC 仅因为某些对象符合删除条件而停止您的程序运行并清理内存是合理的。

于 2013-08-12T19:52:03.807 回答