Condividi tramite


Utilizzo dei metadati in fase di esecuzione

Per meglio comprendere i metadati e il ruolo che essi rivestono in Common Language Runtime, può essere utile creare un piccolo programma e illustrare come i metadati ne influenzino l'esecuzione. Nell'esempio di codice che segue vengono mostrati due metodi all'interno di una classe denominata MyApp. Il metodo Main è il punto di ingresso del programma, mentre il metodo Add restituisce semplicemente la somma di due argomenti integer.

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
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);
   }
}

Durante l'esecuzione del codice, il runtime carica il modulo in memoria e cerca questa classe nei metadati. Dopo il caricamento, il runtime compie un'analisi approfondita del flusso Microsoft Intermediate Language (MSIL) del metodo per convertirlo in veloci istruzioni macchina native. Il runtime consente di utilizzare un compilatore JIT (Just-In-Time) per convertire le istruzioni MSIL in codice macchina nativo, procedendo un metodo alla volta, in base alle necessità.

Nell'esempio che segue viene illustrata parte del codice MSIL prodotto dalla funzione Main del codice precedente. È possibile vedere il codice MSIL e i metadati di qualsiasi applicazione .NET Framework utilizzando 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 */

Il compilatore JIT legge il codice MSIL dell'intero metodo, lo analizza approfonditamente, quindi genera efficienti istruzioni native corrispondenti. All'istruzione IL_000d il runtime incontra un token di metadati che punta al metodo Add (/* 06000003 */); il token viene utilizzato per consultare la terza riga della tabella MethodDef.

Nella tabella che segue viene illustrata la parte di MethodDef a cui fa riferimento il token di metadati che descrive il metodo Add. Benché questo assembly includa altre tabelle di metadati, ciascuna con i propri valori univoci, viene qui discussa solo questa tabella.

Riga

RVA (Relative Virtual Address)

ImplFlags

Flag

Nome

(punta all'heap delle stringhe)

Firma (punta all'heap dei blob)

1

0x00002050

IL

Gestito

Public

ReuseSlot

SpecialName

RTSpecialName

.ctor

.ctor (costruttore)

 

2

0x00002058

IL

Gestito

Public

Static

ReuseSlot

Main

String

3

0x0000208c

IL

Gestito

Public

Static

ReuseSlot

Add

int, int, int

Ogni colonna della tabella contiene importanti informazioni sul codice. La colonna RVA consente al runtime di calcolare l'indirizzo di memoria iniziale del codice MSIL che definisce questo metodo. Le colonne ImplFlags e Flag contengono maschere di bit che descrivono il metodo (indicano ad esempio se il metodo è pubblico o privato). La colonna Nome indicizza il nome del metodo nell'heap delle stringhe. La colonna Firma indicizza la definizione della firma del metodo nell'heap dei blob.

Il runtime calcola l'indirizzo di offset desiderato dalla colonna RVA nella terza riga e restituisce tale indirizzo al compilatore JIT, che quindi procede con il nuovo indirizzo. Il compilatore JIT continua a processare il codice MSIL al nuovo indirizzo fino a quando incontra un altro token di metadati e il processo si ripete.

Grazie ai metadati, il runtime ha accesso a tutte le informazioni necessarie per caricare il codice e convertirlo in istruzioni macchina native. In questo modo, i metadati consentono l'esistenza dei file autodescrittivi e, unitamente al sistema di tipi comune, l'ereditarietà tra linguaggi diversi.

Vedere anche

Concetti

Metadati e componenti auto-descrittivi

Processo di esecuzione gestita