【问题标题】:Shared Variables and Garbage Collection共享变量和垃圾收集
【发布时间】:2012-02-21 18:00:26
【问题描述】:
我一直在阅读 .NET 中的垃圾收集,希望得到一些澄清。因此,据我所知,如果我声明一个公共共享类变量,GC 将永远不会摆脱它。这是正确的吗?
另外,私有变量呢?举个例子:
public class myClass
private shared myString As String
public sub ChangeString(newString As String)
myString = newString
end sub
end class
如果没有类的实例,共享变量现在会被 GC 吗?如果我将 ChangeString 更改为共享子怎么办?
【问题讨论】:
标签:
.net
vb.net
garbage-collection
【解决方案1】:
所以,据我所知,如果我声明一个公共共享类变量,GC 永远不会摆脱它。这是正确的吗?
几乎。 GC 不会清理共享变量引用的字符串。
但是,如果您使用新字符串调用 ChangeString,则 myString 指向的字符串将不再以此引用为根,并且可能符合 GC 条件。但是,新字符串(由newString 引用)现在将被myString 变量作为根,从而阻止它进行垃圾回收。
如果没有类的实例,共享变量现在会被 GC 吗?
没有。共享变量是对象的根,因为它属于类的“类型”,而不是任何实例。
如果我将 ChangeString 更改为共享子会怎样?
这完全没有效果。
【解决方案2】:
共享变量存在于类本身中,因此您不需要类的实例来使变量存在,因此您的字符串不会被垃圾收集。
变量是否私有无关紧要,它仍然不会被垃圾收集。使用分片方法或实例方法来设置变量都没有关系。
注意:垃圾收集器从不收集变量,它只收集对象。
【解决方案3】:
静态(共享)变量始终被视为根。线程静态(共享)变量是拥有线程的根。因此,这些变量所指的任何内容都不会被 GC 清理。
如果没有类的实例,共享变量现在会被 GC 吗?
因此,如果调用了静态构造函数,则引用对象将在相关生命周期内持续存在(静态的进程和线程静态的线程)。是否存在类的实例并不重要,重要的是静态构造函数是否执行(这有点不确定,您只知道如果需要任何静态成员,它们将在之前创建第一次需要它们)。
如果我将 ChangeString 更改为共享子会怎样?
这没关系。
【解决方案4】:
Shared 变量引用植根于应用程序域。因此,只要应用程序域仍然加载,那么该变量引用的任何对象仍然是根的,因此无论包含类的多少实例可能存在或可能不存在,GC 都不会收集该对象。但是,如果您更改引用,就像在您的特定示例中使用 ChangeString 所做的那样,那么旧对象将不再是根对象,现在可以被收集。
同样,只要您不进行高级应用程序域管理,那么 myString 引用的任何对象都将不符合收集条件,当然,除非您通过重新设置 myString 变量来停止引用该对象。