Category Archives: Common Language Runtime

.NET CLR Explained

Inside the CLR


This post aims to provide a summary cheat sheet that outlines the .NET CLR, its key components and features, and inner workings as a frame of reference for developers of every calibre.

Key Points

  • Provides services such as garbage-collection, exception-handling, debugging, and security
  • Compilers output metadata in a format recognisable by the CLR
  • Executes code that has been compiled by a .NET-compliant compiler
  • Automatic memory-management – arguably the primary feature of the CLR
  • Once compiled, all CLR-based languages interface seamlessly

Managed Execution

Managed Execution consists of the following steps:

  • Loading source code
  • Executing source code
  • Providing automatic memory-management through garbage-collection

Managed Code to MSIL

Microsoft Intermediate Language is a common denominator to which all CLR-compliant languages are transformed upon compilation. MSIL can be described as follows:

  • A set of CPU-independent instructions
  • Contains instructions for loading, storing, constructing, and executing methods
  • Removes the need for type libraries or registry entires
  • Exposes metadata, used to generate native code, through portable files

MSIL to Native Code

Native code is code that can be interpreted and executed by a specific OS architecture. Generally speaking, any given application will target one or more OS frameworks. In order to run on these frameworks, compiled MSIL must be compiled further to native code, or code that is specific to a particular environment, or collection of environments. Native code can be described as follows:

  • Runs on OS architecture supported by the underlying MSIL compiler
  • MSIL must be compiled to native code that targets OS architecture
  • This can be achieved either prior to (AOT compiler), or during (JIT compiler) code-execution

JIT Compiler

  • Convert MSIL to managed code at runtime
  • Stores native code in memory
  • Does not load entire assembly
  • Stubs un-called MSIL directives until invoked
  • Loads MSIL stubs to memory when invoked

AOT Compiler (NGEN.exe)

  • Convert MSIL to managed code prior to assembly-execution
  • Loads the entire assembly
  • Persists the generated code to disk in the Native Image Cache

Code Verification

MSIL is subject to a verification process, unless explicitly overridden by policy. The verification process ensures that MSIL adheres to and upholds the contract defined by the CLR in terms of allowing managed-execution. This helps ensure that code is type-safe, and protected from corruption.


The following topics define brief descriptions of CLR key features

Running Code

  • Provides infrastructure to facilitate managed-execution of source code
  • JIT compiles methods as they are invoked
  • Subscribes executing assemblies to garbage-collection, security, debugging services, etc.

Automatic Memory Management

One of the most seismic paradigm shifts in the field of software development has been the advent of frameworks that automatically manage memory. This feature shields developers from the complexities and pitfalls of memory-management, removing complexity and increasing productivity. The following outline key features of automatic memory management in the CLR

Allocating Memory

  • Objects are saved to memory in a contiguous manner (side-by-side)
  • Pointers provide access to Reference Types on the Managed Heap
  • Access to objects is fast and reliable

Releasing Memory

  • Garbage Collector releases memory assigned to objects that are no longer in use
  • Application Roots point to objects currently in memory
  • Unreachable objects are removed from memory
  • Heap-compaction occurs in cases where significant numbers of unreachable objects exist
  • Objects over 85KB in size are assigned to the Large Object Heap

Generations and Performance

  • Managed Heap is divided into 3 Generations
  • Segmentation allows for more effective Heap-compaction
  • New objects are assigned to Generation 0
  • Objects that survive garbage-collection are promoted upwards through Generations
  • Garbage-collection occurs when Generation 0 is full
  • Most objects live and die in Generation 0
  • Certain objects, such as database connections, tend to survive multiple garbage-collection cycles
  • Objects in Generation 2 remain there until they are deemed to be unreachable

Unmanaged Resources

  • Require explicit removal from memory
  • Examples include handles to the OS file system, network connections, etc.
  • Clients explicitly release unmanned resource via Dispose methods

Connect with me: