【问题标题】:Do static members ever get garbage collected?静态成员是否曾经被垃圾收集?
【发布时间】:2011-09-29 19:34:42
【问题描述】:

静态成员变量会被垃圾回收吗?

例如,让我们使用下面的类。

public class HasStatic {
    private static List<string> shared = new List<string>();

}

假设它是这样使用的:

//Startup
{
HasStatic a = new HasStatic();
HasStatic b = new HasStatic();
HasStatic c = new HasStatic();
HasStatic d = new HasStatic();
//Something
}
//Other code
//Things deep GC somewhere in here
HasStatic e = new HasStatic();

abcd 被垃圾回收时,静态成员shared 是否也会被回收? e 能否获得shared 的新实例?

【问题讨论】:

  • 请记住a.shared[1]b.shared[1] 具有相同的值,并且HasStatic 的这个元素也可以通过HasStatic.shared[1] 引用。 (当然,假设shared 列表中至少有 2 个元素。)

标签: c# garbage-collection static-members


【解决方案1】:

不,静态成员与 Type 相关联,Type 与加载它的 AppDomain 相关联。

请注意,对于要初始化的类和 shared 变量引用 List&lt;string&gt;,不必有 任何HasStatic 实例。

除非您考虑卸载 AppDomain 的情况,否则静态变量可以永远视为 GC 根。 (当然,如果更改 HasStatic.shared 的值以引用不同的实例,则第一个实例可能有资格进行垃圾回收。)

【讨论】:

  • +1。我对此非常确定,但需要进行测试才能验证。 ...甚至可以在我的 C# in Depth 书中查找它!哈哈
  • 有两个例外需要提及。通过WeakReference 引用的任何内容都可以被垃圾回收,任何实例化为ThreadLocal 且线程终止的静态成员也是如此。
  • 这是一个非常古老的答案,我知道,但我有一个后续问题,Jon:鉴于括号中的最后一句话:是什么决定了原始实例是否有资格进行垃圾收集?
  • @ChrisRidge:和其他任何事情一样:基本上是否有任何方法可以到达对象。
  • 如果将静态成员设置为null会怎样?根据我一直在阅读的内容,这将使其可用于 GC。
【解决方案2】:

我要添加到 Jon 的出色答案中的唯一一点是 CLR 4 支持“可收藏的程序集”。如果您动态生成可回收程序集,那么当程序集被垃圾回收时,其类型的静态信息就会消失。

有关该功能的简要概述,请参阅此 msdn 文章:

http://msdn.microsoft.com/en-us/library/dd554932%28VS.100%29.aspx

【讨论】:

  • 这些在实践中的效果如何?是不是有很多(用户)代码缓存反射数据,从而使类型和程序集保持活动状态?
  • 哇...以前从未听说过这些。学习新东西总是很高兴。
  • @CodeInChaos:如果用户代码缓存了保持更大对象存活的数据,那么系统可以工作。这就是垃圾收集的全部意义,就是让可访问的东西保持活力。可收集程序集的理由是相反的问题:我们希望能够在临时程序集中生成临时代码,当它们都无法访问时这些临时代码就会消失。在可收集的组件之前,我们无法做到这一点。
  • 我的意思是代码通过缓存一旦类型不再存在就过时的类型相关信息,意外地使该可收集程序集保持活动状态。我创建了一个问题,因为这在 cmets 中讨论起来有点复杂:stackoverflow.com/questions/6601502/caching-reflection-data
  • @Eric:那么,WeakReferences 和 ThreadLocal 成员可能也值得一提。
猜你喜欢
  • 1970-01-01
  • 2018-08-15
  • 1970-01-01
  • 2016-02-29
  • 1970-01-01
  • 2010-10-01
  • 1970-01-01
  • 2020-02-11
  • 1970-01-01
相关资源
最近更新 更多