Javaの「仮想マシン」とPythonの「インタープリター」という用語の違いは?


207

Javaでは「仮想マシン」が常に使用されているのに、Pythonの「仮想マシン」を読むのはまれなようです。

どちらもバイトコードを解釈します。なぜ一方を仮想マシン、もう一方をインタープリターと呼ぶのですか?

回答:


137

仮想マシンは、特定の言語に依存せずにサポートされる特定のアトミックで明確な命令セットを備えた仮想コンピューティング環境であり、一般的にそれ自体がサンドボックスと見なされます。VMは特定のCPUの命令セットに類似しており、そのような命令の非常に基本的なビルディングブロック(またはバイトコード)が次のものから独立しているため、より基本的なレベルで機能する傾向があります。命令は、仮想マシンの現在の状態のみに基づいて確定的に実行され、その時点での命令ストリームの他の場所の情報には依存しません。

一方、インタープリターは、周囲のトークンのコンテキストでデコードする必要がある特定の言語および特定の文法の構文のストリームを解析するように調整されているという点で、より洗練されています。各バイトまたは各行を分離して見ることはできず、次に何をすべきかを正確に知ることはできません。言語のトークンは、VMの命令(バイトコード)とは異なり、個別に取得することはできません。

Javaコンパイラは、Java言語をバイトコードストリームに変換します。Cコンパイラは、C言語プログラムをアセンブリコードに変換するのと同じです。一方、インタープリターは、プログラムを明確に定義された中間形式に変換するのではなく、ソースを解釈するプロセスの問題としてプログラムのアクションを実行するだけです。

VMとインタープリターの違いのもう1つのテストは、それを言語に依存しないと考えるかどうかです。Java VMとしてわかっているのは、実際にはJava固有ではありません。JVMで実行できるバイトコードを生成する他の言語からコンパイラを作成できます。一方、Pythonインタープリターによる解釈のために、Python以外の他の言語をPythonに「コンパイル」することはあまり考えないでしょう。

解釈プロセスは洗練されているため、これは比較的遅いプロセスになる可能性があります。具体的には、言語トークンなどを解析して識別し、ソースのコンテキストを理解して、インタープリター内で実行プロセスを実行できるようにします。このようなインタープリター型言語を高速化するために、ここでは、より簡単に直接解釈される、事前に解析され、事前にトークン化されたソースコードの中間形式を定義できます。この種のバイナリ形式は実行時に解釈されますが、パフォーマンスを向上させるために、人間が判読しにくい形式から始まっています。ただし、そのフォームを実行するロジックは仮想マシンではありません。これらのコードを分離して取得することはまだできないためです。周囲のトークンのコンテキストは依然として重要であり、今では別のよりコンピューター効率的なフォームになっています。


7
私はpythonがバイトコード、pycを生成した、または「そのような解釈された言語を加速するのに役立つ、これがより多くの事前に解析され、事前にトークン化されたソースコードの中間形式を定義できる場所です。すぐに直接解釈されます。」
James McMahon、

32
@InSciTek Jeff:あなたの答えから、Pythonが仮想マシンも使用していることを知っているかどうかはわかりません。
tzot 2009年

3
@TZ-人気のあるPython実装は、裏側VMを備えたPythonコンパイラです。インタラクティブモードでは、インタプリタフロントエンドとコンパイラバックエンドの両方と少しハイブリッドです。ただし、これらは実装の選択です。VMの概念とインタープリターの違いを説明しようとした
Tall 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.ScalaがJavaバイトコードにコンパイルされるのと同じように、Pythonバイトコードにコンパイルできる言語を書くことができます。インタラクティブモードでは、Pythonのインタラクティブシェルが入力されたコマンドをバイトコードにコンパイルし、そのバイトコードを実行します。evalとexecを使用して独自のシェルを記述でき、compile()組み込み関数を使用して文字列をバイトコードに変換できます。
ライライアン

4
@Lie Ryanはい、しかし、JVMのように公式にはサポートされていません。Pythonでは、バイトコードは文書化されていない実装の詳細です。
アンチモン2014

159

この投稿では、「仮想マシン」はプロセス仮想マシンを指し、QemuやVirtualboxのようなシステム仮想マシンを指しません。プロセス仮想マシンは、一般的なプログラミング環境を提供する単なるプログラムであり、プログラム可能なプログラムです。

Javaにはインタープリターと仮想マシンがあり、Pythonには仮想マシンとインタープリターがあります。「仮想マシン」がJavaでより一般的な用語であり、「インタープリター」がPythonでより一般的な用語である理由は、静的タイピング(Java)と動的タイピング(Python)の2つの言語の主な違いに大きく関係しています。このコンテキストでは、「タイプ」はプリミティブデータタイプ(データのメモリ内ストレージサイズを示唆するタイプ)を指し ます。Java仮想マシンは簡単です。プログラマーは、各変数のプリミティブデータ型を指定する必要があります。これにより、JavaバイトコードがJava仮想マシンによって解釈および実行されるだけでなく、マシン命令にコンパイルされるための十分な情報が提供されます。。Python仮想マシンは、各操作の実行前に一時停止して、操作に含まれる各変数またはデータ構造のプリミティブデータ型を判別するという追加のタスクを実行するという意味で、より複雑です。Pythonを使用すると、プログラマーはプリミティブデータ型について考える必要がなくなり、操作をより高いレベルで表現できます。この自由の代償はパフォーマンスです。「インタプリタ」は、データ型を検査するために一時停止する必要があるため、また動的に型付けされた言語の比較的簡潔な構文がインタラクティブなインタフェースに適しているため、Pythonの推奨用語です。インタラクティブなJavaインターフェースを構築するのに技術的な障壁はありませんが、静的に型付けされたコードをインタラクティブに記述しようとするのは面倒なので、そのようには行われません。

Javaの世界では、仮想マシンは実際にマシン命令にコンパイルできる言語で記述されたプログラムを実行し、その結果、速度とリソース効率が向上するため、仮想マシンがショーを盗みます。比較的言えば、Javaバイトコードは、コンパイルされたプログラムのパフォーマンスに近いパフォーマンスでJava仮想マシンによって実行できます。これは、バイトコードにプリミティブデータタイプ情報が存在するためです。Java仮想マシンは、Javaを独自のカテゴリに分類します。

移植性のある静的型付け言語

次に近いのはLLVMですが、LLVMは異なるレベルで動作します。

ポータブルなインタープリター型アセンブリ言語

「バイトコード」という用語はJavaとPythonの両方で使用されていますが、すべてのバイトコードが同等に作成されているわけではありません。バイトコードは、コンパイラー/インタープリターが使用する中間言語の総称です。gccのようなCコンパイラでさえ、中間言語(またはいくつか)を使用して作業を完了します。Javaバイトコードにはプリミティブデータ型に関する情報が含まれていますが、Pythonバイトコードには含まれていません。この点で、Python(およびBash、Perl、Rubyなど)の仮想マシンは、Javaの仮想マシンよりも根本的に低速であるか、実行する作業が多いだけです。さまざまなバイトコード形式に含まれている情報を検討すると便利です。

  • llvm: cpuレジスタ
  • Java:プリミティブデータ型
  • Python:ユーザー定義型

現実的な例えを描くと、LLVMはアトムで動作し、Java仮想マシンは分子で動作し、Python仮想マシンはマテリアルで動作します。最終的にはすべてが原子以下の粒子(実際のマシン操作)に分解される必要があるため、Python仮想マシンには最も複雑なタスクがあります。

静的に型付けされた言語のインタプリタ/コンパイラは、動的に型付けされた言語のインタプリタ/コンパイラと同じ手荷物を持っていません。静的に型付けされた言語のプログラマはスラックを吸収する必要があります。ただし、すべての非決定論的関数がひそかに決定論的であるのと同じように、すべての動的型付け言語がひそかに静的型付けされます。したがって、2つの言語ファミリのパフォーマンスの違いは、Pythonがその名前をHAL 9000に変更する頃に横ばいになるはずです。

Pythonのような動的言語の仮想マシンは、いくつかの理想的な論理マシンを実装しており、必ずしも実際の物理ハードウェアに厳密に対応しているわけではありません。対照的に、Java仮想マシンは、機能が従来のCコンパイラーに似ていますが、マシン命令を発行する代わりに組み込みルーチンを実行する点が異なります。Pythonでは、整数は一連の属性とメソッドが付加されたPythonオブジェクトです。Javaでは、intは指定されたビット数で、通常は32です。これは、実際には公平な比較ではありません。Python整数は、Java Integerクラスと実際に比較する必要があります。Java言語の「int」プリミティブデータ型は、Python言語の何にも比較できません。Python言語には、このプリミティブのレイヤーが欠けているだけであり、Pythonバイトコードも同様です。

Java変数は明示的に型付けされているため、JythonのパフォーマンスのようなものがcPythonと同じように機能すること が合理的に期待できます。一方、Pythonで実装されたJava仮想マシンは、泥よりも低速であることがほぼ保証されています。そして、RubyやPerlなどがこれよりうまくいくと期待しないでください。彼らはそうするように設計されていませんでした。これらは「スクリプト」用に設計されており、動的言語でのプログラミングが呼ばれています。

仮想マシンで行われるすべての操作は、最終的には実際のハードウェアに到達する必要があります。仮想マシンには、論理演算の任意の組み合わせを実行するのに十分一般的な事前コンパイルされたルーチンが含まれています。仮想マシンは新しいマシン命令を発行していない可能性がありますが、独自のルーチンを不規則に複雑なシーケンスで繰り返し実行しています。Java仮想マシン、Python仮想マシン、および他のすべての汎用仮想マシンは、思いつくあらゆるロジックを実行するように調整できるという点では同等ですが、それらのタスクは異なります。引き受け、プログラマに任せるタスク。

Psyco for Pythonは完全なPython仮想マシンではありませんが、数行のコードをコンパイルできると思われる時点で通常のPython仮想マシンをハイジャックするジャストインタイムコンパイラー-主に、いくつかのプリミティブ型を考えるループ変数は、反復のたびに値が変化しても一定のままです。その場合、通常の仮想マシンの継続的なタイプの決定の一部を無視できます。ただし、タイプをPsycoの足元から引き出さないように、少し注意する必要があります。ただし、Pyscoは通常、タイプが変更されないと確信が持てない場合、通常の仮想マシンにフォールバックすることを知っています。

この話の教訓は、プリミティブなデータ型情報はコンパイラ/仮想マシンにとって本当に役立つということです。

最後に、すべてを全体的に見ると、次のことを考慮してください。iPhoneで実行されるqemu仮想マシンで実行されるLLVMで実行されるJavaインタープリター/仮想マシンで実行されるJavaで実装されるPythonインタープリター/仮想マシンによって実行されるPythonプログラム。

パーマリンク


1
trying to write any statically-typed code interactively would be tedious。OCamlとHaskellを知っていれば、静的型付けの非常に簡潔な言語であるため、そうではないことがわかります。
Matthias Braun

@MatthiasBraunこれらの関数型言語が簡潔なコードを生成することには同意できますが、必ずしもそれらがインタラクティブモードに適しているとは限りません。OCamlとHaskellがlispのように動的に型付けされていれば、私が想定しているインタラクティブモードの方がうまく機能します。
爆弾

58

おそらく異なる用語の1つの理由は、Pythonインタープリターに人間が読める生のソースコードをそのままフィードし、バイトコードなどを気にしないことを考えているためです。

Javaでは、明示的にバイトコードにコンパイルしてから、VMのソースコードではなく、バイトコードだけを実行する必要があります。

Pythonは仮想マシンを内部で使用していますが、ユーザーの観点からは、ほとんどの場合この詳細を無視できます。


1
同意する。この用語の違いは、実際にはエンドユーザー(開発者、つまり)の経験に起因します。実際の技術的な違いとは何の関係もありません。技術的なラインが非常に不鮮明で、存在しないほどに近いからです。
Cody Brocious

1
+1:そして-さらに重要なこと-要点は何ですか?この違いのために、あなたはどんなプログラムを書くことができませんか?どのスタックトレースバックがあなたを混乱させていますか?どのライブラリが正しく機能していないようですか?
S.Lott、2009年

@ S.Lott同僚との議論に勝つことは常に良いことだからです。;)
Qix-モニカは2014年

16

Interpreterは、ソースコードをいくつかの効率的な中間表現(コード)に変換し、すぐにこれを実行します。

