I started discussing this topic at as part of my previous post, but I decided a dedicated post would be better to delve deeper and include code examples.
Here’s a recap of the key point from my last post:
In .Net, an assembly is loaded the first time a method using its classes is JIT-compiled. This happens before execution, so the runtime can’t know if the code needing that assembly will actually be reached (like code within an unexecuted ‘if’ block). This has performance implications, particularly for time-critical applications, as unnecessary assembly loading can be avoided with careful coding. In contrast, Java’s HotSpot JVM, with its initial interpretation phase, loads classes on-demand, at the instruction level, not the method level. This means a class is only loaded when its first instruction is interpreted.
Let’s illustrate the Java behavior first:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| public static void main(String[] args) throws java.io.IOException{
System.out.println("Started");
System.out.println("insert option: B or P");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine();
System.out.println(input.length());
if (input.equals("P")){
Person p = new Person("Xana");
System.out.println("Person created");
}
else{
Book b = new Book();
System.out.println("Book created");
}
input = br.readLine();
}
|
Running this with the ‘-verbose’ option shows that classes ‘Book’ or ‘Person’ are loaded only when they’re first used (new Person()
or new Book()
), demonstrating that class loading in Java is tied to actual execution, not just method compilation.
For a deeper look, refer to this: 
Feel free to experiment with the code here: grab the code here
Moving on to .Net, I revisited some older tests and decided to create a clearer example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
| class Parser
{
[MethodImpl(MethodImplOptions.NoInlining)]
public void ParseFile(string fileType)
{
Console.WriteLine ("ParseFile");
if (fileType == "xml")
{
XmlDocument doc = new XmlDocument();
}
else{/*do something here*/}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public void ParseFileAssemblyAware(string fileType)
{
Console.WriteLine ("ParseFileAssemblyAware");
if (fileType == "xml")
this.ParseXml();
else{/*do something here*/}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void ParseXml()
{
Console.WriteLine ("ParseXml");
XmlDocument doc = new XmlDocument();
}
}
class App
{
public static void Main(string[] args)
{
Console.WriteLine("started");
AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(delegate(object sender, AssemblyLoadEventArgs args1)
{
Console.WriteLine("ASSEMBLY LOADED: " + args1.LoadedAssembly.FullName);
});
Parser parser = new Parser();
Console.WriteLine("file type (xml or other)?");
string fileType = Console.ReadLine();
Console.WriteLine("AssemblyLoadingAware (Y or N)?");
bool assemblyLoadingAware = Console.ReadLine().ToLower() == "y";
if(assemblyLoadingAware)
parser.ParseFileAssemblyAware(fileType);
else
parser.ParseFile(fileType);
}
}
```[The source](http://wwww.telecable.es/personales/covam1/deployToNenyures/SourceCode/AssemblyClassLoading/AssemblyLoadTest2012_v2.cs)
Here's what we observe when running this on the .Net CLR:
* At the start of 'Main', the 'System.Xml' assembly is not yet loaded.
* Choosing "No" for "AssemblyLoadingAware" causes 'System.Xml' to load when calling 'ParseFile'. This happens because the entire method is JIT-compiled, and the JIT compiler, upon seeing a reference to 'XmlDocument', triggers the assembly load, regardless of whether the code using it will actually be executed.
* Choosing "Yes" for "AssemblyLoadingAware" and providing input "other", the 'System.Xml' assembly is not loaded. This is because we've moved the XML handling code to a separate method ('ParseXml'). So, when 'ParseFileAssemblyAware' is JIT-compiled, there's no direct 'XmlDocument' reference, delaying the assembly load until (and if) 'ParseXml' is called.
You can find a more detailed breakdown here: [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiocm4JCLzZNFUVrjMg_HsuD0OlyP-N1pchdkAweAHHFEcFo55fTWXJl5SIu8rJFIq2-gtdZu9Ivadtr0DaKBY1B_tD074tsY_YWntfV87i8mBOr2nIsLtSzZ1ICOyeJBa1SJlrFpBWJQ-/s1600/CLR.jpg)
The key takeaway for .Net development, particularly for performance-sensitive applications, is to be mindful of such scenarios. Unnecessary assembly loading impacts both memory footprint and execution time.
It's important to note the use of the `[MethodImpl(MethodImplOptions.NoInlining)]` attribute on the methods in 'Person'. This prevents the JIT compiler from inlining these short methods into 'Main', which would otherwise mask the assembly loading behavior we're trying to illustrate. Without it, 'System.Xml' would be loaded prematurely during 'Main' compilation, before our assembly load handler is attached. You can verify this using tools like ProcessExplorer.
[MethodImpl](http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimplattribute.aspx)


|