(Esta é uma pergunta extremamente nova para os novatos).
Venho estudando um pouco sobre máquinas virtuais.
Acontece que muitos deles são projetados de maneira muito semelhante a computadores físicos ou teóricos.
Eu li que a JVM, por exemplo, é uma 'máquina de empilhar'. O que isso significa (e me corrija se eu estiver errado) é que ele armazena toda a sua 'memória temporária' em uma pilha e faz operações nessa pilha para todos os seus códigos de operação.
Por exemplo, o código-fonte 2 + 3
será traduzido para bytecode semelhante a:
push 2
push 3
add
Minha pergunta é esta:
As JVMs provavelmente são escritas usando C / C ++ e tal. Se sim, por que a JVM não executa o seguinte código C: 2 + 3
..? Quero dizer, por que ele precisa de uma pilha ou em outros 'registros' de VMs - como em um computador físico?
A CPU física subjacente cuida de tudo isso. Por que os gravadores de VM simplesmente não executam o bytecode interpretado com instruções 'usuais' no idioma em que a VM está programada?
Por que as VMs precisam emular o hardware, quando o hardware real já faz isso por nós?
Novamente, perguntas muito novas. Obrigado pela ajuda
fonte
printf("hi");
: isso é considerado uma VM? Não possui 'pilha' ou 'registradores' e nem nada.Respostas:
Uma máquina, virtual ou não, precisa de um modelo de computação que descreva como a computação é realizada nela. Por definição, assim que calcula, implementa algum modelo de computação. A questão então é: qual modelo devemos escolher para nossa VM? Máquinas físicas são limitadas pelo que pode ser feito de maneira eficaz e eficiente em hardware. Mas, como você observa, as máquinas virtuais não têm essas restrições, elas são definidas no software usando linguagens arbitrariamente de alto nível.
De fato, existem máquinas virtuais de alto nível, como você descreve. Eles são chamados de linguagens de programação . O padrão C, por exemplo, dedica a maior parte de suas páginas à definição de um modelo para a chamada "máquina abstrata C", que descreve como o programa C se comporta e, por extensão (como regra geral), como um compilador (ou intérprete) compatível com C Deve se comportar.
Obviamente, geralmente não chamamos isso de máquina virtual. Geralmente, uma VM significa algo de nível inferior, mais próximo ao hardware, que não se destina a ser diretamente programado, projetado para ser executado com eficiência. Esse viés de seleção significa que algo que aceita código composível de alto nível (como o que você descreve) não seria considerado uma VM porque executa código de alto nível.
Mas, para ir direto ao ponto, aqui estão alguns motivos para criar uma VM (como em algo direcionado por um compilador de bytecode) com base em registro ou algo semelhante. Máquinas de empilhar e registrar são extremamente simples. Há uma sequência de instruções, algum estado e semântica para cada instrução (uma função Estado -> Estado). Sem reduções complexas de árvores, sem precedência do operador. Analisar, analisar e executar é muito simples, porque é uma linguagem mínima (o açúcar sintático é compilado) e projetado para ser lido por máquina em vez de humano.
Por outro lado, analisar até mesmo as linguagens C mais simples é bastante difícil e executá-lo exige análises não locais, como verificação e propagação de tipos, resolução de sobrecargas, manutenção de uma tabela de símbolos, resolução de identificadores de sequência , transformando texto linear em um AST baseado em precedência , e assim por diante. Ele se baseia em conceitos que são naturais para os seres humanos, mas precisam ser minuciosamente projetados de maneira reversa pelas máquinas.
O bytecode da JVM, por exemplo, é emitido por
javac
. Praticamente nunca precisa ser lido ou escrito por seres humanos, por isso é natural orientá-lo para o consumo pelas máquinas. Se você é otimizado para os seres humanos, a JVM seria apenas em cada partida ler o código, analisá-lo, analisar é, em seguida, convertê-lo em uma representação intermediária semelhante a uma simplificada tal modelo de máquina de qualquer maneira . Poderia muito bem cortar o intermediário.fonte
System.out.println("hi");
é compilado com alguma instrução em uma pilha,int a = 7
compilado com uma instrução na pilha, etc.) torna a execução do programa simples e mais eficiente?2 + 3
é compiladopush 2 push 3 add
. Oadd
passo no final é executada pela JVM de qualquer maneira, executando o código C2 + 3
. Não há outra maneira de os programadores da JVM fazerem isso. Por que não compilá-lo2 + 3
e fazer com que a JVM execute o código C2 + 3
(supondo que esteja escrito em C) imediatamente?2 + 3
no código-fonte da JVM porque a JVM precisa trabalhar com qualquer programa que execute operações em qualquer ordem. Criar código-fonte C e adiar para uma implementação C apenas empurra o mesmo problema para a implementação C (e não pode ser feito facilmente, muito menos com eficiência). Deve haver alguma estrutura de dados que descreva o programa, para que possa ser interpretado e compilado pelo JIT, e o "código-fonte legível por humanos" é uma péssima escolha da estrutura de dados pelas razões descritas acima.a + b
? Os valores a serem adicionados não são origináriosi.argument{1,2}
, eles são carregados a partir de variáveis locais. Que talfrobnicate(x[i]) + (Foo.bar() * 2)
? Usando esse design, existe apenas umaadd
operação (paraint
) e funciona independentemente de como os addends foram computados. Além disso, uma instrução que adiciona apenas literais inteiros seria inútil: seu resultado também poderia ser pré-calculado (ou seja, em vez dissoadd(2,3)
, deveria serpush(5)
).Esta resposta se concentra na JVM, mas na verdade se aplica a qualquer VM.
Não, mas torna a VM muito mais simples e portátil: uma VM que emula hardware pode usar o mesmo modelo computacional que qualquer CPU de hardware.
A JVM, em particular, foi construída com a portabilidade em mente; na verdade, foi construída para ser implementada em hardware (pode ser difícil acreditar hoje, mas a origem do Java estava no mundo incorporado - especificamente, controladores para televisão interativa )
Se você tiver um objetivo como esse, é desejável que a VM opere o mais próximo possível de uma máquina física, pois a conversão para o código de máquina real se torna mais fácil e, portanto, mais rápida. Depois de ter os códigos de operação da VM, em teoria, tudo o que você precisa fazer é converter os códigos de operação da CPU na qual o programa realmente é executado. Na prática, não é exatamente assim tão simples.
O uso de um modelo de máquina virtual baseado em pilha tem a vantagem de poder ser facilmente transferido para máquinas de registro e pilha, enquanto o oposto não é necessariamente verdadeiro. Uma VM baseada em registro precisaria fazer suposições sobre o número de registros, o tamanho dos registros etc. Com uma máquina de empilhar, essas suposições não são necessárias.
Bem, é isso que essas VMs fazem, elas interpretam o bytecode. Até a JVM realmente faz isso, pelo menos antes do JIT (just-in-time) entrar em ação: interpreta os códigos de byte e executa as instruções no idioma em que a JVM foi escrita (normalmente C ou C ++, mas há até uma escrita) em JavaScript, Doppio ). Observe, no entanto, que mesmo essas instruções foram traduzidas para código de máquina por um compilador e, na verdade, parecem muito semelhantes ao que o compilador Java produz - ou seja, eles usam registradores e a pilha para executar seu trabalho. Observe que o uso de linguagens "interpretadas" vs "compiladas" se torna um pouco embaçado nesse momento.
fonte
Por que as VMs precisam ser "máquinas de empilhar" ou "registrar máquinas" etc.?
Eles não. Se você precisar de uma máquina virtual, pode ser qualquer coisa.
As máquinas virtuais existentes apareceram como soluções para situações como: Uma ideia realmente brilhante me veio à cabeça: eu inventei uma nova linguagem de programação! Mas eu tenho que gerar código. (Que tarefa chata!) Mas eu não quero gerar código i8086 porque é feio e não quero gerar código 68k porque todo mundo está usando a Intel. Também existe o VAX, mas eu não tenho nenhum VAX, nem um computador nem um livro do VAX. Portanto, gerarei código para algum processador que não existe fisicamente e implementarei esse processador em software. As especificações dessa VM farão um capítulo na minha tese. Em teoria, será possível compilá-lo no código nativo de qualquer processador, mas isso não será eu.
Por outro lado, a notação como "2 + 3" provavelmente não será usada pelas VMs em um futuro próximo, pois implica muita transformação antes que algo possa ser executado.
fonte
Para responder à pergunta real que foi feita. O termo "MÁQUINA virtual" significa que TODOS os softwares / hardwares são simulados / emulados. Se você usa o software / hardware subjacente para executar as instruções, não possui uma VM, possui um compilador / intérprete.
fonte