Linguagem Java “Máquina Virtual” vs. Python “Intérprete”?

207

Parece raro ler uma "máquina virtual" Python enquanto em Java a "máquina virtual" é usada o tempo todo.

Ambos interpretam códigos de bytes; por que chamar uma máquina virtual e a outra intérprete?

twils
fonte

Respostas:

137

Uma máquina virtual é um ambiente de computação virtual com um conjunto específico de instruções atômicas bem definidas que são suportadas independentemente de qualquer idioma específico e geralmente é pensado como uma caixa de areia em si. A VM é análoga a um conjunto de instruções de uma CPU específica e tende a funcionar em um nível mais fundamental com blocos de construção muito básicos dessas instruções (ou códigos de bytes) que são independentes da próxima. Uma instrução é executada deterministicamente apenas com base no estado atual da máquina virtual e não depende de informações em outras partes do fluxo de instruções naquele momento.

Um intérprete, por outro lado, é mais sofisticado, pois é adaptado para analisar um fluxo de alguma sintaxe de um idioma específico e de uma gramática específica que deve ser decodificada no contexto dos tokens circundantes. Você não pode olhar para cada byte ou mesmo cada linha isoladamente e saber exatamente o que fazer a seguir. Os tokens no idioma não podem ser tomados isoladamente, como podem em relação às instruções (códigos de bytes) de uma VM.

Um compilador Java converte a linguagem Java em um fluxo de código de bytes não diferente de um compilador C converte programas da linguagem C em código de montagem. Um intérprete, por outro lado, não converte realmente o programa em nenhuma forma intermediária bem definida, apenas executa as ações do programa como uma questão do processo de interpretação da fonte.

Outro teste da diferença entre uma VM e um intérprete é se você pensa que ela é independente de idioma. O que conhecemos como Java VM não é realmente específico de Java. Você pode criar um compilador a partir de outros idiomas que resultam em códigos de bytes que podem ser executados na JVM. Por outro lado, acho que não pensamos realmente em "compilar" outra linguagem que não seja Python no Python para interpretação pelo intérprete do Python.

Devido à sofisticação do processo de interpretação, esse pode ser um processo relativamente lento ... especificamente analisando e identificando os tokens de idioma etc. e entendendo o contexto da fonte para poder executar o processo de execução no intérprete. Para ajudar a acelerar essas linguagens interpretadas, é aqui que podemos definir formas intermediárias de código-fonte pré-analisado e pré-tokenizado que é mais prontamente interpretado diretamente. Esse tipo de forma binária ainda é interpretada no tempo de execução, está apenas começando de uma forma legível por menos humanos para melhorar o desempenho. No entanto, a lógica que executa esse formulário não é uma máquina virtual, porque esses códigos ainda não podem ser tomados isoladamente - o contexto dos tokens circundantes ainda importa, eles agora estão em uma forma diferente e mais eficiente em computadores.

Tall Jeff
fonte
7
Fiquei com a impressão de que python gerou código de bytes, pyc, ou é isso que você está consultando por "ajuda a acelerar essas linguagens interpretadas; é aqui que podemos definir formas intermediárias de código-fonte pré-analisado e pré-tokenizado que é mais prontamente diretamente interpretado ".
James McMahon
32
@InSciTek Jeff: Pela sua resposta, não está claro se você sabe que o Python também usa uma máquina virtual.
tzot 15/01/09
3
@TZ - A implementação popular do Python é um compilador Python com uma VM no verso. No modo interativo, é um pouco híbrido com um front end de intérprete e um back-end de compilador. No entanto, essas são escolhas de implementação. Tentei descrever diferença entre o conceito de VM e Intérprete
Alto Jeff
8
On the other hand, I don't think we would really think of "compiling" some other language other than Python into Python for interpretation by the Python interpreter.É possível escrever uma linguagem que possa ser compilada no bytecode do Python, assim como o Scala é compilado no bytecode do Java. No modo interativo, o shell interativo do Python compila seu comando digitado no bytecode e executa esse bytecode. Você pode escrever seu próprio shell usando eval e exec e pode usar a função interna compile () para transformar uma string em bytecode.
Lie Ryan
4
@ Ryan Ryan sim, mas não é oficialmente suportado como é com a JVM. No Python, bytecode é um detalhe de implementação não documentado.
Antimônio
159

Nesta postagem, "máquina virtual" refere-se a máquinas virtuais de processo, não a máquinas virtuais do sistema como Qemu ou Virtualbox. Uma máquina virtual de processo é simplesmente um programa que fornece um ambiente geral de programação - um programa que pode ser programado.

Java possui um intérprete e uma máquina virtual, e o Python possui uma máquina virtual e um intérprete. O motivo "máquina virtual" é um termo mais comum em Java e "intérprete" é um termo mais comum em Python tem muito a ver com a principal diferença entre as duas linguagens: digitação estática (Java) versus digitação dinâmica (Python). Nesse contexto, "tipo" refere-se a tipos de dados primitivos - tipos que sugerem o tamanho de armazenamento na memória dos dados. A máquina virtual Java é fácil. Requer que o programador especifique o tipo de dados primitivo de cada variável. Isso fornece informações suficientes para o bytecode Java não apenas ser interpretado e executado pela máquina virtual Java, mas também ser compilado nas instruções da máquina. A máquina virtual Python é mais complexa no sentido de assumir a tarefa adicional de fazer uma pausa antes da execução de cada operação para determinar os tipos de dados primitivos para cada variável ou estrutura de dados envolvida na operação. O Python libera o programador de pensar em termos de tipos de dados primitivos e permite que as operações sejam expressas em um nível superior. O preço dessa liberdade é o desempenho. "Intérprete" é o termo preferido para Python, porque ele precisa pausar para inspecionar tipos de dados e também porque a sintaxe comparativamente concisa das linguagens dinamicamente digitadas é uma boa opção para interfaces interativas. Não há barreira técnica para a construção de uma interface Java interativa, mas tentar escrever qualquer código estaticamente digitado interativamente seria tedioso, por isso simplesmente não é feito dessa maneira.

No mundo Java, a máquina virtual rouba a cena porque executa programas escritos em uma linguagem que pode realmente ser compilada nas instruções da máquina, e o resultado é a velocidade e a eficiência dos recursos. O bytecode Java pode ser executado pela máquina virtual Java com desempenho próximo ao dos programas compilados, relativamente falando. Isso ocorre devido à presença de informações primitivas do tipo de dados no bytecode. A máquina virtual Java coloca o Java em uma categoria própria:

linguagem de tipo estaticamente interpretada portátil

O próximo passo mais próximo é o LLVM, mas o LLVM opera em um nível diferente:

linguagem assembly interpretada portátil

O termo "bytecode" é usado em Java e Python, mas nem todos os bytecode são criados iguais. bytecode é apenas o termo genérico para idiomas intermediários usados ​​por compiladores / intérpretes. Até os compiladores C, como o gcc, usam uma linguagem intermediária (ou várias) para fazer o trabalho. O bytecode Java contém informações sobre tipos de dados primitivos, enquanto o bytecode Python não. Nesse aspecto, a máquina virtual Python (e Bash, Perl, Ruby etc.) realmente é fundamentalmente mais lenta que a máquina virtual Java, ou melhor, simplesmente tem mais trabalho a fazer. É útil considerar quais informações estão contidas em diferentes formatos de bytecode:

  • llvm: registradores da CPU
  • Java: tipos de dados primitivos
  • Python: tipos definidos pelo usuário

Para desenhar uma analogia do mundo real: o LLVM trabalha com átomos, a máquina virtual Java trabalha com moléculas e a máquina virtual Python trabalha com materiais. Como tudo deve eventualmente se decompor em partículas subatômicas (operações reais da máquina), a máquina virtual Python tem a tarefa mais complexa.

Os intérpretes / compiladores das linguagens de tipo estático simplesmente não têm a mesma bagagem que os intérpretes / compiladores das linguagens de tipo dinâmico. Os programadores de linguagens de tipo estatístico precisam assumir a folga, pela qual o retorno é o desempenho. No entanto, assim como todas as funções não determinísticas são secretamente determinísticas, todas as linguagens de tipo dinâmico são secretamente de tipo estaticamente. Portanto, as diferenças de desempenho entre as duas famílias de idiomas devem se nivelar sempre que o Python muda seu nome para HAL 9000.

As máquinas virtuais de linguagens dinâmicas como Python implementam alguma máquina lógica idealizada e não correspondem necessariamente muito a nenhum hardware físico real. A máquina virtual Java, por outro lado, é mais semelhante em funcionalidade a um compilador C clássico, exceto que, em vez de emitir instruções da máquina, ele executa rotinas internas. No Python, um número inteiro é um objeto Python com vários atributos e métodos anexados. Em Java, int é um número designado de bits, geralmente 32. Não é realmente uma comparação justa. Inteiros Python realmente devem ser comparados à classe Java Integer. O tipo de dados primitivo "int" do Java não pode ser comparado a nada na linguagem Python, porque a linguagem Python simplesmente não possui essa camada de primitivas, assim como o bytecode do Python.

Como as variáveis ​​Java são digitadas explicitamente, é possível esperar razoavelmente que algo como o desempenho do Jython esteja no mesmo estádio do cPython . Por outro lado, é quase garantido que uma máquina virtual Java implementada em Python seja mais lenta que a lama. E não espere que Ruby, Perl, etc., se saiam melhor. Eles não foram projetados para fazer isso. Eles foram projetados para "scripts", que é chamado de programação em uma linguagem dinâmica.

Toda operação que ocorre em uma máquina virtual acaba atingindo o hardware real. Máquinas virtuais contêm rotinas pré-compiladas que são gerais o suficiente para executar qualquer combinação de operações lógicas. Uma máquina virtual pode não estar emitindo novas instruções para a máquina, mas certamente está executando suas próprias rotinas repetidamente em sequências arbitrariamente complexas. A máquina virtual Java, a máquina virtual Python e todas as outras máquinas virtuais de uso geral existentes são iguais no sentido de que podem ser persuadidas a executar qualquer lógica que você possa imaginar, mas são diferentes em termos de quais tarefas serão executadas. assumir e quais tarefas eles deixam para o programador.

O Psyco for Python não é uma máquina virtual completa do Python, mas um compilador just-in-time que seqüestra a máquina virtual regular do Python em pontos em que acha que pode compilar algumas linhas de código - principalmente loops onde considera o tipo primitivo de alguns A variável permanecerá constante, mesmo que o valor esteja mudando a cada iteração. Nesse caso, ele pode renunciar a algumas das incessantes determinações de tipo da máquina virtual comum. Você tem que ter um pouco de cuidado, no entanto, para não tirar o tipo de baixo dos pés de Psyco. A Pysco, no entanto, geralmente sabe voltar à máquina virtual comum se não estiver completamente confiante de que o tipo não mudará.

A moral da história é que informações primitivas de tipo de dados são realmente úteis para um compilador / máquina virtual.

Finalmente, para colocar tudo em perspectiva, considere o seguinte: um programa Python executado por um interpretador / máquina virtual Python implementado em Java em execução em um interpretador / máquina virtual Java implementado em LLVM em execução em uma máquina virtual qemu em um iPhone.

permalink

pooryorick
fonte
1
trying to write any statically-typed code interactively would be tedious. Se você conhece OCaml e Haskell, verá que isso não é verdade, pois são linguagens estaticamente muito concisas.
Matthias Braun
@MatthiasBraun Posso concordar que essas linguagens funcionais produzem código conciso, mas isso não significa necessariamente que elas sejam adequadas ao modo interativo. Se OCaml e Haskell fossem dinamicamente tipados como lisp, eles funcionariam melhor para o modo interativo, presumo.
bombas
58

Provavelmente, um motivo para a terminologia diferente é que normalmente se pensa em alimentar o código-fonte legível por humanos do interpretador python e não se preocupar com o bytecode e tudo mais.

Em Java, é necessário compilar explicitamente para o bytecode e, em seguida, executar apenas o bytecode, não o código-fonte na VM.

Embora o Python use uma máquina virtual oculta, na perspectiva do usuário, é possível ignorar esse detalhe na maioria das vezes.

Mr Fooz
fonte
1
Concordo. Essa diferença de terminologia realmente se resume à experiência do usuário final (desenvolvedor, ou seja). Não tem nada a ver com diferenças técnicas reais, já que a linha técnica é tão incrivelmente desfocada que é quase inexistente.
Cody Brocious
1
+1: e - mais importante - qual é o objetivo? Que programa você não pode escrever por causa dessa distinção? Que pilha de traceback está confundindo você? Qual biblioteca não parece funcionar corretamente?
S.Lott
@ S.Lott Porque é sempre bom ganhar discussões com os colegas. ;)
Qix - MONICA FOI ERRADA
16

Intérprete , converte o código fonte em alguma representação intermediária eficiente (código) e executa isso imediatamente.

