[.NET Internals 09] Just-In-Time (JIT) compilation

Have you ever heard the term JIT? It’s an acronym for Just-In-Time. JIT compiler is a tool which performs the JIT compilation, which is a crucial feature of .NET applications. Let’s say a few more words on it today 🙂

What makes managed applications portable?

As we know from the previous posts published within the series, .NET Framework and CLR provide a lot of useful features for applications targeting the platform, such as automatic memory management. However, one of the main goals of managed runtimes’ invention was to make implemented applications portable. So what does it mean than an application is portable? It means that, first of all, it can be run on any kind of hardware. Ideally, it should also be software-agnostic (especially OS-agnostic). We can still observe this trend for instance by the fact that Microsoft created ans is actively developing a multi-platform NET Core. Such portability not only makes the application possible to be launched on any hardware or software platform, but also releases developers from taking care about underlying low-level structures. For instance when working with TPL, the programmer normally doesn’t need to change his/her code taking into account the underlying hardware (e.g. number or architecture of CPUs). It’s the same for memory allocation (described in the previous posts) where many close-to-metal details differ based on operating system’s architecture (32/64 bit) – CLR handles it for us. However, at some point, every application needs to be executed by the processor, which requires having a machine code  -assembly instructions understood and possible to be executed by the CPU. Depending on the OS’s or CPU’s architecture it’s sometimes necessary to use completely different CPU instructions sets in the assembly code. As you can guess, to make source code really portable it cannot be directly compiled to machine code. There’s something intermediate needed.

Intermediate Language (IL)

Because of the reasons described above, managed runtimes’ programming languages source code (like C#, F# or Java) is not directly compiled to assembly language. Instead, it’s firstly compiled to an intermediate language (IL).  CLR’s intermediate language is also referred to as MSIL (Microsoft Intermediate Language). Compilation of source code into IL is performed by the particular language’s compiler. This is the process which happens when you build your app by pressing F6 in Visual Studio or using csc.exe to compile your code. Source code -> IL compilation is done by the particular language’s compiler. For instance, C# code is compiled by Roslyn. which is a C# language’s compiler:
Visual Studio’s build – Roslyn

Viewing MSIL

In order to see the MSIL code contained in the compiled EXE/DLL files (like I showed you e.g. here and here), you can use ILSpy Visual Studio extension, which, when installed, adds a menu option in Visual Studio (Tools -> ILSpy), where you can open any compiled file and view the IL code of contained objects:
ILSpy – MSIL code
What is actually compiled into IL code? For now we can say that the most important are methods (grouped into classes, namespaces etc. of course). There are also many other things compiled (even more than you would expect by looking at your source code), but we will focus on the methods for now. OK, so we have the IL code now, but it cannot be understood by the CPU yet. How and when is it then compiled to assembly code?

Just-In-Time (JIT) compilation

Let’s start by some historical background 🙂 In the early 1960s, Japanese engineers at Toyota had to reorganize their warehouse management, because they had very high storage costs – delivery of the parts from suppliers took a lot of time, because they ordered a lot in advance. Every delivery had to be handled by someone, so they needed a lot of employees. Ordered parts were stored in the warehouses for a long time, required a lot or storage space and maintenance. In order to minimize the costs, they invented a just-in-time manufacturing (also known as Toyota Production System). Its main principle was to =&0=&

[.NET Internals 07] Unmanaged resources: finalization, fReachable queue and dispose pattern

Today we’re going to see how unmanaged resources are handled by .NET, what are finalization and fReachable queues and what’s the garbage collector’s role in it. We’ll also get to know what is a dispose pattern and see how to implement it.

Unmanaged resources and finalizers

First of all we should all get familiar with what unmanaged resources are. These ones can be files or folders on the disk, database connections, GUI elements or network resources. You can also think of them as some external elements we need to interact with in our applications through some protocol (e.g. database queries or file system manipulation methods). They’re called unmanaged not without a reason – any unmanaged resources accessed from .NET code will not be automatically cleaned by the garbage collector. That’s how they are not(un)managed. Maybe you’ve heard about

destructors in C++

[.NET Internals 01] Basics of memory structure

Have you ever wondered about what’s under the hood of the applications you develop? Ever been surprised that there’s no need to worry about memory allocation and deallocation using high-level programming languages such as Java or C# after leaving the university? Still remember (old) C++ times with delete statement?
Source: “Arnaud Porterie – The Truth About C++”
By this post, I’d like to introduce a new “.NET Internals” series on the blog. I will be publishing a new post on .NET internal concepts every Wednesday. No end date for the moment 🙂 Posts within the series will be mostly about memory management and performance aspects of .NET applications. All discussed concepts are applicable to most of the modern programming platforms, but the examples will be based on .NET Framework. If you’re interested in such topics, I encourage you to check this blog every Wednesday starting today 🙂 *there is 1 assumption and 1 fact here:
  • assumption: you used to program in C/C++ (before C++11) on the university,
  • fact: that’s not true you don’t need to worry about memory management using high-level programming languages; wait for the next posts to get to know why.


Each application targeting .NET is managed by CLR (Common Language Runtime), which is a part of .NET Framework, which must be installed on the computer on which the .NET application is launched – the exception are

.NET Core self-contained apps