Pergunta

Eu estava lendo esta questão para descobrir as diferenças entre a Máquina Virtual Java eo .NET CLR e resposta de Benji tenho me perguntando por que máquinas virtuais são necessários em primeiro lugar.

No meu entendimento da explicação de Benji, o compilador JIT de uma Máquina Virtual interpreta o código intermediário para o código de montagem real que é executado na CPU. A razão que tem que fazer isso é porque CPUs muitas vezes têm diferentes números de registros e de acordo com Benji "alguns registros são para fins especiais, e cada instrução espera que seus operandos em diferentes registos." Isso faz sentido, então, que há uma necessidade de um intérprete intermediário como a máquina virtual para que o mesmo código pode ser executado em qualquer CPU.

Mas, se esse for o caso, então o que eu não entendo é por que o código C ou C ++ compilado em código de máquina é capaz de rodar em qualquer computador, desde que ele é o sistema operacional correto. Por que então um programa C I compilados na minha máquina Windows usando um Pentium ser capaz de correr no meu outro computador com Windows usando um AMD?

Se o código C pode ser executado em qualquer CPU, então qual é o propósito da máquina virtual? É por isso que o mesmo código pode ser executado em qualquer sistema operacional? Eu sei que Java tem versões VM em praticamente qualquer sistema operacional, mas existe uma CLR para outro sistema operacional de além do Windows?

Ou há algo mais que eu estou perdendo? Será que as OS fazer alguma outra interpretação do código de montagem que corre para adaptá-lo ao CPU especial ou algo assim?

Estou muito curioso sobre como tudo isso funciona, então uma explicação clara seria muito apreciada.

Nota: A razão que eu não basta postar minhas consultas como comentários na questão JVM vs. CLR é porque eu não tenho pontos suficientes para postar comentários ainda = b

.

Edit: Obrigado por todas as grandes respostas! Assim, parece que eu estava faltando era que, apesar de todos os processadores têm diferenças há uma padronização comum, principalmente a arquitetura X86, que fornece um conjunto grande o suficiente de recursos comuns para que o código C compilado em um processador X86 vai trabalhar para a maior parte no outro processador X86. Isso reforça a justificação para máquinas virtuais, para não mencionar que eu esqueci sobre a importância da coleta de lixo.

Foi útil?

Solução

A AMD e processadores Intel usam o mesmo conjunto de instruções e arquitetura da máquina (do ponto de vista da execução do código de máquina).

C e C ++ compiladores de compilação para código de máquina, com cabeçalhos apropriados para o sistema operacional que eles são direcionados a. Uma vez compilado deixam de associar em qualquer maneira, forma ou formulário com a linguagem que eles foram compilados e são apenas executáveis ??binários. (Existem artefatos taht pode mostrar que língua ele foi compilado a partir, mas isso não é o ponto aqui)

Assim, uma vez compilados, eles estão associados à máquina (X86, a intel e instrução amd conjunto e arquitetura) e do OS.

É por isso que eles podem ser executados em qualquer máquina x86 compatível, e qualquer sistema operacional compatível (win95 através WinVista, por algum software).

No entanto, eles não podem ser executado em uma máquina OSX, mesmo se ele estiver sendo executado em um processador Intel -. O binário não é compatível a menos que você executar o software de emulação adicional (como paralelos, ou uma máquina virtual com o Windows)

Além disso, se você quiser executá-los em um processador ARM ou MIPS, ou PowerPC, então você tem que executar um conjunto emulador instrução de máquina completo que interpreta o código máquina binário do X86 em qualquer máquina que você está executando-o por diante.

Contraste isso com .NET.

O .NET máquina virtual é fabricado como se houvesse muito melhores processadores no mundo - processadores que entendem objetos, alocação de memória e coleta de lixo, e outras construções de alto nível. É uma máquina muito complexa e não pode ser construído diretamente no silício agora (com bom desempenho), mas um emulador pode ser escrito que permitirá que ele seja executado em qualquer processador existente.

