程序集究竟何时加载



因此,我正试图准确了解.NET程序集何时加载到.NET进程中。我读了这篇博客文章,它很好地解释了事情,证实了很多我认为我已经知道的事情,但它也提出了一个我认为我有点误解的问题。

依赖程序集在代码

我认为这意味着当并且如果第一次调用程序集时,程序集就会加载到程序中。因此,如果我有一个像下面的示例这样的程序,其中实例化RasDialer类的行永远不会被调用——我相信DotRas程序集永远不会被加载到进程中,我对此肯定是错的。

然而,如果代码真的无法访问,就像我在注释掉的部分中所说的那样,那么程序集将永远不会加载,但如果有机会,程序集似乎会被加载。

这是我的小测试应用程序:

static void Main(string[] args)
{
Console.WriteLine("Before");
var dictionary = new Dictionary<int, string>();
PrintAssemblies(); // <- DotRas is loaded here for null check variant
if (dictionary == null)
{
// This line will never execute, but it does not matter
var dialer = new RasDialer();
}
// DotRas will not be loaded if I uncomment this and comment 
// out the other if statement since it is truly unreachable
//if (false)
//{
//    var dialer = new RasDialer();
//}
Console.WriteLine(Environment.NewLine + "After");
PrintAssemblies();
Console.ReadLine();
}
public static void PrintAssemblies()
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
Console.WriteLine(assembly.GetName());
}
}

有什么简单的方法可以判断程序集何时加载到内存中吗?

在我在顶部链接的博客条目中,他的依赖程序集直到他调用PrintAssemblies()之后才加载,但对于我的依赖程序集,在调用之前加载。因此,这似乎不容易预测。

如果JIT编译器需要依赖程序集中的类型,那么它将导致加载程序集,我的假设正确吗?

一旦检查了引用程序集的方法,就会加载程序集。

大致就是说,当从IL转换为机器代码时。因此,只要您的方法引用了另一个程序集中的代码,就会加载该程序集。

因此,在您的示例中,包含RasDialer类的程序集将在第一次调用Main时加载,就在方法开始执行之前。

您应该知道,有些小方法是内联的(但可能不是在调试时)。因此,内联的代码将在内联后立即加载引用的程序集。

void A(object arg0) {
if (argO == null) {
ClassFromAssembly1.Call();
B();
C();
}
}
void B() {
ClassFromAssembly2.Call();
}
[MethodImpl(MethodImplOptions.NoInlining)]
void C() {
ClassFromAssembly3.Call();
}

一旦第一次调用方法A,就在方法A的代码开始执行之前,Assembly1和Assembly2都会被加载。

一旦对方法C进行了第一次调用,就会加载Assembly3。

arg0的值不能用于控制Assembly1的加载。Assembly2将在何时加载,无法确定(取决于B的内联)。Assembly3的加载可以通过arg0的值来控制。

最新更新