类型列表的对象(占用内存)何时符合垃圾收集条件,同时保存对列表的引用的变量在哪里?在下面的代码中,没有为其分配变量。
案例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?
当弹出堆栈帧时,列表是否符合GC的条件?
有什么方法可以加快GC的资格?
答案 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
有资格收集。
当然,所有这一切都假设
returnList
的所有者未维持对其返回值的引用。当弹出堆栈帧时,列表是否会获得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将不可用于收集