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

Memory management 关于代码如何影响GC过程的一些问题,memory-management,garbage-collection,Memory Management,Garbage Collection,1) 添加Dispose()或finalize方法对使对象很快成为GC对象有影响吗?我的经理编写了一些代码,添加了一个finalize()方法,希望它是GC'd 但我认为,如果对象符合某些标准,则必须首先对其进行“标记”以便收集 2) 写“o=null”(其中o是一个ref类型)对使对象更快地成为GC对象有影响吗?无论是在C++还是java/C语言中, 谢谢你,Java: 1) 否,finalize()在垃圾回收器确定该对象可进行GC时被调用-它与GC发生的时间无关,也与该对象是否将在给定的运行

1) 添加Dispose()或finalize方法对使对象很快成为GC对象有影响吗?我的经理编写了一些代码,添加了一个finalize()方法,希望它是GC'd

但我认为,如果对象符合某些标准,则必须首先对其进行“标记”以便收集

2) 写“o=null”(其中o是一个ref类型)对使对象更快地成为GC对象有影响吗?无论是在C++还是java/C语言中,

谢谢你,Java:

1) 否,
finalize()
在垃圾回收器确定该对象可进行GC时被调用-它与GC发生的时间无关,也与该对象是否将在给定的运行中进行GC无关。事实上,实现
finalize()
会延迟对象的GCD-第一个GC过程确定该对象是可GC的(即应调用
finalize()
),并且直到第二个过程才释放该对象-假设终结器没有创建对该对象的新引用


2) 保留引用将延迟GC,因此如果保留引用的对象仍然可以访问,则断开引用可以允许更早地对对象进行GC。但是,不能保证对象会更早地进行GCD。

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

让我们从添加终结器开始,或者更确切地说,收集没有终结器的对象时会发生什么

当GC运行并发现没有根引用的对象时,将收集这些对象

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

此列表是在普通GC之外处理的,由于对象现在有根引用(该列表),因此暂时不符合收集条件。通过对列表进行迭代并调用所有终结器来处理该列表。这里有很多细节我都在掩饰

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

因此,实际上,添加终结器不会使对象更快地被收集,相反,它实际上会使对象稍后被收集

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

在这方面,调用Dispose也没有任何意义。Dispose只是一个方法调用,调用它不会将对象标记为符合收集条件。如果在调用Dispose后,仍然有对该对象的根引用,则该对象将保留在内存中而不会被收集

但是,如果类具有Dispose方法和终结器,Dispose方法通常会从终结中注销对象。基本上您会说“Dispose现在已经处理了终结器将要执行的所有操作,因此调用终结器不再有任何意义”。如果执行此操作,则调用Dispose方法,然后删除对对象的所有活动引用,将使该对象符合收集条件,并跳过最终确定步骤

关于你的第二个问题

如上所述,您需要删除对对象的所有根引用。根引用是一种可以追溯到在程序运行期间存在的对象的引用,可以是静态字段、静态调用堆栈上的局部变量等。一旦所有这些都消失了,对象就有资格收集

但是.NET中的GC非常具有攻击性。抖动将与代码一起存储信息,告诉GC使用局部变量的方法的哪些部分,并且如果不再使用变量,例如对于方法的最后部分,即使变量仍然引用对象,该变量被认为是不必要的,因此可以收集对象

例如,这里:

public void Test()
{
    object o = new object();
    // do something else
}
在这种情况下,只要方法中不再使用
o
变量,在“执行其他操作”代码期间,就可以收集其中的对象

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

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

此外,如果该变量稍后在方法中重新使用,则可以通过将当前对象设置为null来帮助使其符合收集条件。(注意,我不完全确定这一点,也许抖动可以看出不需要当前值,因此可以收集它,因为稍后您仍然会覆盖内容)

因此,总结一下:

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

(1)哪种语言/垃圾收集器?(2) #2是第无数个傻瓜。对于#1,.NETGC上的许多问题也解决了这个问题。1,Java是类似的-具有finalize方法的对象在下一次通过