当对象有资格进行垃圾收集时

时间:2012-10-31 19:42:09

标签: java garbage-collection

给我一​​个方法并询问,当它符合垃圾收集资格时,我的意思是在哪一行。我相信ooa都有资格进行垃圾回收。因为,它们被设置为null。如果我错了,请纠正我。但是,问题是,当它符合gc的条件时,我的意思是在哪一行。 ?

public Object m() {
        Object o = new Float(3.14F);
        Object[] oa = new Object[1];
        oa[0] = o; /* Line 5 */
        o = null; /* Line 6 */
        oa[0] = null; /* Line 7 */
        return o; /* Line 8 */
    }

请有人解释。 ?

5 个答案:

答案 0 :(得分:4)

让我们来看看代码:

1)  o = new Float();  
2)  oa = new Object[];  
    at this point we have 2 objects.  
3) oa[0] = o;  
    at this point oa[0] holds the reference of o.  
4)  o = null;  
    o is still being referenced by oa[0]  
5)  oa[0] = null  
    o now has zero references.  
6)  return o;  
     o is null. 

第7行是o的GC资格。在函数退出之前,oa不符合GC条件。

通常,只有在没有引用的情况下,对象才有资格使用GC。在处理String时要非常小心,因为有一个叫做字符串池的特殊地方。所以下面的代码:

void foo()  
{  
   String s = "foo";   
   s=null;  
   return s;  
}  

s绝不保证符合该职能的条件。

评论问题

  

一个问题,你说..在功能之前,没有资格获得GC   退出。但是,在返回o之前,oa设置为null并且无处可去   转介

答案:

  

oa未设置为null。设置为null的是oa [0]处的对象   (oa的第一个索引)。如果该行为oa = null则为真,   并且无论oa中的唯一项目是否为null,实际上都不是   使包装器(在本例中为数组)为null。类似于拥有   列出并清空其所有元素不会使List为空。

答案 1 :(得分:3)

允许Java进行某些优化,因此仅针对局部效应的优化JIT可以简化此代码

public Object m() {
    //Object o =                    // o does not participate in any externally visible side-effect
    new Float(3.14F);               // Available for collection as soon as ctor finishes.
    //Object[] oa = new Object[1];  // Array ctors are known not to have side-effects, and oa does not participate in a side-effect or result that is visible outside the method.
    //oa[0] = o; /* Line 5 */       // Side-effect not visible.
    // o = null; /* Line 6 */       // Side-effect not visible.
    //oa[0] = null; /* Line 7 */
    //return o; /* Line 8 */        // Eliminated by inlining.
    return null;                    // Type-analysis proves that this method can only return null.
}

不要假设局部变量到null的赋值实际上发生在长期方法调用中。

答案 2 :(得分:1)

当不再引用该对象时,垃圾收集符合条件,但重要的是要注意GC不能保证在那时运行,因此从技术上讲,可以分配内存。

oa [0]引用该对象,因此当您在第7行将其设置为null时,不再存在对该对象的引用,因此它符合GC的条件。

正如评论所指出的那样,oa,数组本身仍然存在,直到方法执行完毕,即在第8行执行之后。它在方法m()的生命周期中是本地的,因此当m()从执行返回时它将符合GC的条件。

答案 3 :(得分:0)

  

如果我错了,请纠正我。但是,问题是,当它有资格获得gc时,我的意思是在哪一行。 ?

这个问题是荒谬的,或者基于过度简化的垃圾收集模型。垃圾收集器在运行时对可用表示进行操作,这意味着从全局根(包括寄存器,堆栈和全局变量)跟踪可达性。与高级源代码没有对应关系,因此询问行号是没有意义的。实际上,在GC运行之前,编译器会将您的代码变得无法识别。

答案 4 :(得分:-1)

AFAIK,Java使用Mark-And-Sweep算法。 GC反复在堆上的单独线程中运行。

如果某个参考变量(或对象)超出范围,则标记为删除并在适当时(或覆盖)清除。

每当变量设置为null时,即静态引用和其他线程的引用计数对象变为无法访问时,即其引用不再存在时,它标记为再次删除。

代码中的第7行是将其标记为删除的位置。