【问题标题】:When Are Static Classes In .NET Loaded Into Memory?.NET 中的静态类何时加载到内存中?
【发布时间】:2017-01-14 01:52:47
【问题描述】:

正如标题所示,我对静态类何时加载到 .NET(尤其是 C#)中的内存感兴趣。我认为它类似于 Java 中的this question 和关于静态方法的this question,因为它在第一次使用时被加载。此外,一旦它在内存中,它会一直留在那里直到应用程序终止,还是在垃圾收集器来清理使用它的类时被清理?

我意识到静态类使用的少量内存在具有 8+GB RAM 标准的计算机世界中并不是非常重要,但了解内部结构总是很有趣。

编辑:

这些答案让我想为这个问题添加更多内容并用一个例子来澄清。如果我理解正确,在下面的示例中,Contraption.SomeString 将首先放入内存中,紧随其后的是 Contraption.AnotherString,第一次通过循环。

public static class Contraption
{
    public static string SomeString = "Some String";
    public static string AnotherString = "Another String";
}

public class Processor
{
    public void Process(List<SomeClass> items)
    {
        foreach(var item in items)
        {
            if(item.Name == Contraption.SomeString)
            {
                //do something
            }
            if(item.Name == Contraption.AnotherString)
            {
                //do something
            }
        }
    }
}

【问题讨论】:

    标签: c# .net internals


    【解决方案1】:

    关于静态字段初始化,很重要的一点是static constructor的使用。 CLR 有一个类加载器组件,它加载一个类(元数据信息)并在程序中使用它们时从内存管理器请求内存分配。元数据加载是一次性工作,发布它只是根据需要请求内存

    正如讨论中所理解的那样,静态类变量在第一次使用类时在任何地方加载,并分配内存,但是使用静态构造函数可以确保在调用类加载器时首先初始化它们,它是一次性调用,它可以对类中的所有静态变量进行初始化,这甚至在第一个使用策略之前,因为它在 CLR (mscoree.dll) 是组件时为给定程序加载。

    静态构造函数在任何情况下(程序重启除外)都不会在第一次调用后被调用,即使出现异常,它的应用相当广泛,静态变量也可以通过设置为null来收集

    【讨论】:

    • 所以静态不在编译时分配内存?但是在第一次使用时在运行时?它存储在哪里?堆栈还是堆?
    • @Luminous_Dev 堆栈和堆分配与值或引用类型有关。这与静态/非静态无关
    【解决方案2】:

    我假设您指的是静态类中的字段(或非静态类中的静态字段)。它们将在第一次使用之前被初始化。它在 C# 规范中有所描述:

    10.4.5.1 静态字段初始化

    类的静态字段变量初始化器对应于一系列赋值,它们按照它们在类声明中出现的文本顺序执行。如果类中存在静态构造函数(第 10.11 节),则在执行该静态构造函数之前立即执行静态字段初始值设定项。否则,静态字段初始值设定项会在第一次使用该类的静态字段之前的依赖于实现的时间执行。

    静态类成员被认为是垃圾收集根并且总是可以访问的。

    您可以通过将静态成员重置为null或其他对象来强制回收对象:

    public static class Foo 
    {
        public static object Bar = new object();
    }
    
    // somewhere later
    Foo.Bar = null;
    // the object can be collected now.
    

    【讨论】:

    • 是的。在我发布这篇文章后我意识到,如果没有附带的静态成员,静态类是毫无意义的。
    • new string("My first string here") 是什么意思?
    • @PetSerAl 还有一些与文字字符串和字符串实习相关的额外复杂性。使用new string() 是为了绕过它。我把它改成了一个对象,以减少混乱。
    • @MarcinJuraszek 我不是关于字符串实习的。 System.String 没有接受其他字符串实例的构造函数。如果要创建具有相同值的新字符串实例,则需要调用Copy()
    【解决方案3】:

    静态变量在 AppDomain 的生命周期内持续存在,在 .NET 中,每个应用程序可以有多个 AppDoamins。虽然大多数时候,每个应用程序只有一个 AppDomain,而其他 AppDomain 大多是为沙盒插件创建的。

    https://msdn.microsoft.com/en-us/library/2bh4z9hs(v=vs.110).aspx

    【讨论】:

      猜你喜欢
      • 2023-04-01
      • 2014-02-10
      • 2013-10-19
      • 1970-01-01
      • 1970-01-01
      • 2015-10-21
      • 1970-01-01
      • 2013-09-16
      • 2014-03-11
      相关资源
      最近更新 更多