Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When exactly are assemblies loaded?

So I'm trying to understand exactly when .NET Assemblies are loaded into a .NET process. 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.

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. 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?

like image 635
Derek W Avatar asked Feb 20 '14 17:02

Derek W


1 Answers

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. 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.

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.

Assembly3 will be loaded, as soon as the first call to method C is made.

The value of arg0, cannot be used to control the loading of Assembly1. When Assembly2 will be loaded, cannot be determined (depends on the inlining of B). The loading of Assembly3 can be controlled with the value of arg0.

like image 198
GvS Avatar answered Oct 14 '22 16:10

GvS