Virtual Machine , executa explicitamente o código pré-compilado armazenado, criado por um compilador que faz parte do sistema de intérpretes.

Uma característica muito importante de uma máquina virtual é que o software executado dentro dela é limitado aos recursos fornecidos pela máquina virtual. Precisamente, ele não pode sair do seu mundo virtual. Pense na execução segura do código remoto, Java Applets.

No caso de python, se estamos mantendo pyc arquivos , como mencionado no comentário deste post, o mecanismo se tornará mais como uma VM e esse bytecode será executado mais rapidamente - ainda seria interpretado, mas de uma forma muito mais amigável ao computador . Se olharmos para isso como um todo, o PVM é um último passo do Python Interpreter.

O ponto principal é que, quando se refere o Python Interpreter, significa que o referimos como um todo, e quando dizemos PVM, isso significa que estamos apenas falando sobre uma parte do Python Interpreter, um ambiente de tempo de execução. Semelhante ao Java, nos referimos a diferentes partes differentyl, JRE, JVM, JDK, etc.

Para mais, Wikipedia Entry: Intérprete e Máquina Virtual . Mais um aqui . Aqui você encontra a Comparação de máquinas virtuais de aplicativos . Ajuda a entender a diferença entre compiladores, intérpretes e VMs.

Adeel Ansari
fonte
12

O termo intérprete é um termo herdado que remonta às linguagens de script de shell anteriores. Como as "linguagens de script" evoluíram para linguagens completas e suas plataformas correspondentes se tornaram mais sofisticadas e em área restrita, a distinção entre uma máquina virtual e um intérprete (no sentido Python) é muito pequena ou inexistente.

O interpretador Python ainda funciona da mesma maneira que um script de shell, no sentido de que pode ser executado sem uma etapa de compilação separada. Além disso, as diferenças entre o intérprete do Python (ou Perl ou Ruby) e a máquina virtual do Java são principalmente detalhes de implementação. (Pode-se argumentar que o Java é mais seguro do que o Python, mas ambos fornecem acesso à arquitetura subjacente por meio de uma interface C nativa.)

Daniel Naab
fonte
1
existem shells java que podem executar código java sem etapas de compilação separadas (visíveis pelo usuário).
Lie Ryan
1
me dê o nome: D
Maciej Nowicki 18/10
11

Para fornecer uma resposta profunda à pergunta " Por que Java Virtual Machine, mas Python intérprete? ", Vamos tentar voltar ao campo da teoria da compilação quanto ao ponto de partida da discussão.

O processo típico de compilação de programas inclui as próximas etapas:

  1. Análise lexical . Divide o texto do programa em "palavras" significativas chamadas tokens (como parte do processo, todos os comentários, espaços, novas linhas etc. são removidos, porque não afetam o comportamento do programa). O resultado é um fluxo ordenado de tokens.
  2. Análise de sintaxe . Constrói a chamada Árvore Sintaxe Abstrata (AST) partir do fluxo de tokens. A AST estabelece relações entre tokens e, como conseqüência, define uma ordem de avaliação do programa.
  3. Análise semântica . Verifica a correção semântica do AST usando informações sobre tipos e um conjunto de regras semânticas da linguagem de programação. (Por exemplo, a = b + cé uma declaração correta do ponto de vista da sintaxe, mas completamente incorreta do ponto de vista semântico, se afoi declarada como um objeto constante)
  4. Geração intermediária de código . Serializa o AST no fluxo ordenado linearmente de operações "primitivas" independentes da máquina. De fato, o gerador de código percorre o AST e registra a ordem das etapas de avaliação. Como resultado, a partir da representação em árvore do programa, obtemos uma representação em lista muito mais simples, na qual a ordem de avaliação do programa é preservada.
  5. Geração de código de máquina . O programa na forma de bytecode "primitivo" independente da máquina é traduzido em código de máquina da arquitetura específica do processador.

Está bem. Vamos agora definir os termos.

Intérprete , no significado clássico dessa palavra, assume a execução com base na avaliação do programa com base no AST produzido diretamente a partir do texto do programa . Nesse caso, um programa é distribuído na forma de código-fonte e o intérprete é alimentado pelo texto do programa, frequentemente de maneira dinâmica (declaração por declaração ou linha por linha). Para cada instrução de entrada, o intérprete cria seu AST e o avalia imediatamente, alterando o "estado" do programa. Esse é um comportamento típico demonstrado pelas linguagens de script. Considere, por exemplo, Bash, Windows CMD, etc. Conceitualmente, o Python também toma esse caminho.

