Compilation du MSIL en code natif

Mise à jour : novembre 2007

Avant d'exécuter le langage MSIL (MicroSoft Intermediate Language), vous devez le compiler en code natif avec le Common Language Runtime pour l'architecture de l'ordinateur cible. Le .NET Framework propose deux méthodes de conversion :

Compilation à l'aide du compilateur juste-à-temps

La compilation JIT convertit à la demande le langage MSIL en code natif au moment de l'exécution de l'application, lorsque le contenu d'un assembly est chargé et exécuté. Dans la mesure où le Common Language Runtime fournit un compilateur JIT pour chaque architecture de processeur qu'il prend en charge, les développeurs peuvent générer un jeu d'assemblys MSIL pouvant être traité par un compilateur JIT et exécuté sur différents ordinateurs ayant des architectures d'ordinateur différentes. Cependant, votre code managé s'exécutera sur un système d'exploitation spécifique uniquement s'il appelle des API natives spécifiques à une plateforme ou une bibliothèque de classes spécifique à une plateforme.

La compilation JIT tient compte du fait qu'une partie du code ne sera peut-être jamais appelée au moment de l'exécution. Au lieu de consacrer du temps et des ressources mémoire à la conversion de toutes les instructions MSIL d'un fichier exécutable portable (PE) en code natif, elle les convertit au fur et à mesure des besoins au moment de l'exécution et stocke le code natif obtenu en mémoire afin qu'il soit accessible pour les appels ultérieurs dans le contexte de ce processus. Le chargeur crée et attache un stub à chaque méthode dans un type lorsque le type est chargé et initialisé. Lorsqu'une méthode est appelée pour la première fois, le stub passe le contrôle au compilateur JIT, qui convertit le MSIL de cette méthode en code natif et modifie le stub afin de pointer directement vers le code natif généré. Les appels suivants à la méthode traitée par le compilateur JIT passent alors directement au code natif.

Génération du code d'installation à l'aide de NGen.exe

Comme le compilateur JIT convertit le MSIL d'un assembly en code natif lorsque les méthodes individuelles définies dans cet assembly sont appelées, les performances sont nécessairement altérées au moment de l'exécution. Dans la plupart des cas, cette baisse de performances est acceptable. Et surtout, le code généré par le compilateur JIT est lié au processus qui a déclenché la compilation. Il ne peut pas être partagé entre plusieurs processus. Pour que le code généré puisse être partagé entre plusieurs appels d'une application ou entre plusieurs processus partageant un jeu d'assemblys, le Common Language Runtime prend en charge un mode de compilation à l'avance. Ce mode de compilation utilise le Outil Native Image Generator Tool (Ngen.exe) pour convertir les assemblys MSIL en code natif de façon similaire au compilateur JIT. Toutefois, le fonctionnement de Ngen.exe diffère de celui du compilateur JIT sur trois points :

  • Il effectue la conversion du MSIL en code natif avant et non pendant l'exécution de l'application.

  • Il compile un assembly entier, plutôt qu'une méthode à la fois.

  • Il conserve le code généré dans le cache des images natives comme un fichier sur le disque.

Vérification du code

Dans le cadre de la compilation du MSIL en code natif, le code MSIL est soumis à un processus de vérification, sauf si un administrateur a établi une stratégie de sécurité qui autorise le code à ignorer ce processus. La vérification examine le MSIL et les métadonnées afin de déterminer si le code est de type sécurisé, ce qui signifie qu'il ne doit accéder qu'aux emplacements de mémoire autorisés. La sécurité de type permet d'isoler les objets les uns des autres et de les protéger par conséquent de toute altération accidentelle ou malveillante. Elle garantit également que les restrictions liées à la sécurité peuvent être appliquées au code de manière fiable.

Le runtime s'appuie sur le fait que les instructions suivantes sont vraies pour le code de type sécurisé vérifié :

  • une référence à un type qui est strictement compatible avec le type référencé ;

  • seules les opérations définies de façon appropriée sont appelées pour un objet ;

  • les identités sont conformes à ce qu'elles prétendent être.

Pendant le processus de vérification, le code MSIL est examiné en vue d'essayer de confirmer qu'il peut accéder aux emplacements de mémoire et appeler des méthodes uniquement par le biais de types correctement définis. Par exemple, le code n'autorise pas l'accès aux champs d'un objet d'une manière qui accepte le débordement de capacité des emplacements de mémoire. Par ailleurs, le processus de vérification inspecte le code MSIL afin de déterminer s'il a été généré correctement, car un code MSIL incorrect peut donner lieu à une violation des règles de sécurité des types. Le processus de vérification passe un jeu de code de type sécurisé et correctement défini, et ne passe que du code de ce type. Cependant, une partie du code de type sécurisé peut ne pas passer le test de vérification avec succès en raison de certaines limitations du processus de vérification, et certains langages, de par leur design, ne produisent pas un code de type sécurisé vérifié. Si le code de type sécurisé est requis par la stratégie de sécurité mais qu'il ne passe pas le test de vérification avec succès, une exception est levée lorsque le code est exécuté.

Voir aussi

Concepts

Processus d'exécution managée