代码之家  ›  专栏  ›  技术社区  ›  GurdeepS

关于代码如何影响GC过程的一些问题

  •  0
  • GurdeepS  · 技术社区  · 14 年前

    1) 添加Dispose()或finalize方法是否会对使对象很快成为GC有任何影响?我问这个问题时,我的经理写了一些代码,添加了finalize()方法,希望它是GC'd。

    2) 写入“o=null”(其中o是ref类型)是否会对使对象更快地成为GC有任何影响?无论是在C++还是java/C语言中。

    谢谢

    2 回复  |  直到 14 年前
        1
  •  2
  •   Lasse V. Karlsen    14 年前

    注意,这个答案是关于.NET的。我根本不知道Java是如何做到这一点的。

    让我们从添加终结器开始,或者更确切地说,当一个对象 被收集。

    当GC运行并发现没有根引用的对象时,会收集它们。

    但是,如果将终结器添加到类中,当GC发现对象符合收集条件时,会将其放置在列表中,因为它有终结器。

    调用对象的终结器后,将从列表中删除该对象。有时稍后,当GC再次发现该对象时,尽管它的类型中仍然有finalizer方法,但该对象已被标记为不再需要运行finalizer,并且该对象现在被收集,就好像它没有finalizer开始一样。

    所以,实际上,添加终结器并不能使对象更快地被收集,相反,它实际上会使对象更晚地被收集。

    使对象符合集合条件的唯一方法是删除对它的所有根引用。

    但是,如果类具有Dispose方法和终结器,则Dispose方法通常会从终结中注销对象。基本上你说“Dispose现在已经处理了终结器将要做的所有事情,所以不再需要调用终结器”。如果它这样做,调用Dispose方法,然后删除对该对象的所有活动引用,将使它同时符合收集条件,并跳过终结步骤。

    如上所述,您需要删除对该对象的所有根引用。根引用是一种可以被跟踪回在程序期间存在的对象的引用,无论是静态字段、静态调用堆栈上的局部变量等。一旦所有这些都不存在,对象就有资格进行收集。

    例如,这里:

    public void Test()
    {
        object o = new object();
        // do something else
    }
    

    在这种情况下,只要 o 变量不再用于方法中,在“执行其他操作”代码期间,可以收集其中的对象。

    抖动将检测程序在调试器中运行的时间,然后人为地将所有变量的生存期延长到其作用域的末尾,以便您可以检查变量,即使在技术上不再认为它们是“活动的”。但是当不在调试器中运行时 o型 上面没有显式的空值并不意味着什么,对象仍然可以被收集。

    现在,如果 是一个静态字段,它比方法调用的寿命长得多,那么是的,显式地将其设置为空当然会有帮助,因为现在您正在删除对对象的根引用。

    笔记 我不太确定,也许抖动可以看出不需要当前的值,所以可以收集,因为稍后会覆盖内容)

    • 除非需要,否则不要添加终结器
    • 若要将对象“标记”为符合收集条件,请删除对该对象的所有根引用
    • 您可以通过显式地将变量和字段设置为空来帮助收集,但是对于方法不再使用的局部变量,这可能是不必要的(但不会造成伤害)
        2
  •  0
  •   SimonJ    14 年前

    爪哇语:

    1) 不, finalize() 完成() 延误 一个来自GCed的对象-第一个GC过程确定该对象是可GC的(即。 完成()

    2) 保留引用将延迟GC,因此中断引用 如果持有引用的对象仍然可以访问,则允许更早地对该对象进行gcd。不能保证物体