Se substituirmos a etapa de execução baseada em AST na geração da etapa do bytecode binário intermediário independente da máquina no interpretador, dividiremos todo o processo de execução do programa em duas fases separadas: compilação e execução. Nesse caso, o que anteriormente era um intérprete se tornará um compilador de bytecode, que transformará o programa da forma do texto em alguma forma binária . Em seguida, o programa é distribuído nessa forma binária, mas não na forma de código-fonte. Na máquina do usuário, esse bytecode é alimentado em uma nova entidade - máquina virtual , que de fato interpreta esse bytecode. Devido a isso, as máquinas virtuais também são chamadas de intérprete de bytecode . Mas coloque sua atenção aqui! Um intérprete clássico é umintérprete de texto intérprete , mas uma máquina virtual é umbinário ! Essa é uma abordagem adotada por Java e C #.

Finalmente, se adicionarmos a geração de código de máquina ao compilador de bytecode, obteremos como resultado o que chamamos de compilador clássico . Um compilador clássico converte o código-fonte do programa no código de máquina de um processador específico. Esse código de máquina pode ser executado diretamente no processador de destino sem nenhuma mediação adicional (sem nenhum tipo de intérprete nem intérprete de texto nem intérprete binário).

Vamos agora voltar à pergunta original e considerar Java vs Python.

O Java foi projetado inicialmente para ter o menor número possível de dependências de implementação. Seu design é baseado no princípio "escreva uma vez, execute em qualquer lugar" (WORA). Para implementá-lo, o Java foi inicialmente projetado como uma linguagem de programação que é compilada no bytecode binário independente da máquina , que pode ser executado em todas as plataformas que suportam o Java sem a necessidade de sua recompilação. Você pode pensar em Java como no C ++ baseado em WORA . Na verdade, o Java está mais próximo do C ++ do que das linguagens de script como Python . Mas, ao contrário do C ++ , Javafoi projetado para ser compilado no bytecode binário, que é executado no ambiente da máquina virtual , enquanto o C ++ foi projetado para ser compilado no código da máquina e, em seguida, executado diretamente pelo processador de destino.

O Python foi inicialmente projetado como um tipo de linguagem de programação de script que interpreta scripts (programas na forma do texto escrito de acordo com as regras da linguagem de programação). Devido a isso, o Python inicialmente suportou uma interpretação dinâmica de comandos ou instruções de uma linha, como fazem o Bash ou o Windows CMD. Pela mesma razão, as implementações iniciais do Python não possuíam nenhum tipo de compilador de bytecode e máquinas virtuais para execução desse bytecode, mas desde o início o Python exigiu um intérprete capaz de entender e avaliar o texto do programa Python .

Devido a isso, historicamente, os desenvolvedores Java tendem a falar sobre Java Virtual Machine (porque, inicialmente, Java veio como pacote do compilador de bytecodes Java e interpretador de bytecode - JVM ), e os desenvolvedores Python tendem a falar sobre o interpretador Python (porque inicialmente o Python possui nenhuma máquina virtual e era um tipo de interpretador clássico de texto que executa o texto do programa diretamente, sem nenhum tipo de compilação ou transformação em qualquer forma de código binário).

Atualmente, o Python também tem a máquina virtual oculta e pode compilar e interpretar o bytecode do Python. E esse fato faz um investimento adicional na confusão " Por que Java Virtual Machine, mas intérprete Python?e que os programas demonstrarão exatamente o mesmo comportamento e produzirão igualmente a mesma saída a partir da entrada igual. A única diferença observável será a velocidade de execução do programa e a quantidade de memória consumida pelo intérprete. Portanto, a máquina virtual no Python não é uma parte inevitável do design da linguagem, mas apenas uma extensão opcional do principal intérprete do Python.