De repente, você pode escrever emulador específico uma máquina para qualquer processador você deseja executar .NET e, em seguida QUALQUER .NET programa pode ser executado nele. Não há necessidade de se preocupar com o sistema operacional ou a arquitetura CPU subjacente -. Se há uma .NET VM, o software será executado

Mas vamos ir um pouco mais - uma vez que você tem essa linguagem comum, por que não fazer compiladores que convertem qualquer outra língua escrita nele

?

Então, agora você pode ter um C, C #, C ++, Java, JavaScript, Basic, python, lua, ou qualquer outro compilador de linguagem que converte o código escrito por isso vai funcionar nesta máquina virtual.

Você dissociada da máquina a partir da linguagem por 2 graus, e com não muito trabalho que você permitir que qualquer pessoa para escrever qualquer código e executá-lo em qualquer máquina, desde que um compilador e uma máquina virtual existe para mapear os dois graus de separação.

Se você ainda está se perguntando por que isso é uma coisa boa, considere máquinas DOS início, eo que da Microsoft real contribuição para o mundo foi:

Autocad teve que motoristas de gravação para cada impressora que pudessem imprimir. Assim fez o Lotus 1-2-3. Na verdade, se você queria o seu software para impressão, você tinha que escrever seus próprios drivers. Se havia 10 impressoras e 10 programas, de 100 diferentes peças de essencialmente o mesmo código tinha que ser escrito separada e independentemente.

O Windows 3.1 tentaram realizar (juntamente com GEM e tantas outras camadas de abstração) é fazê-lo de modo que o fabricante da impressora, escreveu um driver para sua impressora e o programador escreveu um driver para a classe janelas impressora.

Agora, com 10 programas e 10 impressoras, apenas 20 pedaços de código tem que ser escrito, e desde o lado microsoft do código foi o mesmo para todos, em seguida, exemplos de MS significava que você teve muito pouco trabalho a fazer.

Agora, um programa não foi restrito a apenas 10 impressoras que eles escolheram para apoio, mas todas as impressoras cujos fabricantes forneceram os motoristas no janelas.

O mesmo problema está ocorrendo no desenvolvimento de aplicações. Existem aplicações realmente puros Eu não pode usar porque eu não usar um MAC. Há uma tonelada de duplicação (quantos processadores de texto de classe mundial que nós realmente precisamos?).

Java foi feito para corrigir isso, mas tinha muitas limitações, algumas das quais não são really resolvido.

.NET está mais perto, mas ninguém está desenvolvendo de classe mundial VMs para outras plataformas que não o Windows (mono é tão perto ... e ainda não chegou lá).

Então ... É por isso que precisamos de VMs. Porque eu não quero me limitar a um público menor, simplesmente porque eles escolheram uma OS / máquina de combinação diferente do meu.

-Adam

Outras dicas

Seu pressuposto de que o código C pode ser executado em qualquer processador está incorreto. Existem coisas como registros e endianness que fará compilados programas em C não funcionar em todos em uma única plataforma, embora possa trabalhar em outro.

No entanto, há certas semelhanças que os processadores de ação, por exemplo, processadores x86 da Intel e os processadores AMD compartilham de um grande conjunto suficiente de propriedades que mais código compilado contra um vai correr no outro. No entanto, se você quiser usar propriedades específicas do processador, então você precisa de um compilador ou conjunto de bibliotecas que irá fazer isso por você.

Como para por que você quer uma máquina virtual, para além da afirmação de que ele vai lidar com as diferenças de processadores para você, há também o fato de que as máquinas virtuais oferecem serviços para código que não estão disponíveis para programas compilados em C ++ (não conseguiu ) hoje.

O serviço mais importante oferecido é a coleta de lixo, oferecido pelo CLR eo JVM. Ambas estas máquinas virtuais oferecer-lhe este serviço gratuitamente. Eles gerir a memória para você.