仮想マシンは、インタープリターシステムの一部であるコンパイラーによってビルドされた、保存済みのプリコンパイル済みコードを明示的に実行します。

仮想マシンの非常に重要な特性は、内部で実行されるソフトウェアが、仮想マシンによって提供されるリソースに制限されることです。正確には、仮想世界から抜け出すことはできません。リモートコードの安全な実行、Javaアプレットについて考えてみましょう。

Pythonの場合、この投稿のコメントで述べたようにpycファイルを保持している場合、メカニズムはVMのようになり、このバイトコードはより高速に実行されます-それでも解釈されますが、コンピューターにやさしい形式です。これを全体として見ると、PVMはPythonインタープリターの最後のステップです。

要点は、Pythonインタープリターを参照するときは、それを全体として参照することを意味し、PVMを言うときは、実行時環境であるPythonインタープリターの一部について話しているだけです。Javaと同様に、JRE、JVM、JDKなどのさまざまな部分を区別します。

詳細については、Wikipedia Entry:Interpreter、およびVirtual Machineをご覧ください。ここでもう1つ。ここには、アプリケーション仮想マシンの比較があります。コンパイラ、インタープリタ、VMの違いを理解するのに役立ちます。


12

インタープリターという用語は、以前のシェルスクリプト言語にさかのぼるレガシー用語です。「スクリプト言語」がフル機能の言語に進化し、対応するプラットフォームがより洗練され、サンドボックス化されるにつれて、仮想マシンとインタプリタ(Pythonの意味で)の違いは非常に小さいか、存在しなくなります。

Pythonインタープリターは、別個のコンパイル手順なしで実行できるという意味で、シェルスクリプトと同じように機能します。さらに、Pythonのインタプリタ(またはPerlやRubyのインタプリタ)とJavaの仮想マシンの違いは、ほとんどが実装の詳細です。(JavaはPythonよりも完全にサンドボックス化されていると主張することもできますが、どちらも最終的にはネイティブCインターフェースを介して基礎となるアーキテクチャへのアクセスを提供します。)


1
個別の(ユーザーに表示される)コンパイル手順なしでJavaコードを実行できるJavaシェルがあります。
Lie Ryan

1
Gimme the name:D
Maciej Nowicki

11

なぜJava仮想マシンなのにPythonインタープリターなのか」という質問に対する深い回答を提供するために、議論の出発点としてコンパイル理論の分野に戻りましょう。

プログラムのコンパイルの一般的なプロセスには、次のステップが含まれます。

  1. 字句解析トークンと呼ばれる意味のある「単語」にプログラムのテキストを分割します(プロセスの一部として、コメント、スペース、改行などはプログラムの動作に影響しないため、削除されます)。結果は、順序付けられたトークンのストリームです。
  2. 構文解析。トークンのストリームから、いわゆる抽象構文ツリー(AST)を構築します。ASTはトークン間の関係を確立し、その結果、プログラムの評価順序を定義します。
  3. 意味分析。プログラミング言語の型と一連のセマンティックルールに関する情報を使用して、ASTのセマンティックな正当性を検証します。(たとえば、a = b + cは構文の観点からは正しいステートメントですaが、が定数オブジェクトとして宣言されている場合、セマンティックの観点からは完全に正しくありません)
  4. 中間コード生成。ASTをシリアル化して、マシンに依存しない「プリミティブ」操作の線形に並べられたストリームにします。実際、コードジェネレーターはASTをトラバースし、評価ステップの順序を記録します。その結果、プログラムのツリー状の表現から、プログラム評価の順序が保持される、はるかに単純なリストのような表現が実現されます。
  5. マシンコード生成。マシンに依存しない「プリミティブ」バイトコードの形式のプログラムは、特定のプロセッサアーキテクチャのマシンコードに変換されます。

OK。用語を定義しましょう。

Interpreterは、その単語の古典的な意味で、プログラムテキストから直接生成されたASTに基づくプログラム評価に基づいて実行されることを前提としています。その場合、プログラムはソースコードの形式で配布され、インタープリターはプログラムテキストによって、頻繁に動的な方法で(ステートメントごとまたは行ごとに)提供されます。入力ステートメントごとに、インタープリターはそのASTを作成し、プログラムの「状態」を変更して即座に評価します。これは、スクリプト言語によって示される典型的な動作です。たとえば、Bash、Windows CMDなどを検討してください。概念的には、Pythonもこの方法を採用しています。

インタープリターで中間のマシンに依存しないバイナリバイトコードステップの生成でASTベースの実行ステップを置き換える場合、プログラム実行のプロセス全体を2つの別々のフェーズ(コンパイルと実行)に分割します。その場合、以前はインタープリターであったものがバイトコードコンパイラになり、プログラムがテキストの形式からバイナリ形式に変換されます。その後、プログラムはそのバイナリ形式で配布されますが、ソースコードの形式では配布されません。ユーザーマシンでは、そのバイトコードが新しいエンティティ(仮想マシン)に送られます。仮想マシンは実際にそのバイトコードを解釈します。このため、仮想マシンはバイトコードインタープリターとも呼ばれます。しかし、ここに注意を向けてください!古典的な通訳はテキストインタープリターですが、仮想マシンはバイナリインタープリターです!これは、JavaおよびC#で採用されているアプローチです。

最後に、バイトコードコンパイラにマシンコード生成を追加すると、結果として、従来のコンパイラと呼ばれるものを実現できます。従来のコンパイラは、プログラムのソースコードを特定のプロセッサのマシンコードに変換します。そのマシンコードは、追加の仲介なしに(テキストインタープリターもバイナリインタープリターも、いかなる種類のインタープリターも使用せずに)ターゲットプロセッサで直接実行できます。

では、元の質問に戻り、JavaとPythonについて考えてみましょう。

Javaは当初、実装の依存関係をできるだけ少なくするように設計されました。その設計は、「1回の書き込みでどこでも実行できる」(WORA)という原則に基づいています。これを実装するために、Javaは当初、マシンに依存しないバイナリバイトコードにコンパイルされるプログラミング言語として設計され、再コンパイルすることなく、Javaをサポートするすべてのプラットフォームで実行できます。JavaはWORAベースのC ++と同じように考えることができます。実際、JavaPythonのようなスクリプト言語よりもC ++に近いです。しかし、C ++とは対照的に、JavaC ++はマシンコードでコンパイルされ、ターゲットプロセッサによって直接実行されるように設計されているのに対し、はバイナリバイトコードにコンパイルされて仮想マシンの環境で実行されるように設計されていました。

Pythonは当初、スクリプト(プログラミング言語の規則に従って記述されたテキスト形式のプログラム)を解釈する一種のスクリプトプログラミング言語として設計されました。このため、Pythonは最初、BashまたはWindows CMDと同様に、1行のコマンドまたはステートメントの動的な解釈をサポートしています。同じ理由で、Pythonの初期実装には、そのようなバイトコードを実行するためのバイトコードコンパイラと仮想マシンはありませんでしたが、最初からPythonは、Pythonプログラムテキストを理解および評価できるインタープリタを必要としていました。