Java pode ser considerado de maneira semelhante. Java sob o capô tem um compilador JIT e pode compilar seletivamente métodos da classe Java no código de máquina da plataforma de destino e, em seguida, executá-lo diretamente. Mas! O Java ainda usa a interpretação do bytecode como uma maneira principal de execução do programa Java. Como implementações em Python que exploram máquinas virtuais sob o capô exclusivamente como uma técnica de otimização, as máquinas virtuais Java usam compiladores Just-In-Time exclusivamente para fins de otimização. Da mesma forma, apenas devido ao fato de que a execução direta do código da máquina é pelo menos dez vezes mais rápida que a interpretação do bytecode Java. E, como no caso do Python, a presença do compilador JIT sob o capô da JVM é absolutamente transparente para designers de linguagem Java e desenvolvedores de programas Java. A mesma linguagem de programação Java pode ser implementada pela JVM com e sem o compilador JIT. E da mesma maneira, os mesmos programas podem ser executados em JVMs com e sem JIT dentro, e os mesmos programas demonstrarão exatamente o mesmo comportamento e produzirão igualmente a mesma saída da entrada igual nas duas JVMs (com e sem JIT). E, como no caso do Python, a única diferença observável entre eles estará na velocidade de execução e na quantidade de memória consumida pela JVM. E, finalmente, como no caso do Python, o JIT em Java também não é uma parte inevitável do design da linguagem, mas apenas uma extensão opcional das principais implementações da JVM. e os mesmos programas demonstrarão exatamente o mesmo comportamento e produzirão igualmente a mesma saída da entrada igual nas duas JVMs (com e sem JIT). E, como no caso do Python, a única diferença observável entre eles estará na velocidade de execução e na quantidade de memória consumida pela JVM. E, finalmente, como no caso do Python, o JIT em Java também não é uma parte inevitável do design da linguagem, mas apenas uma extensão opcional das principais implementações da JVM. e os mesmos programas demonstrarão exatamente o mesmo comportamento e produzirão igualmente a mesma saída da entrada igual nas duas JVMs (com e sem JIT). E, como no caso do Python, a única diferença observável entre eles estará na velocidade de execução e na quantidade de memória consumida pela JVM. E, finalmente, como no caso do Python, o JIT em Java também não é uma parte inevitável do design da linguagem, mas apenas uma extensão opcional das principais implementações da JVM.

Do ponto de vista do design e implementação de máquinas virtuais de Java e Python, eles diferem significativamente, enquanto (atenção!) Ambos ainda permanecem máquinas virtuais. A JVM é um exemplo de uma máquina virtual de baixo nível, com operações básicas simples e alto custo de envio de instruções. O Python, por sua vez, é uma máquina virtual de alto nível, para a qual as instruções demonstram um comportamento complexo e o custo de envio de instruções não é tão significativo. Java opera com nível de abstração muito baixo. A JVM opera no pequeno conjunto bem definido de tipos primitivos e possui uma correspondência muito estreita (geralmente de um a um) entre instruções de bytecode e instruções de código de máquina nativas. Pelo contrário, a máquina virtual Python opera em alto nível de abstração, opera com tipos de dados complexos (objetos) e suporta polimorfismo ad-hoc, enquanto as instruções de bytecode expõem um comportamento complexo, que pode ser representado por uma série de várias instruções de código de máquina nativas. Por exemplo, o Python suporta matemática de alcance ilimitado. Portanto, a VM do Python é forçada a explorar aritmética longa para números inteiros potencialmente grandes para os quais o resultado da operação pode exceder a palavra da máquina. Portanto, uma instrução de bytecode para aritmética no Python pode se expor na chamada de função dentro do Python VM, enquanto na operação aritmética da JVM se exporá na operação simples expressa por uma ou poucas instruções nativas da máquina. Portanto, a VM do Python é forçada a explorar aritmética longa para números inteiros potencialmente grandes para os quais o resultado da operação pode exceder a palavra da máquina. Portanto, uma instrução de bytecode para aritmética no Python pode se expor na chamada de função dentro do Python VM, enquanto na operação aritmética da JVM se exporá na operação simples expressa por uma ou poucas instruções nativas da máquina. Portanto, a VM do Python é forçada a explorar aritmética longa para números inteiros potencialmente grandes para os quais o resultado da operação pode exceder a palavra da máquina. Portanto, uma instrução de bytecode para aritmética no Python pode se expor na chamada de função dentro do Python VM, enquanto na operação aritmética da JVM se exporá na operação simples expressa por uma ou poucas instruções nativas da máquina.

Como resultado, podemos tirar as próximas conclusões. Java Virtual Machine, mas o interpretador Python é porque:

  1. O termo máquina virtual assume a interpretação binária do bytecode, enquanto o termo intérprete assume a interpretação do texto do programa.
  2. Historicamente, Java foi projetado e implementado para interpretação de bytecode binário e Python foi inicialmente projetado e implementado para interpretação de texto de programa. Portanto, o termo "Java Virtual Machine" é histórico e bem estabelecido na comunidade Java. Da mesma forma, o termo "Intérprete Python" é histórico e bem estabelecido na comunidade Python. Os povos tendem a prolongar a tradição e usam os mesmos termos que foram usados ​​muito antes.
  3. Finalmente, atualmente, para Java, a interpretação de bytecode binário é a principal maneira de execução de programas, enquanto a compilação JIT é apenas uma otimização opcional e transparente. E para o Python, atualmente, a interpretação do texto do programa é a principal maneira de execução dos programas Python, enquanto a compilação no bytecode da VM do Python é apenas uma otimização opcional e transparente.

Portanto, Java e Python têm máquinas virtuais como intérpretes binários de bytecode, o que pode gerar confusão como " Por que Java Virtual Machine, mas interpretador de Python? ". O ponto principal aqui é que, para Python, uma máquina virtual não é um meio primário ou necessário de execução do programa; é apenas uma extensão opcional do interpretador de texto clássico. Por outro lado, uma máquina virtual é uma parte essencial e inevitável do ecossistema de execução de programas Java. A escolha de digitação estática ou dinâmica para o design da linguagem de programação afeta principalmente apenas o nível de abstração da máquina virtual, mas não determina se uma máquina virtual é ou não necessária. Os idiomas que usam os dois sistemas de digitação podem ser projetados para serem compilados, interpretados ou executados no ambiente da máquina virtual, dependendo do modelo de execução desejado.

ZarathustrA
fonte
2
Isto deve ser escolhido como a resposta oficial IMHO.
Ravikanth Andhavarapu
A resposta oficial deve ser feita pelo SIM, pois "Java e Python têm máquinas virtuais são intérpretes binários de bytecode". Período.
Stuartw
10

Não há diferença real entre eles, as pessoas seguem as convenções que os criadores escolheram.

Cody Brocious
fonte
3
Vou lhe dar uma ajuda aqui, já que acho que essa é provavelmente a resposta real e você foi votado por falta de bits.
vikingben
3

Não esqueça que o Python tem compiladores JIT disponíveis para x86, confundindo ainda mais o problema. (Veja psico).

Uma interpretação mais rigorosa de uma 'linguagem interpretada' só se torna útil quando se discute problemas de desempenho da VM, por exemplo, comparado ao Python, Ruby foi (é?) Considerado mais lento porque é uma linguagem interpretada, diferente do Python - em outras palavras, contexto é tudo.

Arafangion
fonte
1
Isto é errado. Primeiro, não existe uma "linguagem interpretada". Se uma implementação usa um compilador ou um intérprete não é uma característica do idioma, mas da implementação. Segundo, das 13 implementações Ruby, exatamente 1 é um intérprete, todas as outras possuem compiladores.
Jörg W Mittag
2
Terceiro, Ruby não é lento. Nenhuma linguagem é lenta, porque a velocidade não é uma característica da linguagem, mas sua implementação. Das 13 implementações Ruby, algumas são mais lentas que as 7 implementações do Python, outras são mais rápidas.
Jörg W Mittag
Eu acho que ele está comparando as implementações padrão aqui Jörg. CPython e Ruby (acho que a implementação oficial se chama Ruby).
21419 James McMahon
Embora Arafangion possa estar se referindo às implementações "padrão", ele deveria ter dito isso. Sou Pythonista, mas odeio qualquer declaração da forma "A linguagem X é lenta", pois concordo com Jörg no que diz respeito às implementações.
tzot 15/01/09
1
É exatamente por isso que eu disse "era (é?)" E, particularmente, o termo "mais lento". Em nenhum lugar eu disse que Ruby é por si só lento.
Arafangion
2

O Python pode interpretar o código sem compilá-lo no bytecode. Java não pode .

Python é uma linguagem interpretada, em oposição a uma linguagem compilada, embora a distinção possa ser imprecisa devido à presença do compilador de bytecodes. Isso significa que os arquivos de origem podem ser executados diretamente sem criar explicitamente um executável que é executado.

(da documentação).

Em Java, cada arquivo tem que ser compilado para um .classarquivo, que, em seguida, é executado na JVM. Pelo contrário, o python é importado pelo script principal, para ajudar a acelerar o uso subsequente desses arquivos.

No entanto, no caso típico, a maioria do código python (pelo menos, CPython) é executado em uma máquina de pilha emulada, que possui instruções quase idênticas às da JVM, portanto, não há grande diferença.

A verdadeira razão para a discordância, no entanto, é porque, desde o início, o java se identificou como "bytecode portátil e executável" e o python se identificou como linguagem interpretada dinâmica com um REPL. Os nomes ficam!

nota azul
fonte
0

Antes de tudo, você deve entender que programação ou ciência da computação em geral não é matemática e não temos definições rigorosas para a maioria dos termos que usamos frequentemente.

agora para sua pergunta:

o que é um intérprete (em ciência da computação)

Ele converte o código-fonte pela menor unidade executável e depois executa essa unidade.

o que é uma máquina virtual

no caso da JVM, a máquina virtual é um software que contém um intérprete, carregadores de classes, coletor de lixo, programador de encadeamentos, compilador JIT e muitas outras coisas.

como você pode ver, o intérprete é uma peça ou JVM e a JVM inteira não pode ser chamada de intérprete porque contém muitos outros componentes.

por que usar a palavra "intérprete" ao falar sobre python

com java, a parte da compilação é explícita. python, por outro lado, não é explícito como java sobre seu processo de compilação e interpretação, da perspectiva do usuário final, a interpretação é o único mecanismo usado para executar programas python

mightyWOZ
fonte
0

Não, os dois não interpretam o código de bytes.

O Python interpreta apenas o bytecode se você estiver executando o pypy. Caso contrário, é compilado em C e interpretado nesse nível.

Java compila para bytecode.

Michael Tamillow
fonte
Você pode dar algum recurso à sua resposta?
Isuru Dilshan
e este é em Java: en.wikipedia.org/wiki/Java_virtual_machine
Michael Tamillow
Isso é o que há de errado com o Stack Overflow. Alguém tem um ataque de irritação porque é chamado e o expressa com votos negativos.
Michael Tamillow 30/01
0

Eu acho que as linhas entre os dois são borradas, as pessoas discutem principalmente sobre o significado da palavra "intérprete" e o quão próxima a linguagem está de cada lado do espectro "intérprete ... compilador". Ninguém faz 100% no entanto. Eu acho que é fácil escrever a implementação Java ou Python que seja de qualquer valor do espectro.

Atualmente, Java e Python têm máquinas virtuais e bytecode, embora um opere por tamanhos de valores concretos (como número inteiro de 32 bits), enquanto outro precisa determinar o tamanho de cada chamada, o que, na minha opinião, não define a fronteira entre os termos.

O argumento de que o Python não possui bytecode oficialmente definido e que existe apenas na memória também não me convence, apenas porque estou planejando desenvolver dispositivos que reconheçam apenas o bytecode do Python e a parte da compilação será feita na máquina JS do navegador.

O desempenho é apenas sobre a implementação concreta. Não precisamos saber o tamanho do objeto para poder trabalhar com ele e, finalmente, na maioria dos casos, trabalhamos com estruturas, não com tipos básicos. É possível otimizar a VM do Python da maneira que elimina a necessidade de criar um novo objeto a cada vez durante o cálculo da expressão, reutilizando um existente. Feito isso, não há diferença de desempenho global entre o cálculo da soma de dois números inteiros, que é onde o Java brilha.

Não há diferença significativa entre os dois, apenas algumas nuances de implementação e falta de otimização que são irrelevantes para o usuário final, talvez até no ponto em que ela começa a notar lags de desempenho, mas novamente é questão de implementação e não de arquitetura.

Oleg Gordeev
fonte
0

para posts que mencionam que o python não precisa gerar código de bytes, não tenho certeza se isso é verdade. parece que todas as chamadas no Python devem ter um .__code__.co_codeatributo que contenha o código de bytes. Não vejo uma razão significativa para chamar python "não compilado" apenas porque os artefatos compilados podem não ser salvos; e muitas vezes não são salvos por design em Python, por exemplo, toda compreensão compila novo bytecode para sua entrada; esse é o motivo pelo qual o escopo da variável de compreensão não é consistente entre compile(mode='exec, ...)e compila compile(mode='single', ...), como entre executar um script python e usar pdb

ThorSummoner
fonte