Coisas como verificação de limites, violações de acesso (enquanto ainda é possível, eles são extremamente difíceis) também são oferecidos.

O CLR também oferece uma forma de segurança código para você.

Nenhum destes são oferecidos como parte do ambiente de tempo de execução básico para uma série de outras línguas que não operam com uma máquina virtual.

Você pode obter alguns deles usando bibliotecas, mas depois que as forças você em um padrão de uso com a biblioteca, enquanto que em .NET e serviços Java que são oferecidos a você através do CLR e JVM são consistentes em seu acesso.

Essencialmente, permite 'código gerenciado', o que significa exatamente o que diz - a máquina virtual gere o código como ele é executado. Três benefícios principais deste são just-in-time control compilação, ponteiros gerenciados / coleta de lixo e segurança.

Para a compilação just-in-time, a máquina virtual observa o código executar e assim como o código é executado com mais freqüência, é reoptimised para correr mais rápido. Você não pode fazer isso com o código nativo.

ponteiros gerenciados também mais fácil é para otimizar porque as faixas de máquinas virtuais enquanto eles vão ao redor, gerenciá-los de maneiras diferentes, dependendo do seu tamanho e vida. É difícil fazer isso em C ++, porque você não pode realmente dizer onde um ponteiro está a ir apenas lendo o código.

A segurança é um auto-explicativo, a máquina virtual pára o código de fazer coisas que não deveria, porque está assistindo. Pessoalmente eu acho que é provavelmente o maior motivo por que a Microsoft escolheu código gerenciado para C #.

Basicamente o meu ponto é, porque a máquina virtual pode assistir o código como acontece, ele pode fazer coisas que tornam a vida mais fácil para o programador e tornar o código mais rápido.

A maioria dos compiladores, mesmo compiladores de código nativo, use algum tipo de linguagem intermediária.

Isso é feito principalmente para reduzir os custos de construção do compilador. Há muitas línguas (N) de programação do mundo. Há também muitos (M) plataformas de hard ware do mundo. Se compiladores trabalhou sem o uso de uma linguagem intermediária, o número total de "compiladores" que precisam ser escrito para suportar todos os idiomas em todas as plataformas de hardware seria N * M.

No entanto, através da definição de uma linguagem intermediária e quebrar um compilador-se em 2 partes, uma extremidade dianteira e uma extremidade traseira, com a extremidade dianteira compilar o código-fonte em IL e back-end compilar IL em código de máquina, você pode começar afastado com apenas por escrito n + m compiladores. Isso acaba sendo uma economia de custo enorme.

A grande diferença entre compiladores CLR / JVM e compiladores de código nativo é a forma como o front-end e os compiladores de back-end são ligados uns aos outros. Em um compilador de código nativo os dois componentes são geralmente combinados no mesmo executável, e ambos são executados quando os hits programador "construir" no IDE.

Com compiladores CLR / JVM, o front-end e back-end são executados em momentos diferentes. O front-end é executado em tempo de compilação, produzindo IL que é realmente enviado aos clientes. A extremidade posterior é então incorporada em um componente separado que é invocado durante a execução.

Então, isso levanta a questão alternativo, "Quais são os benefícios da atrasando a compilação de back-end até a execução"?

A resposta é:. "Depende"

atrasando a compilação de back-end até a execução, torna-se possível enviar um conjunto de binários que podem ser executados em várias plataformas de hardware. Ele também torna possível para programas para tirar proveito de melhorias na tecnologia de compilação de back-end sem ser reimplantado. Ele também pode fornecer uma base para a eficiente implementação de muitos recursos de linguagem dinâmica. Finalmente, ele oferece a capacidade de introduzir restrições de segurança e de confiabilidade entre compilados separadamente, bibliotecas ligadas dinamicamente (DLLs) que não é possível com adiantado compilação código de máquina.

