.NET 中的静态 类 何时加载到内存中?
When Are Static Classes In .NET Loaded Into Memory?
如标题所示,我对何时将静态 classes 加载到 .NET 中的内存很感兴趣,尤其是 C#。我假设它类似于 in Java and this question 关于静态方法,因为它是在第一次使用时加载的。此外,一旦它在内存中,它会一直留在那里直到应用程序终止,或者当垃圾收集器来清理使用它的 class 时它是否被清理?
我意识到静态 class 使用的少量内存在具有 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
}
}
}
}
我假设您指的是静态 classes 中的字段(或 non-static classes 中的静态字段)。它们将在第一次使用前被初始化。它在 C# 规范中有描述:
10.4.5.1 Static field initialization
The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. If a static constructor (Section 10.11) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.
静态 class 成员被视为 垃圾收集根 并且始终可以访问。
您可以通过将静态成员重置为 null
或其他对象来强制回收对象:
public static class Foo
{
public static object Bar = new object();
}
// somewhere later
Foo.Bar = null;
// the object can be collected now.
静态变量在 AppDomain 的生命周期内持续存在,在 .NET 中,每个应用程序可以有多个 AppDoam。虽然大多数情况下,每个应用程序只有一个 AppDomain,而其他 AppDomains 大多是为沙盒插件创建的。
https://msdn.microsoft.com/en-us/library/2bh4z9hs(v=vs.110).aspx
关于静态字段的初始化,很重要的一点是static constructor的用法。 CLR 有一个 class 加载器组件,它加载 class(元数据信息)并在程序中使用时从内存管理器请求内存分配。元数据加载是一次性工作,post 它只是根据需要请求内存
正如讨论中所理解的那样,静态 class 变量在第一次使用 class 时加载,并分配内存,但使用静态构造函数可以确保它们是当 class 加载器被调用时初始化为第一件事,它是一次性调用,它可以对 class 中的所有静态变量进行初始化,这甚至在第一次使用策略之前,因为它何时CLR (mscoree.dll) 是为给定程序加载的组件。
静态构造函数在任何情况下(程序重启除外)都不会在第一次调用后被调用,即使有异常,它的使用非常广泛,静态变量也可以通过设置它们来收集null
如标题所示,我对何时将静态 classes 加载到 .NET 中的内存很感兴趣,尤其是 C#。我假设它类似于
我意识到静态 class 使用的少量内存在具有 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
}
}
}
}
我假设您指的是静态 classes 中的字段(或 non-static classes 中的静态字段)。它们将在第一次使用前被初始化。它在 C# 规范中有描述:
10.4.5.1 Static field initialization
The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. If a static constructor (Section 10.11) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.
静态 class 成员被视为 垃圾收集根 并且始终可以访问。
您可以通过将静态成员重置为 null
或其他对象来强制回收对象:
public static class Foo
{
public static object Bar = new object();
}
// somewhere later
Foo.Bar = null;
// the object can be collected now.
静态变量在 AppDomain 的生命周期内持续存在,在 .NET 中,每个应用程序可以有多个 AppDoam。虽然大多数情况下,每个应用程序只有一个 AppDomain,而其他 AppDomains 大多是为沙盒插件创建的。
https://msdn.microsoft.com/en-us/library/2bh4z9hs(v=vs.110).aspx
关于静态字段的初始化,很重要的一点是static constructor的用法。 CLR 有一个 class 加载器组件,它加载 class(元数据信息)并在程序中使用时从内存管理器请求内存分配。元数据加载是一次性工作,post 它只是根据需要请求内存
正如讨论中所理解的那样,静态 class 变量在第一次使用 class 时加载,并分配内存,但使用静态构造函数可以确保它们是当 class 加载器被调用时初始化为第一件事,它是一次性调用,它可以对 class 中的所有静态变量进行初始化,这甚至在第一次使用策略之前,因为它何时CLR (mscoree.dll) 是为给定程序加载的组件。
静态构造函数在任何情况下(程序重启除外)都不会在第一次调用后被调用,即使有异常,它的使用非常广泛,静态变量也可以通过设置它们来收集null