简体   繁体   English

什么时候加载程序集?

[英]When exactly are assemblies loaded?

So I'm trying to understand exactly when .NET Assemblies are loaded into a .NET process. 所以我试图准确理解.NET程序集何时加载到.NET进程中。 I read this blog entry which did a great job of explaining things and confirmed a lot of what I thought I already knew, but it also brought up a point in which I think I slightly misunderstood. 我读了这篇博客文章 ,它很好地解释了一些事情并证实了我认为已经知道的很多东西,但它也提出了一个我认为我有点误解的观点。

Dependent Assemblies are just in time loaded when first referenced in code 在代码中首次引用时,从属程序集只是及时加载

I took this to mean that when and furthermore if the first time a call to an assembly was made then the assembly was loaded into the program. 我认为这意味着第一次调用程序集时,然后将程序集加载到程序中。 So if I have a program like the sample below where the line in which the RasDialer class is instantiated would never be called - I believed that the DotRas assembly would never be loaded into the process and I was definitely wrong about that. 因此,如果我有一个类似于下面示例的程序,其中实例化RasDialer类的行将永远不会被调用 - 我相信DotRas程序集永远不会被加载到进程中,我绝对错了。

However, if the code is truly unreachable as in my commented out section - then the assembly will never load, but it seems that if there is a chance then the assembly will be loaded. 但是,如果代码在我注释掉的部分中确实无法访问 - 那么程序集将永远不会加载,但似乎如果有机会则会加载程序集。

Here is my little test application: 这是我的小测试应用程序:

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());
    }
}

Is there any easy way to tell when an assembly will be loaded into memory? 有没有简单的方法来判断何时将程序集加载到内存中?

In the blog entry that I linked up at the top - his dependent assembly does not load until after his call to PrintAssemblies() , but for mine the dependent assembly loads before the call. 在我在顶部链接的博客条目中 - 他的依赖程序集在调用PrintAssemblies()之后才加载,但是对于我的依赖程序集在调用之前加载。 So it doesn't appear to be easily predictable. 所以它似乎不容易预测。

Am I correct to assume that if there is a chance that a type in the dependent assembly is needed by the JIT compiler it will cause the assembly to be loaded? 我是否正确地假设如果JIT编译器有可能需要依赖程序集中的类型,它将导致程序集被加载?

The Assemblies are loaded as soon as a method that references your assembly get's checked. 一旦引用程序集的方法被检查,就会加载程序集。

Roughly that is, when converting from IL to machine code. 大致就是从IL转换为机器代码。 So as soon as your method references code in another assembly that assembly is loaded. 因此,只要您的方法引用另一个程序集中的代码,即加载程序集。

So in your example, the assembly that contains the RasDialer class, will be loaded on the first time Main is called, just before the executing of the method begins. 因此,在您的示例中,包含RasDialer类的程序集将在第一次调用Main加载,就在方法执行开始之前。

You should be aware that some small methods are inlined (but probably not while debugging). 您应该知道一些小方法是内联的(但可能不是在调试时)。 So code that is inlined, will load referenced assemblies as soon as it gets inlined. 因此,内联的代码将在内联后立即加载引用的程序集。

  void A(object arg0) {
      if (argO == null) {
        ClassFromAssembly1.Call();
        B();
        C();
      }
  }

  void B() {
      ClassFromAssembly2.Call();
  }

  [MethodImpl(MethodImplOptions.NoInlining)]
  void C() {
      ClassFromAssembly3.Call();
  }

As soon as method A is called for the first time, just before the code of method A starts executing, both Assembly1 and probably also Assembly2 are loaded. 只要方法A第一次被调用,就在方法A的代码开始执行之前,就会加载Assembly1和Assembly2。

Assembly3 will be loaded, as soon as the first call to method C is made. 只要第一次调用方法C ,就会加载Assembly3。

The value of arg0 , cannot be used to control the loading of Assembly1. arg0的值不能用于控制Assembly1的加载。 When Assembly2 will be loaded, cannot be determined (depends on the inlining of B). 当Assembly2将被加载时,无法确定(取决于B的内联)。 The loading of Assembly3 can be controlled with the value of arg0 . 可以使用arg0的值来控制Assembly3的加载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM