A CLR é uma máquina virtual?

li um livro que se referia à. Net CLR como uma máquina virtual ? Alguém pode justificar isto? Qual é a razão pela qual precisamos do conceito de máquinas virtuais em algumas plataformas de desenvolvimento?

não é possível desenvolver um framework nativo [um sem máquina virtual] que é totalmente orientado a objetos e tão poderoso quanto. net?

o livro que se refere à CLR como máquina virtual é " Professional. NET Framework 2.0 ".

Author: Aaron Hall, 2009-10-14

7 answers

Há muitos equívocos aqui. Eu suponho que você poderia pensar em.Net como uma máquina virtual se você realmente quisesse, mas vamos ver como o Framework. net realmente lida com o seu código. O cenário típico se parece com este
  1. escreves um programa. Net em C#, VB.Net, F#, ou alguma outra linguagem compatível.
  2. esse código é compilado até uma linguagem intermediária (IL), que é semelhante ao bytecode Java, que é distribuído para máquinas de usuário final.
  3. Um fim o usuário invoca o programa pela primeira vez em um computador com a versão correta do .Net instalado
  4. o computador vê que este é um conjunto. Net em vez de código de máquina "raw", e passa-o para o compilador JIT
  5. o compilador JIT compila o IL para código de máquina totalmente nativo .
  6. o código nativo é guardado na memória para a vida deste programa de execução.
  7. o código nativo salvo é invocado, e o IL já não importa.

Existe um alguns pontos importantes aqui, mas o grande é que em nenhum momento é qualquer código alguma vez interpretado. Em vez disso, você pode ver no Passo 5 que ele é compilado para o código nativo. Esta é uma diferença enormedo que carregá-la numa máquina virtual, por várias razões:

  1. o código totalmente compilado é executado pela cpu diretamente ao invés de interpretado ou traduzido por uma camada adicional de abstração de software, que deve ser mais rápida.
  2. o compilador JIT pode aproveitar otimizações específicas para a máquina individual executando o programa, em vez de se estabelecer para um menor denominador comum.
  3. Se quiser pode até mesmo pré-compilar o código e, em essência, esconder o Passo 5 do utilizador completamente.
Eu suponho que você poderia chamar isso de uma máquina virtual, no sentido em que o JITter abstrai os detalhes da máquina real do desenvolvedor. Pessoalmente, acho que isso não está certo, porque para muitas pessoas, uma máquina virtual implica um tempo de execução abstração longe do código nativo que para programas. Net apenas não existe.

Um outro ponto chave sobre todo este processo que realmente o diferencia de um ambiente de "máquina virtual" é que é apenas o processo típico . Se você realmente quiser, você pode pré-compilar um .Net assembleia, antes da distribuição e implantar o código nativo diretamente aos usuários finais (dica: é mais lento no agregado ao longo da vida do programa, porque você perde a máquina-otimizações específicas). De claro, você ainda precisa do tempo de execução.Net instalado, mas neste ponto não é muito diferente de qualquer outra API de runtime; é mais como um DLLs de coleção com uma API agradável que você pode ligar, como você pode ter com o VB ou C runtimes Microsoft também navios com Visual Studio. Este tipo de tira o IL de cena, tornando o apelido VM muito mais difícil de justificar. (Eu digo "mais ou menos" porque o IL ainda está implantado e usado para verificar o código salvo, mas ele nunca é tocado por execucao).

Um outro ponto Revelador é a falta de um processo VM. Quando você executa seu aplicativo, não há nenhum processo comum de "caixa de areia" que corre. Compare isso com Java, onde se você abrir o Gerenciador de tarefas quando UM programa está em execução, você verá um processo especificamente para a VM Java, e o processo real da aplicação é um thread dentro da caixa de areia criada pela VM. No. NET, você vê o processo da aplicação no Gerenciador de tarefas do Windows diretamente. Em resumo, pode-se dizer que IL + CLR + JIT juntos de alguma forma compõem uma máquina virtual. Pessoalmente, acho que não, mas não vou discutir contigo se acreditas nisso. O ponto que quero fazer é que quando você diz a alguém que o.Net roda em uma máquina virtual sem mais explicações, a idéia que você está se comunicando com essa pessoa é "interpretada por bytecode em um processo de host."E isso é errado.
 85