このため、歴史的に、のJava開発者は、について話す傾向にあったJava仮想マシン(最初は、のでJavaはのパッケージとして来ているJavaのバイトコードコンパイラとバイトコードインタプリタ - JVM、および)Pythonの開発者が話に傾向があっPythonの最初にあるため(インタープリタPythonが持っています仮想マシンではなく、何らかのコンパイルやバイナリコードの形式への変換を行わずにプログラムテキストを直接実行する、一種の古典的なテキストインタープリターでした。

現在、Pythonには内部に仮想マシンもあり、Pythonバイトコードをコンパイルして解釈できます。そして、その事実は混乱に追加の投資をします。そのプログラムはまったく同じ動作を示し、同じ入力から同じように同じ出力を生成します。観察可能な唯一の違いは、プログラムの実行速度とインタプリタが消費するメモリの量です。したがって、Pythonの仮想マシンは言語設計の不可避の部分ではなく、主要なPythonインタープリターのオプションの拡張機能にすぎません。

Javaも同様に考えることができます。内部のJavaにはJITコンパイラーがあり、Javaクラスのメソッドを選択的にコンパイルしてターゲットプラットフォームのマシンコードにしてから、直接実行できます。だが!Javaは、Javaプログラム実行の主要な方法としてバイトコード解釈を使用しています。内部で仮想マシンを最適化手法としてのみ活用するPython実装と同様に、Java仮想マシンは、最適化の目的でのみJust-In-Timeコンパイラを使用します。同様に、マシンコードの直接実行がJavaバイトコードの解釈よりも少なくとも10倍速いという事実のために。また、Pythonの場合と同様に、JVMのフードの下にあるJITコンパイラの存在は、Java言語設計者とJavaプログラム開発者の両方にとって完全に透過的です。同じJavaプログラミング言語を、JITコンパイラの有無にかかわらず、JVMで実装できます。また、同じ方法で、JITの有無にかかわらず、JVMで同じプログラムを実行できます。同じプログラムは、まったく同じ動作を示し、両方のJVM(JITの有無にかかわらず)で同じ入力から等しく同じ出力を生成します。また、Pythonの場合と同様に、両者の唯一の観察可能な違いは、実行速度とJVMによって消費されるメモリの量です。そして最後に、Pythonの場合と同様に、JavaのJITも言語設計の不可避な部分ではなく、主要なJVM実装のオプションの拡張機能にすぎません。また、同じプログラムはまったく同じ動作を示し、両方のJVM(JITの有無にかかわらず)で同じ入力から同じ出力を生成します。また、Pythonの場合と同様に、両者の唯一の観察可能な違いは、実行速度とJVMによって消費されるメモリの量です。そして最後に、Pythonの場合と同様に、JavaのJITも言語設計の不可避な部分ではなく、主要なJVM実装のオプションの拡張機能にすぎません。また、同じプログラムはまったく同じ動作を示し、両方のJVM(JITの有無にかかわらず)で同じ入力から同じ出力を生成します。また、Pythonの場合と同様に、両者の唯一の観察可能な違いは、実行速度とJVMによって消費されるメモリの量です。そして最後に、Pythonの場合と同様に、JavaのJITも言語設計の不可避な部分ではなく、主要なJVM実装のオプションの拡張機能にすぎません。

JavaとPythonの仮想マシンの設計と実装の観点から見ると、両者は大きく異なります(注意!)どちらも仮想マシンのままです。JVMは、シンプルな基本操作と高い命令ディスパッチコストを備えた低レベルの仮想マシンの例です。一方、Pythonは、命令が複雑な動作を示す高レベルの仮想マシンであり、命令のディスパッチコストはそれほど大きくありません。Javaは非常に低い抽象化レベルで動作します。JVMは、明確に定義された小さなプリミティブ型のセットで動作し、バイトコード命令とネイティブマシンコード命令の間で非常に厳密な対応(通常は1対1)を持っています。逆に、Python仮想マシンは高度な抽象化レベルで動作し、複雑なデータ型(オブジェクト)で動作し、アドホックなポリモーフィズムをサポートします。バイトコード命令は複雑な動作を公開しますが、これは一連の複数のネイティブマシンコード命令で表すことができます。たとえば、Pythonは無限範囲の数学をサポートしています。したがって、Python VMは、演算の結果がマシンワードをオーバーフローする可能性のある大きな整数の可能性がある場合、長い演算を利用することを余儀なくされます。したがって、Pythonの算術演算用の1つのバイトコード命令はPython VM内の関数呼び出しに公開できますが、JVMの算術演算では、1つまたはいくつかのネイティブマシン命令で表される単純な演算に公開されます。したがって、Python VMは、演算の結果がマシンワードをオーバーフローする可能性のある大きな整数の可能性がある場合、長い演算を利用することを余儀なくされます。したがって、Pythonの算術演算用の1つのバイトコード命令はPython VM内の関数呼び出しに公開できますが、JVMの算術演算では、1つまたはいくつかのネイティブマシン命令で表される単純な演算に公開されます。したがって、Python VMは、演算の結果がマシンワードをオーバーフローする可能性のある大きな整数の可能性がある場合、長い演算を利用することを余儀なくされます。したがって、Pythonの算術演算用の1つのバイトコード命令はPython VM内の関数呼び出しに公開できますが、JVMの算術演算では、1つまたはいくつかのネイティブマシン命令で表される単純な演算に公開されます。

その結果、次の結論を導き出すことができます。Java Virtual MachineですがPythonインタープリターは次の理由によります:

  1. 仮想マシンの用語はバイナリバイトコードの解釈を想定していますが、インタープリターの用語はプログラムテキストの解釈を想定しています。
  2. 歴史的に、Javaはバイナリバイトコードの解釈のために設計および実装され、Pythonは当初プログラムテキストの解釈のために設計および実装されました。したがって、「Java仮想マシン」という用語は歴史的なものであり、Javaコミュニティでは十分に確立されています。同様に、「Pythonインタープリター」という用語は歴史的であり、Pythonコミュニティで十分に確立されています。人々は伝統を長くし、ずっと以前に使用されていたのと同じ用語を使用する傾向があります。
  3. 最後に、現在、Javaの場合、バイナリバイトコード解釈はプログラム実行の主要な方法ですが、JITコンパイルはオプションで透過的な最適化にすぎません。Pythonの場合、現在、プログラムテキストの解釈はPythonプログラム実行の主要な方法ですが、Python VMバイトコードへのコンパイルはオプションで透過的な最適化にすぎません。

したがって、JavaとPythonの両方に仮想マシンがあるバイナリバイトコードインタープリターがあるため、「なぜJava仮想マシンなのにPythonインタープリターなのか」などの混乱を招く可能性があります。「ここで重要なのは、Pythonの場合、仮想マシンはプログラム実行の主要な手段または必要な手段ではないことです。これは、従来のテキストインタープリターのオプションの拡張にすぎません。一方、仮想マシンはコアであり、不可避です。 Javaプログラム実行エコシステムの一部です。プログラミング言語設計の静的または動的型選択は、主に仮想マシンの抽象化レベルにのみ影響しますが、仮想マシンが必要かどうかは決定しません。両方の型システムを使用する言語は、コンパイルするように設計できます仮想マシンの環境内で、必要な実行モデルに応じて、解釈、実行されます。


2
これは私見の公式回答として選ばれるべきです。
ラビカンスアンダバラプ

「JavaとPythonの両方に仮想マシンはバイナリバイトコードインタープリターである」から、公式の回答はYESになります。限目。
stuartw


3

Pythonにはx86対応のJITコンパイラがあり、問題をさらに混乱させていることを忘れないでください。(psycoを参照)。

「解釈された言語」のより厳密な解釈は、VMのパフォーマンスの問題を議論する場合にのみ役立ちます。たとえば、Pythonと比較して、RubyはPythonとは異なり、解釈された言語であるため低速であると考えられていました(?)言葉、文脈がすべてです。


1
それは間違っている。まず、「解釈された言語」というものはありません。実装がコンパイラとインタープリタのどちらを使用するかは、言語の特性ではなく、実装の特性です。第二に、13ほどのRuby実装のうち、正確に1はインタープリターであり、他のすべてはコンパイラーを持っています。
イェルクWミッターク

2
第三に、Rubyは遅くありません。速度は言語の特性ではなく、言語の実装であるため、遅い言語はありません。13ほどのRuby実装のうち、一部は7つのPython実装よりも低速で、一部は高速です。
イェルクWミッターク

私は彼がここでヨルクの標準実装を比較していると思います。CPythonとRuby(正式な実装の名前はRubyにすぎないと思います)。
ジェームズマクマホン

Arafangionは「標準」の実装を参照しているかもしれませんが、彼はそのように言うべきでした。私はPythonistaが、私は嫌いどの私は実装の問題についてヨルグに同意するので、フォームの文は、「言語Xが遅いです」。
tzot 2009年

1
これがまさに私が「だった(ある?)」、特に「遅い」という言葉を言った理由です。Ruby自体が遅いとはどこにも言いませんでした。
アラファンギオン2009

2

Pythonは、バイトコードにコンパイルせずにコードを解釈できます。Javaはできません

コンパイルされたものとは対照的に、Pythonはインタープリター型言語ですが、バイトコードコンパイラーが存在するため、区別がぼやけることがあります。これは、実行可能ファイルを明示的に作成せずにソースファイルを直接実行できることを意味します。

(ドキュメントから)。

Javaでは、すべての単一のファイルがなければならないにコンパイルされ.class、その後JVM上で動作するファイル、。それどころか、Pythonはメインスクリプトによってインポートされます。これにより、それらのファイルのその後の使用を高速化できます。

ただし、典型的なケースでは、ほとんどのpython(少なくともCPython)コードはエミュレートされたスタックマシンで実行され、JVMの命令とほぼ同じなので、大きな違いはありません。

ただし、この違いの本当の理由は、最初からjavaが「ポータブルで実行可能なバイトコード」としてブランド化し、pythonがREPLを使用して動的な解釈言語としてブランド化したためです。名入れ!


0

まず第一に、プログラミングやコンピュータサイエンスは一般に数学ではなく、私たちが頻繁に使用するほとんどの用語の厳密な定義がないことを理解する必要があります。

今あなたの質問に:

インタープリターとは(コンピューターサイエンス)

実行可能な最小単位でソースコードを変換し、その単位を実行します。

仮想マシンとは

JVMの場合、仮想マシンはインタープリター、クラスローダー、ガベージコレクター、スレッドスケジューラー、JITコンパイラーなどの多くを含むソフトウェアです。

ご覧のとおり、インタプリタは一部またはJVMであり、JVM全体には他の多くのコンポーネントが含まれているため、インタプリタと呼ぶことはできません。

Pythonについて話すときに「インタプリタ」という単語を使用する理由

Javaでは、コンパイル部分は明示的です。一方、pythonは、コンパイルと解釈のプロセスについてjavaとして明示されていません。エンドユーザーの観点から見ると、pythonプログラムの実行に使用されるメカニズムは解釈のみです。


0

いいえ、どちらもバイトコードを解釈しません。

Pythonは、pypyで実行している場合にのみバイトコードを解釈します。それ以外の場合は、Cにコンパイルされ、そのレベルで解釈されます。

Javaはバイトコードにコンパイルされます。


回答にリソースを提供できますか?
Isuru Dilshan


これがスタックオーバーフローの問題です。誰かが呼び出され、反対票でそれを表現しているので、誰かがおかしくなっています。
マイケルタミロー

0

私は両方の間の境界線がぼやけていると思います、人々は主に「インタプリタ」という言葉の意味と言語が「インタプリタ...コンパイラ」スペクトルの両側にどれだけ近いかについて議論します。しかし、どれも100%にはなりません。私は、あらゆる価値のあるJavaまたはPythonの実装を書くのは簡単だと思います。

現在、JavaとPythonの両方に仮想マシンとバイトコードがありますが、1つは(32ビット整数のような)具体的な値のサイズで動作し、もう1つは各呼び出しのサイズを決定する必要があります。これは、私の意見では用語間の境界を定義していません。

Pythonが正式に定義されたバイトコードを持たず、それがメモリにのみ存在するという主張も私を納得させません。それは、Pythonバイトコードのみを認識し、コンパイル部分がブラウザーのJSマシンで実行されるデバイスを開発する予定だからです。

パフォーマンスは、具体的な実装のみに関するものです。オブジェクトを操作するためにオブジェクトのサイズを知る必要はありません。最後に、ほとんどの場合、基本的な型ではなく構造体を操作します。既存のオブジェクトを再利用することで、式の計算中に毎回新しいオブジェクトを作成する必要がなくなるように、Python VMを最適化することができます。これが完了すると、Javaが優れている2つの整数の合計の計算にグローバルなパフォーマンスの違いはありません。

この2つの間に大きな違いはありません。エンドユーザーに関係のないいくつかの実装のニュアンスと最適化の欠如だけであり、おそらくパフォーマンスの遅れに気づき始めた時点でおそらくアーキテクチャの問題ではなく実装です。


0

Pythonがバイトコードを生成する必要がないことを言及している投稿の場合、私はそれが本当かどうか確信がありません。Pythonのすべての呼び出し可能オブジェクトに.__code__.co_codeは、バイトコードを含む属性が必要です。コンパイルされたアーティファクトが保存されない可能性があるという理由だけでpythonを「コンパイルされていない」と呼ぶ意味のある理由はわかりません。そして多くの場合、Pythonの設計では保存されません。たとえば、すべての内包表記は入​​力用に新しいバイトコードをコンパイルします。これが、内包表記変数のスコープがcompile(mode='exec, ...)との間で一貫していない理由です。compile(mode='single', ...)たとえば、Pythonスクリプトの実行とpdbの使用の間で

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.