The Common Language Runtime (CLR) provides a
new technology for integrating software components from multiple organizations.
The CLR provides a pervasive type system that spans programming language
and operating system boundaries.
While the other tracks focus on various ways of communicating with the
world outside the CLR, this track focuses on the architecture of the CLR
itself: from assemblies, threading, and garbage collection, to security,
debugging, and techniques for interoperating with your existing COM components.
If you need absolute mastery over the .NET CLR, only one book delivers
what you're looking for: Compiling for the .NET Common Language Runtime
(CLR) by John Gough.
Microsoft's long-term decision to replace COM with the CLR, you should
strive to understand the underlying advantages of migrating from the
old runtime environment to the new one. The architects that designed
the CLR and the .NET platform were able to incorporate the best aspects
of COM while alleviating much of the pain of writing and deploying COM-based
applications.
- Vastly simplified development
- Seamless integration of code written in various languages
- Evidence-based security with code identity
- Assembly-based deployment that eliminates DLL Hell
- Side-by-side versioning of reusable components
- Code reuse through implementation inheritance
- Automatic object lifetime management
- Self describing objects
Code which targets the CLR can be run on several platforms

CLR Architecture

Code in the form of IL must undergo JIT compilation
The Common Language Runtime (CLR)
The CLR is the heart and soul of .NET. The CLR is the runtime.
It loads your code, manages it, runs it and provides a number if support
services. Some of these vital support services include resource management,
thread management, remoting, as well as enforcing code safety and security
constraints. Code that is loaded and running under the control of the
CLR is referred to as managed code. Compiled code in .NET does not contain
assembly language instructions. Rather, code is compiled into assemblies
that contain Microsoft Intermediate Language (MSIL). MSIL is a low level
language, similar in idea to Java byte-code. The MSIL is NOT interpreted.
It is JIT-compiled into native machine code.
The runtime offers an impressive list of features. These
include self-describing components through the use of metadata, trust
and security sandboxing, memory management, cross-language integration,
simple deployment, and versioning.
When I said above, that code consists of MSIL, I didnt state the
whole picture. In addition to the programs logic, .NET compilers
all emit metadata. So when a PE file (DLL or exe) is created into an
assembly, that file will also contain metadata. That metadata describes
the types, members and references in the code. What is the metadata
used for? Well, one use is that the CLR uses it to locate and load classes,
prepare space in memory, resolve method invocations, generate native
code and enforce security constraints. An assembly is a group of resources
and types, along with metadata about those resources and types that
is deployed as a unit. The metadata is called an assembly manifest and
includes information such as a list of types and resources visible outside
the assembly. The manifest also includes information about dependencies,
such as the version of the assemblies used when the assembly was built.
This metadata used to describe types, members and references is done
in terms of the Common Type System (CTS). The CLR depends on the CTS.
The CTS describes a standard set of types and rules for creating those
types. The .NET languages must conform to the CTS. The CLR knows how
to make and manage these types and provides these services to the languages.
This is also what is meant by self-describing components. Since the
metadata travels with the assembly, an assembly is completely self-describing.
No more type libraries!
This type system provides the basis for the CLRs impressive multi-language
capability. An object can be defined in VB.NET, and then called from
a C# object, which is then called from an Eiffel.NET object. It is easy
to design components and applications that interact across languages.
. You can also pass an instance of a class to a method of a class written
in a different language. This cross-language integration is possible
because language compilers and tools that target the runtime use a common
type system defined by the runtime, and they follow the runtime's rules
for defining new types, as well as for creating, using, persisting,
and binding to types. Separate IDL files, type libraries, or proxy/stubs
are not required to access a component across language or process boundaries;
the necessary information is located in the component's metadata.
Assemblies can be private to an application or shared by multiple applications.
Multiple versions of an assembly can be deployed on a machine at the
same time. Application configuration information defines where to look
for assemblies, thus the runtime can load different versions of the
same assembly for two different applications that are running concurrently.
This eliminates issues that arise from incompatibilities between component
versions, improving overall system stability. If necessary, administrators
can add configuration information, such as a different versioning policy,
to assemblies at deployment time, but the original information provided
at build time is never lost.
Because assemblies are self-describing, no explicit registration with
the operating system is required. Application deployment can be as simple
as copying files to a directory tree...). This is what is meant by x-copy
deployment. Configuration information is stored in XML files that can
be edited by any text editor.
Perhaps the most touted and needed service of the runtime is of automatic
memory management. The runtime automatically handles object layout and
deletion and reclamation of memory resources through the use of garbage
collection. Objects that are no longer in use are released automatically.
This, of course, eliminates memory leaks as well as some programming
errors.
Finally, the runtime also supplies integrated, pervasive security services
to ensure that unauthorized users cannot access resources on a machine
and that code cannot perform unauthorized actions. This improves overall
system safety and reliability. Since the runtime is used to load code,
create objects, and make method calls, the runtime can perform security
checks and enforce security policy as managed code is loaded and executed.
The CLR Execution Model
As stated previously, the .NET compilers spit out MSIL to an assembly.
What is this IL? Well, its simply instructions for a virtual machine,
the CLR. It is always executed indirectly through the use of a Just-In-Time
(JIT) compiler. The JIT compiler knows how to translate the IL into
native machine instructions for whatever platform the CLR is implemented
on. Notice that I said whatever Platform. There is nothing
in the CLR design or .NET for that matter that assumes Windows. The
CLR is portable by design and we may see ports to various platforms
in the future. Its also important to note that the machine code is not
saved to a file, and is cached, such that the program can be re-executed.
The assemblies are usually demand-loaded and then JIT-ed at the time
of loading. At load time, the assembly goes through some level of verification.
The most basic check is that the CLR has to be able to make sense of
the IL in order to generate machine code. Higher levels of checking
enable the execution engine to ensure that the assembly is memory-safe.