Author: Joel Coehoorn, 2017-08-14 18:05:57

Similar à máquina virtual Java (JVM), a CLR.NET é uma máquina virtual de interpretação por byte-código.

O JVM interpreta programas que contêm códigos de bytes java e o.Net CLR interpreta programas que contêm o que a Microsoft chama de instruções de "linguagem intermediária (IL)". Existem diferenças entre estes códigos byte, mas as máquinas virtuais são semelhantes e aspiram a fornecer características semelhantes.

Ambas as implementações de máquinas virtuais têm a capacidade para compilar sua entrada bytecode para a linguagem de máquina do computador em que eles estão rodando. Isto é chamado " Just In Time Compilation (JIT)" e o código de saída produzido é chamado "JIT code."Porque o código JIT contém sequências de instruções na linguagem de máquina da CPU do computador, este código é por vezes referido como código "nativo".

No entanto, o código JIT é qualitativamente e quantitativamente diferente do código nativo, como explicado abaixo. Por essa razão, este o artigo considera o código JIT como nada mais do que uma implementação nativa da máquina Virtual enquanto executa um programa particular de bytecode.

Uma característica que ambas as máquinas virtuais (VMs) aspiram a fornecer é a segurança na forma de prevenir certos erros de programação perigosos. Por exemplo, o título deste fórum do site, stackoverflow, é inspirado por um tal tipo de erro perigoso que é possível em código nativo.

Para garantir a segurança e segurança de execução, o VMs implementar a segurança do tipo no "nível de máquina Virtual". Atribuições para memória VM são necessárias para armazenar o tipo de dados que é mantido nesse local de memória. Por exemplo, se um inteiro é empurrado para a pilha, não é possível abrir um duplo da pilha. Os "sindicatos" ao estilo C são proibidos. Ponteiros e acesso direto à memória são proibidos.

Nós não poderíamos obter os mesmos benefícios ao impor um framework de linguagem orientada a objetos nos desenvolvedores se o o resultado é um binário nativo, como um arquivo EXE. Nesse caso, não seríamos capazes de distinguir entre binários nativos gerados usando o framework e EXEs gerados por um usuário malicioso empregando fontes diferentes do framework.

No caso do VMs, a segurança do tipo é aplicada ao "nível mais baixo" a que o programador está autorizado a aceder. (Negligenciando por um momento que é possível escrever código nativo gerenciado, isto é.) Portanto, nenhum usuário vai encontrar uma aplicação que executa uma das operações perigosas que requerem acesso direto a locais de memória e ponteiros.

Na prática, a CLR.net implementa uma forma de escrever o código nativo que pode ser chamado pelo código. net "gerenciado". Neste caso, o fardo é para o autor nativo do código não fazer nenhum dos erros de ponteiro e memória.

Como tanto o JVM como o. Net CLR executam a compilação JIT, tanto o VM cria um binário compilado nativo a partir do bytecode fornecido. Este"código JIT" executa mais rapidamente do que a execução interpretadora da VM, porque mesmo o código de linguagem de máquina produzido pela JIT contém todas as verificações de segurança necessárias da VM que a VM iria executar. Como resultado, o código de saída JIT não é tão rápido quanto o código nativo que normalmente não conteria inúmeras verificações de tempo de execução. No entanto, esta desvantagem de desempenho de velocidade é trocada para uma melhoria da confiabilidade, incluindo a segurança; em particular, o uso de armazenamento não inicializado é impedido, Tipo-segurança de atribuições são executadas, verificação de alcance é realizada (assim, stack-e heap - based buffer transbordamentos evitados), as vidas dos objetos são gerenciados pela coleta de lixo, alocação dinâmica é tipo seguro. Um ambiente executando tais verificações de comportamento em tempo de execução está implementando a especificação de uma máquina virtual e é pouco mais do que a realização de uma linguagem de máquina de uma máquina virtual.

 23
Author: Heath Hunnicutt, 2009-10-26 17:16:56

A parte " Máquina Virtual "refere-se ao fato de que o código.NET é compilado em EXE e DLL's como linguagem de montagem" intermediária " (IL) para executar em uma máquina virtual, em oposição à linguagem de montagem CPU real. Então, em tempo de execução, o ILM é convertido em conjunto CPU real para execução (referido como Just-in-time, ou compilação JIT).

Claro, você poderia escrever um compilador.NET para que fosse compilado em linguagem de montagem CPU em vez de IL. No entanto, isso não seria portátil para todos os CPUs - teria de compilar uma versão diferente para cada par OS/CPU. Mas ao compilar em ILM, você deixa a "máquina Virtual" lidar com o CPU e coisas específicas do so.

 6
Author: noctonura, 2009-10-14 05:28:51
Sou um pouco antiquado, por isso também chamo a CLR de máquina virtual. Meu raciocínio é que a CLR ajusta o código da máquina a partir de um bytecode intermediário, que é o que uma máquina virtual também faz.

Os benefícios da CLR devem-se principalmente à forma como reúne o código da máquina que utiliza Informação do tipo de tempo de execução.

Você pode desenvolver um framework nativo tão poderoso quanto o framework.net usando apenas tipos nativos. A única flexibilidade que se perde é a capacidade de reemble o código nativo se você alguma vez transportar seu programa para outra plataforma sem recompilar.

 2
Author: Andrew Keith, 2009-10-14 05:23:32

A vantagem da CLR é a liberdade de escrever código em qualquer linguagem de programação que o desenvolvedor escolha, uma vez que o código será compilado até CLR antes de ser interpretado em chamadas nativas. O framework. net usa esta compilação JIT para tratar tudo uniformemente e programas de saída que funcionam para a plataforma que está sendo implantada, que está ausente de linguagens compiladas.

 2
Author: Ben Lakey, 2009-11-01 20:52:57

Nem a JVM nem a CLR fazem qualquer coisa que seja materialmente diferente do que a maioria das "máquinas virtuais" para outras línguas também fazem. Modernamente, todos eles usam JIT para converter instruções virtuais (código p, bytecodes, instruções de linguagem intermediária, chamá-lo o que você quiser) para instruções de "hardware de CPU nativo" ("código de máquina.")

Na verdade, a primeira "máquina virtual" a fazer isso foi a máquina virtual Smalltalk. O autor dessa inovação, Peter Deutsch, apelidou-a de "dynamic translation "instead of the term" JIT, " which was popularized by Java. Se o Smalltalk "ambiente de execução em tempo de execução" vai ser chamado de " máquina virtual "(e isso é o que ainda é chamado,), então qualquer e todos os outros" sistemas de tempo de execução "que fazem essencialmente a mesma coisa também se qualifica como "máquinas virtuais"."
 2
Author: user2809447, 2014-07-03 22:28:54
Você tem muitas respostas valiosas, mas acho que uma coisa ainda não foi mencionada: modularidade. É muito difícil exportar uma classe OO da DLL nativa. Claro, você pode dizer ao linker para exportar a classe e importá-la em outro lugar, mas isso é frágil; mudar um único membro privado em uma classe irá quebrar a compatibilidade binária, ou seja, se você mudar um DLL sem recompilar todos os outros módulos, o seu programa irá estoirar horrivelmente no tempo de execução. Há algumas maneiras. em torno disso: por exemplo, você pode definir interfaces públicas abstratas, derivar desses e exportar as funções de fábrica global a partir de seu DLL. Dessa forma, você pode alterar os detalhes de implementação de uma classe. Mas você não pode derivar dessa classe em outro DLL. E mudar a interface também quebra a compatibilidade binária, é claro.

Não tenho a certeza se há uma boa solução para isto em código nativo: se o compilador / linker cria o código nativo no tempo de compilação, então ele deve saber a memória exata disposição das classes/estruturas utilizadas em código. Se a última etapa de compilação (gerando o código nativo) for atrasada até que um método seja chamado pela primeira vez, este problema simplesmente desaparece: você pode modificar uma classe em um conjunto, e desde que o JIT possa resolver todos os membros usados no tempo de execução, tudo correrá bem.

Em poucas palavras: se você criar um programa monolítico único-executável, você provavelmente poderia ter a maioria das características poderosas do. NET com um compilador isso cria código nativo. Mas as desvantagens de ter um compilador JIT (framework installation, um pouco mais tempo de startup) realmente não superam os benefícios na maioria dos casos.

 1
Author: Niki, 2009-10-26 15:06:38