Compilação MSIL para código nativo
Antes de poder executar Microsoft Intermediate Language (MSIL), ele deve ser compilado contra o Common Language Runtime para código nativo contra o Common Language Runtime para a arquitetura da máquina de destino.O .NET Framework fornece duas maneiras para realizar essa conversão:
Um Compilador .NET Framework just-in-time (JIT).
O Nativo Gerador de Imagem (Ngen.exe) do .NET Framework.
A compilação pelo compilador just-in-time
A compilação JIT converte MSIL para código nativo por demanda no tempo de execução do aplicativo, quando o conteúdo de um assembly é carregado e executado.Devido ao fato de que o Common Language Runtime fornece um compilador JIT para cada arquitetura de CPU suportada, os desenvolvedores podem gravar um conjunto de assemblies MSIL que pode ser compilado pelo JIT e executado em computadores com arquiteturas de máquina diferentes.Entretanto, seu código gerenciado será executado apenas por um sistema operacional específico se ele chama APIs nativas específicas da plataforma, ou uma biblioteca de classes específica da plataforma.
Compilação JIT leva em consideração o fato que alguns códigos podem nunca ser chamados durante a execução.Em vez de usar tempo e memória para converter todo o MSIL em um arquivo PE para código nativo, ele converte o MSIL conforme necessário durante a execução e armazena o código nativo resultante na memória para que seja acessível para chamadas subsequentes no contexto desse processo.O carregador cria e anexa um stub para cada método em um tipo quando o tipo é carregado e inicializado.Quando um método é chamado pela primeira vez, o stub passa o controle para o compilador JIT, que converte o MSIL para esse método em código nativo e modifica o stub para apontar diretamente para o código nativo gerado.Chamadas subsequentes do método compilado pelo JIT, portanto, vão diretamente para o código nativo.
Geração de Código Install-Time Usando NGen.exe
Como o compilador JIT converte o MSIL de um assembly para código nativo quando métodos individuais definidos nesse assembly são chamados, isso necessariamente envolve uma perda desempenho no tempo de execução.Na maioria dos casos, essa perda de desempenho é aceitável.Mais importante, o código gerado pelo compilador JIT é vinculado ao processo que disparou a compilação.Ele não pode ser compartilhado por vários processos.Para permitir que o código gerado seja compartilhado por várias invocações de um aplicativo ou por vários processos que compartilham um conjunto de assemblies, o Common Language Runtime suporta um modo de compilação antecipado.Este modo de compilação antecipado usa o Nativo Gerador de Imagem (Ngen.exe) para converter assemblies MSIL para código nativo de maneira semelhante a do compilador JIT.No entanto, a operação do Ngen.exe é diferente da do compilador JIT de três maneiras:
Ele executa a conversão de MSIL para código nativo antes em vez de durante a execução do aplicativo.
Ele compila um assembly inteiro por vez, em vez de um método por vez.
Ele mantém o código gerado no Native Image Cache como um arquivo no disco.
Verificação de Código
Como parte da compilação MSIL para código nativo, o código MSIL deve passar por um processo de verificação a menos que um administrador tenha estabelecido uma política de segurança que permite ao código ignorar essa verificação.A verificação examina o MSIL e metadados para descobrir se o código é com segurança de tipos, o que significa que ele somente acessa os locais de memória que ele está autorizado para acessar.Segurança de tipo ajuda a isolar objetos uns dos outros e portanto ajuda a protegê-los de danos não intencionais ou mal-intencionados.Também fornece garantia que restrições de segurança no código podem ser aplicadas confiávelmente.
O Runtime depende de que as seguintes declarações sejam verdadeiras para o código que é verificável com segurança de tipos:
Uma referência a um tipo é estritamente compatível com o tipo sendo referenciado.
Somente operações adequadamente definidas são chamadas em um objeto.
Identidades são o que elas afirmam ser.
Durante o processo de verificação, código MSIL é examinado em uma tentativa de confirmar que o código pode acessar locais de memória e chamar métodos apenas por tipos corretamente definidos.Por exemplo, o código não pode permitir que campos de um objeto sejam acessados de uma maneira que permita que locais de memória sejam saturados.Além disso, a verificação inspeciona o código para determinar se o MSIL foi corretamente gerado, porque MSIL incorreto pode levar a uma violação das regras de segurança de tipos.O processo de verificação passa um conjunto bem definido de código com segurança de tipos, e ele passa apenas código que é com segurança de tipos.Entretanto, alguns códigos de tipos seguros podem não passar nessa verificação devido às limitações do processo de verificação, e algumas linguagens, por projeto, não produzem código de tipos seguros verificável.Se o código de tipos seguros for exigido pela política de segurança mas o código não passar pela verificação, uma exceção será lançada quando o código for executado.