No entanto, há também desenhar costas. A análise necessária para implementar extensas otimizações do compilador pode ser caro. Isto significa que as extremidades "JIT" de volta, muitas vezes, fazer menos otimizações de backends iniciais fazer. Isso pode prejudicar o desempenho. Além disso, a necessidade de invocar o compilador em tempo de execução também aumenta o tempo necessário para carregar programas. Programas gerados com os compiladores "upfront" não têm esses problemas.

Em primeiro lugar o código de máquina não é a forma mais baixa de instruções para uma cpu. Hoje x86 CPUS-se interpretar o conjunto de instruções x86 em outro formato interno usando microcódigo. As únicas pessoas que realmente programa de microcódigo são os tipos engenheiro desenvolvedor de chip, que fielmente e indolor emular o chip de instrução legado x86 para atingir o máximo desempenho usando tecnologias de hoje.

tipos de Desenvolvedor foram sempre adicionando camadas adicionais de abstrações por causa do poder e recursos que eles trazem. Depois de todas as abstrações melhores permitem novas aplicações para ser escrita mais rápida e confiável. As empresas não se importam sobre o que ou como eles aparência código como eles só querem o trabalho feito de forma confiável e rápida. Será que realmente importa se a versão C de um aplicativo leva alguns milissegundos menos, mas acaba levando o dobro do tempo para se desenvolver?

A questão de velocidade é quase um não argumento como muitas aplicações empresariais que servem milhões de pessoas são escritos em plataformas / linguagens como Java - por exemplo, GMail, GMaps. Esqueça que a linguagem / plataforma é mais rápido. O que é mais importante é que você use os algoritmos corretos e escrever código effecient e fazer o trabalho.

AMD e Intel processadores ambos têm arquitetura x86, se você deseja executar c / c ++ programa em uma arquitetura diferente você tem que usar um compilador para essa arquitetura, o mesmo binário executável não será executado em diferentes arquiteturas de processador.

Eu sei que Java tem versões VM em praticamente qualquer sistema operacional, mas existe uma CLR para outro sistema operacional de além do Windows?

Mono

De forma muito simplificada, é porque Intel e AMD implementa a mesma linguagem de montagem, com o mesmo número de registo, etc etc ...

Assim, o seu compilador C compila código para trabalhar em Linux. Que a montagem está usando um Linux ABI , por isso, enquanto o programa de compilação está sendo executado em Linux , em x86 montagem e a assinatura da função certa, então tudo é dandy.

Agora tente tomar esse código compilado, e cumpri-lo, dizer Linux / PPC (por exemplo Linux em um velho iBook). Isso não vai funcionar. Onde como um programa Java seria porque a JVM foi implementado na plataforma / PPC Linux.

Assembleia langauge hoje em dia é basicamente outra interface que um programador pode programar para. x86 (32 bits) permite o acesso eax, ebx, ecx, edx para registros inteiros de uso geral, e F00-F07 para ponto flutuante. Nos bastidores, o CPU na verdade tem mais cem registros, e desordenados que coisas ao redor para espremer o desempenho fora.

Você tem razão em sua análise, Java ou C # poderia ter sido concebido para compilar direta para rodar em qualquer máquina, e provavelmente seria mais rápido se eles fizeram isso. Mas a abordagem de máquina virtual dá controle completo do ambiente em que as corridas de código, o VM cria uma sandbox seguro que só permite comandos com o acesso de segurança direito de realizar potencialmente prejudiciais código - como a mudança de senha, ou atualizar um bootsector HD. Existem muitos outros benefícios, mas essa é a razão assassino. Você não pode obter um StackOverflow em C # ...

Eu acho que a premissa da sua pergunta é válida - você certamente não é o primeiro a fazer esta pergunta. Então confira http://llvm.org para ver uma abordagem alternativa (que agora é um projeto que está sendo executado? Ou patrocinados pela Apple)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top