GC根和局部变量

4

在查看计时器文档时,我发现以下示例并附有以下注释:

    // Normally, the timer is declared at the class level,
    // so that it stays in scope as long as it is needed.
    // If the timer is declared in a long-running method,  
    // KeepAlive must be used to prevent the JIT compiler 
    // from allowing aggressive garbage collection to occur 
    // before the method ends. You can experiment with this
    // by commenting out the class-level declaration and 
    // uncommenting the declaration below; then uncomment
    // the GC.KeepAlive(aTimer) at the end of the method.
    //System.Timers.Timer aTimer;
    code in between
    // If the timer is declared in a long-running method, use
    // KeepAlive to prevent garbage collection from occurring
    // before the method ends.
    //GC.KeepAlive(aTimer);

这是否意味着在C#中的垃圾回收器可以清理掉局部变量,即使这样做会产生副作用?可能是因为我之后不再访问计时器,GC可以更早地将其收集吗?

如果我理解正确的话,我不确定我喜欢这样的优化(但我可能并没有理解)。


2
当垃圾回收器确定除了终结器外没有任何东西会注意到对象的销毁时,对象就可以被回收。 - Raymond Chen
可能是Do Timer object get GC-ed when no other object references them?的重复问题。 - Hans Passant
@Raymond 谢谢,不幸的是,我们无法将评论标记为正确答案 :-) - Voo
2个回答

2

是的,在变量的作用域结束之前,GC可能会在变量最后使用后立即回收它。在方法末尾放置GC.KeepAlive可以确保变量在KeepAlive调用之前一直处于“活动”状态。

C#是一种命令式语言,因此GC并不知道副作用的任何信息。


你确定你在回答这个问题吗? - user541686
@Mehrdad:Tia已经回答了,只是比我简洁得多。 - Daniel Mallott
@DanielMallott:我不明白为什么对象的存活与垃圾收集器的触发有任何关系......评论说这可以防止GC变得“过于激进”,而这个答案仅说明对象不会被收集。 - user541686
@Mehrdad:垃圾回收器(GC)天生具有侵略性。关键是保持对象在作用域内 - 在这种情况下,在方法的末尾调用它。否则,GC将(可能)在认为对象已经超出作用域时立即回收它。原始问题中的特定情况只是微软告诉你如何操纵GC的一个例子。 - Daniel Mallott
@DanielMallott:保持对象的存活并不意味着垃圾回收器会变得不那么积极,它只是意味着在运行时它不会回收该对象。 - user541686
简短而甜美,但这是确保不出错的最简单方法;-)似乎.NET GC和Hotspot之间的差异可能比我想象的更有趣,阅读规范是个好主意。 - Voo

1
据我所了解,垃圾回收器会在下一次垃圾回收周期中标记任何它认为不再需要的变量或对象作为垃圾回收的候选对象。我不确定这里的具体应用,但我知道有些情况下,垃圾回收器可能会在仍然需要资源的时候将其标记为可回收(但由于代码编写方式的原因看起来不再需要)。
通常,在方法中,对象或变量在方法调用期间保持在作用域内,但如果方法调用的持续时间超过垃圾回收周期之间的时间,垃圾回收器可能会将您的计时器对象视为超出作用域并将其标记为可回收。添加GC.KeepAlive方法可以强制垃圾回收器等待方法退出后再对计时器对象进行操作。

1
只要方法未返回,即使运行了 100 次 GC 循环,该对象仍然在范围内,因此不是这个问题。似乎 GC 允许进行存活分析并忽略其根集中的“死”变量(可能 GC 在 JIT 代码上工作而不是字节码表示,在这种情况下,这是通常优化的一个简单副作用 - 这样说明是有道理的)。 - Voo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接