如果没有分配变量,对象何时超出范围?

时间:2013-08-12 19:43:25

标签: java

类型列表的对象(占用内存)何时符合垃圾收集条件,同时保存对列表的引用的变量在哪里?在下面的代码中,没有为其分配变量。

案例1:

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

如果代码如下:

案例2:

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

我们可以控制GC,在没有分配变量的情况下,有没有办法在第一种情况下处理它?<​​/ p>

总结:

  1. 参考机制是什么,没有列出的参考变量是案例1?

  2. 当弹出堆栈帧时,列表是否符合GC的条件?

  3. 有什么方法可以加快GC的资格?

4 个答案:

答案 0 :(得分:3)

  

参考机制是什么,没有列出的参考变量是案例1?

列表中有一个隐式引用。这可以通过理解增强的for之类的内容转化为:

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

此处,e引用了returnList上的迭代器,本身引用了returnList。因此,returnList只要e有根,只有 为真,而控制权在for循环中才有效。当控件离开for正文时,e有资格收集,因此returnList有资格收集。

当然,所有这一切都假设

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

    当弹出堆栈帧时,列表是否会获得GC?

    不一定。当JVM可以确定引用没有根参考时,它将有资格进行收集。请注意,它不一定立即被收集。

      

    在案例1中以任何方式加速GC。

    除了离开for循环的控件之外,它不能被收集。在控制离开for循环后,可能被收集。让JVM担心这一点。

    请注意,您可以通过

    尝试手动垃圾回收
    System.gc();
    

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

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

答案 1 :(得分:0)

来自 SCJP第256-257页

  

垃圾收集器执行一些神奇的,未知的操作,以及什么时候   它会发现任何活动线程都无法访问的对象   将该对象视为有资格删除,甚至可能   在某些时候删除它。 (你猜对了;它也可能永远不会   删除它。)当我们谈到达到一个对象时,我们真的   谈论有一个可达的参考变量引用   有问题的对象。如果我们的Java程序有一个引用变量   是指一个对象,该引用变量可用于a   活线程,然后该对象被认为是可达的。

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

答案 2 :(得分:0)

  

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

见下一个答案。

  

当弹出堆栈帧时,列表是否会获得GC?

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

  

在案例1中以任何方式加速GC。

你无法“加速”GC,即使致电System.gc();你只是“建议”GC可以完成其工作 - 再次,它不一定会很快发生。< / p>

它背后有很多意义:说你的程序有2GB的内存可供使用,目前只使用2KB - 它不能证明GC阻止程序运行并清理内存只是因为某些对象符合条件删除。

答案 3 :(得分: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将不可用于收集