Run-Time Use of Metadata

To better understand metadata and its role in the common language runtime, it might be helpful to construct a simple program and illustrate how metadata affects its run-time life. The following code example shows two methods inside a class called MyApp. The Main method is the program entry point, while the Add method simply returns the sum of two integer arguments.

Public Class MyApp
   Public Shared Sub Main()
      Dim ValueOne As Integer = 10
      Dim ValueTwo As Integer = 20
      Console.WriteLine("The Value is: {0}", Add(ValueOne, ValueTwo))
   End Sub
   
   Public Shared Function Add(One As Integer, Two As Integer) As Integer
      Return (One + Two)
   End Function
End Class
[C#]
using System;  
public class MyApp
{
   public static int Main()
   {
      int ValueOne = 10;
      int ValueTwo = 20;         
      Console.WriteLine("The Value is: {0}", Add(ValueOne, ValueTwo));
      return 0;
   }
   public static int Add(int One, int Two)
   {
      return (One + Two);
   }
}

When the code runs, the runtime loads the module into memory and consults the metadata for this class. Once loaded, the runtime performs extensive analysis of the method's Microsoft intermediate language (MSIL) stream to convert it to fast native machine instructions. The runtime uses a just-in-time (JIT) compiler to convert the MSIL instructions to native machine code one method at a time as needed.

The following example shows part of the MSIL produced from the previous code's Main function. You can view the MSIL and metadata from any .NET Framework application using the MSIL Disassembler (Ildasm.exe).

      .entrypoint
      .maxstack  3
      .locals ([0] int32 ValueOne,
               [1] int32 ValueTwo,
               [2] int32 V_2,
               [3] int32 V_3)
      IL_0000:  ldc.i4.s   10
      IL_0002:  stloc.0
      IL_0003:  ldc.i4.s   20
      IL_0005:  stloc.1
      IL_0006:  ldstr      "The Value is: {0}"
      IL_000b:  ldloc.0
      IL_000c:  ldloc.1
      IL_000d:  call int32 ConsoleApplication.MyApp::Add(int32,int32) /* 06000003 */

The JIT compiler reads the MSIL for the whole method, analyzes it thoroughly, and generates efficient native instructions for the method. At IL_000d, a metadata token for the Add method (/* 06000003 */) is encountered and the runtime uses the token to consult the third row of the MethodDef table.

The following table shows part of the MethodDef table referenced by the metadata token that describes the Add method. While other metadata tables exist in this assembly and have their own unique values, only this table is discussed.




Row
Relative Virtual Address (RVA)


ImplFlags



Flags
Name
(Points to string heap.)

Signature (Points to blob heap.)
1 0x00002050 IL

Managed

Public

ReuseSlot

SpecialName

RTSpecialName

.ctor

.ctor (constructor)  
2 0x00002058 IL

Managed

Public

Static

ReuseSlot

Main String
3 0x0000208c IL

Managed

Public

Static

ReuseSlot

Add int, int, int

Each column of the table contains important information about your code. The RVA column allows the runtime to calculate the starting memory address of the MSIL that defines this method. The ImplFlags and Flags columns contain bitmasks that describe the method (for example, whether the method is public or private). The Name column indexes the name of the method from the string heap. The Signature column indexes the definition of the method's signature in the blob heap.

The runtime calculates the desired offset address from the RVA column in the third row and returns this address to the JIT compiler, which then proceeds to the new address. The JIT compiler continues to process MSIL at the new address until it encounters another metadata token and the process is repeated.

Using metadata, the runtime has access to all the information it needs to load your code and process it into native machine instructions. In this manner, metadata enables self-describing files and, together with the common type system, cross-language inheritance.

See Also

Structure and Use of Metadata | Compiling to MSIL | Compiling MSIL to Native Code