什么时候加载程序集?

Der*_*k W 3 .net jit .net-assembly

所以我试图准确理解.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());
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有简单的方法来判断何时将程序集加载到内存中?

在我在顶部链接的博客条目中 - 他的依赖程序集在调用之后才加载PrintAssemblies(),但是对于我的依赖程序集在调用之前加载.所以它似乎不容易预测.

我是否正确地假设如果JIT编译器有可能需要依赖程序集中的类型,它将导致程序集被加载?

GvS*_*GvS 6

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

大致就是从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();
  }
Run Code Online (Sandbox Code Playgroud)

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

一旦第一次调用方法,就会加载Assembly3 C.

arg0,不能用于控制Assembly1的加载.当Assembly2将被加载时,无法确定(取决于B的内联).可以使用值来控制Assembly3的加载arg0.

  • 我已经更新了我的答案。NoInlined 阻止 C 被内联。这使您可以更好地控制何时加载引用的程序集。 (2认同)