程序集何时被加载?

8
我正在尝试了解.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编译器需要依赖程序集中的类型,则可能导致程序集被加载?

1个回答

9
一旦引用您的程序集的方法被检查,程序集就会被加载。粗略地说,在从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的内联)。使用arg0的值可以控制Assembly3的加载。


1
这是否意味着如果 C() 从未被调用 - 比如为了与我关于 if 语句的问题保持一致,该语句从未被评估为 true。那么汇编代码将永远不会通过 NoInlining 选项加载? - Derek W
2
我已经更新了我的答案。NoInlining 防止 C 被内联。这使你可以更好地控制何时加载引用的程序集。 - GvS

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