静态类/成员分配在哪里?

4

我一直在尝试找出静态类的真相已经有很长一段时间了。我的观点是:值类型在使用new运算符时分配在堆栈中,引用类型在堆中分配。但静态类的本质是您无法创建其实例,并且它肯定不是值类型。那么,我有一个问题:CLR何时在哪里为静态内容分配内存?关于何时...我假设是在编译期间,当构建程序集时,但我不确定。至于在哪里...当我试图找出时,我阅读了J.Richter的“CLR via C#”,他写道,当您创建该特定类的实例(与类型对象指针和同步块索引一起)时,实例类的静态方法在堆中分配。但我不明白。它是静态的。它不应该依赖于任何对象状态。所以,请给我解释一下。


1
静态成员和构造函数(我相信你引用的文本是指这些)与静态类之间有区别。您是否知道这种区别?如果知道,您具体是在询问哪一个? - strager
嗯...我知道的区别不在于内存分配,对吧? 这里,我正在询问静态类的内存分配。我提到静态方法,只是因为Richter的书中有一个例子。但如果静态类和实例类的静态成员的分配有任何区别,我想知道它。 - Mark
1
值类型并不总是分配在堆栈上,这是不正确的说法。 - Steven Sudit
当然,但这并不是此问题的重点。 - Mark
2个回答

4
CLR维护与AppDomain相关的几个堆,称为“加载器堆”。它们不同于垃圾回收堆,因为它们不包含可回收对象,主要是类型相关数据。这些数据在AppDomain的生命周期内存在。
静态变量的空间分配在其中一个堆中,即HighFrequencyHeap。JIT编译器进行分配,生成的代码直接引用内存位置。有关背景信息,请参见此MSDN Magazine文章

1

除了用户堆内存,CLR还在堆上保留各种簿记信息和元数据。这包括您执行方法的实际代码,以及为每个加载到AppDomain中的类型加载的Type对象——它的名称、重载、是否为抽象或密封,以及在该类型上定义的所有静态和实例方法的列表。

当您执行一个方法时,CLR会在堆的CLR专用部分中查找相应的Type对象中的方法信息,并执行该方法。静态方法和实例方法之间唯一的区别在于,实例方法在方法参数中包含一个额外的“this”指针,指向方法所执行的实例。

因此,静态信息与其他所有内容一样存储在堆上,但它不与任何特定的对象实例关联。


是的,这很有道理!谢谢!所以,所有这个实例和静态类的东西看起来都很欺骗人。它只是一个额外的“this”指针,但它们都被保存在同一个地方...同样的方式。非常感谢。 - Mark

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