Compilazione di MSIL in codice nativo
Prima di potere eseguire Microsoft Intermediate Language (MSIL), è necessario convertire il codice con un compilatore JIT di .NET Framework in codice nativo, un codice specifico per la CPU eseguito sulla stessa architettura di computer del compilatore JIT. Poiché in Common Language Runtime viene fornito un compilatore JIT per ogni architettura di CPU supportata, gli sviluppatori possono scrivere una serie di istruzioni MSIL compilabili in modalità JIT ed eseguibili su computer con architetture diverse. Il codice gestito, tuttavia, potrà essere eseguito solo su uno specifico sistema operativo se presenta chiamate ad API native specifiche della piattaforma o una libreria di classi specifica della piattaforma.
La compilazione JIT tiene in considerazione la possibilità che parte del codice non venga mai chiamato durante l'esecuzione. Anziché impiegare tempo e memoria per convertire tutto il codice MSIL in un file eseguibile portabile (PE) in codice nativo, viene convertito solo il codice MSIL necessario in fase di esecuzione, mentre il codice nativo risultante viene memorizzato affinché vi possano accedere le chiamate successive. Una volta che un tipo è stato caricato, viene creato uno stub che è poi associato a ciascun metodo del tipo. Alla chiamata iniziale del metodo, lo stub passa il controllo al compilatore JIT, il quale converte il codice MSIL scritto per quel metodo in codice nativo e modifica lo stub in modo che indirizzi l'esecuzione alla posizione del codice nativo. Le successive chiamate del metodo compilato in modalità JIT vengono eseguite direttamente al codice nativo precedentemente generato, riducendo il tempo necessario per la compilazione JIT e per l'esecuzione del codice.
Con il runtime è disponibile un'ulteriore modalità di compilazione, denominata generazione di codice in fase di installazione. Tale modalità consente di convertire il codice MSIL in codice nativo esattamente come con il compilatore JIT, ma per unità maggiori di codice alla volta. Il codice nativo risultante viene memorizzato per essere utilizzato quando l'assembly sarà successivamente caricato ed eseguito. Quando si utilizza la generazione di codice in fase di installazione, l'intero assembly in fase di installazione viene convertito in codice nativo, sulla base delle informazioni relative agli assembly già installati. Il file risultante viene quindi caricato e avviato in modo più rapido rispetto a un file convertito in codice nativo con l'opzione JIT standard.
Durante la compilazione di MSIL in codice nativo, è necessario che il codice passi un processo di verifica, a meno che un amministratore non abbia stabilito criteri di protezione in base ai quali il codice può evitare la verifica. Durante la verifica, MSIL e i metadati vengono esaminati per determinare se il codice è indipendente dai tipi, il che significa che accede solo alle posizioni di memoria cui è autorizzato ad accedere. L'indipendenza dai tipi permette di isolare gli oggetti gli uni dagli altri e pertanto consente di proteggerli da danneggiamenti accidentali o intenzionali. Tale requisito garantisce inoltre che le restrizioni di protezione vengano imposte sul codice in modo affidabile.
In Common Language Runtime si presuppone che per il codice indipendente dai tipi verificabile siano valide le seguenti affermazioni :
Un riferimento a un tipo è strettamente compatibile con il tipo a cui si fa riferimento.
Solo gli operatori definiti in modo appropriato vengono richiamati su un oggetto.
Le identità corrispondono effettivamente a ciò che rappresentano.
Durante il processo di verifica, il codice MSIL viene esaminato per confermare la possibilità di accedere alle posizioni di memoria e chiamare metodi solo tramite tipi definiti correttamente. Il codice, ad esempio, non può consentire l'accesso ai campi di un oggetto secondo modalità che consentono il sovraccarico di posizioni di memoria. Il codice MSIL viene inoltre esaminato per verificare che sia stato generato correttamente, in quanto codice MSIL non corretto può condurre a violazioni delle regole relative all'indipendenza dai tipi. Il processo di verifica può essere superato solo da un gruppo ben definito di codice indipendente dai tipi. È tuttavia possibile che parte del codice indipendente dai tipi non superi la verifica a causa delle limitazioni del processo di verifica e che, per motivi legati alla progettazione, alcuni linguaggi non generino codice verificabile come indipendente dai tipi. Se i criteri di protezione richiedono codice indipendente dai tipi e il codice non supera la verifica, al momento dell'esecuzione verrà generata un'eccezione.