Javaでは、「バイナリコード」は「Javaバイトコード」と同じ意味ですか?
これはJavaのフローですか?
Javaファイル(.Java)-> [javac]-> ByteCodeファイル(.class)-> [JVM/Javaインタープリター]->実行(最初にマシン固有のバイナリコードに変換する)
ありがとう!
答えはあなたが何を意味するかによりますbinary code
。
Java bytecode
は、Java仮想マシンのロード情報と実行命令を含むバイナリデータ形式です。その意味で、Java bytecode
は特別な種類のバイナリコードです。
「バイナリコード」という用語を実際のプロセッサアーキテクチャ(IA-32やSparcなど)のマシン命令を意味するために使用する場合、それは異なります。Java bytecode
はその意味でバイナリコードではありません。プロセッサ固有ではありません。
JVMは非常に複雑なプログラムであり、そこにあるフローは特定のレベルでは予測できません。例えば。 HotSpotJVM内のフローは次のようなものです。
1)バイトコードを取得して解釈します
2)あるメソッドが非常に頻繁に(ある期間中に何度も)実行される場合、それは「ホット」メソッドとしてマークされ、JVMはプラットフォームに依存するマシンコードへのコンパイルをスケジュールします(これはあなたが呼んだものです)バイナリコード?)。そのフローは次のようになります。
ByteCode
--> Hige-level Intermediate Representation (HIR)
--> Middle-level Intermediate Representation (MIR)
--> Low-level Intermediate Representation (LIR)
--> Register Allocation
--> EMIT (platform dependent machine code)
そのフローの各ステップは重要であり、JVMがコードの最適化を実行するのに役立ちます。もちろん、アルゴリズムは変更されません。最適化とは、コードの一部のシーケンスを検出して、パフォーマンスの高いコードと交換できることを意味します(同じ結果が得られます)。 LIRステージから、コードはプラットフォームに依存するようになります(!)。
バイトコードは解釈には適していますが、マシンのネイティブコードに簡単に変換するには不十分です。 HIRがそれを処理し、その目的はバイトコードを中間表現にすばやく変換することです。 MIRは、すべての操作を3オペランド操作に変換します。 ByteCodeはスタック操作に基づいています。
iload_0
iload_1
iand
これは単純なand
操作のバイトコードであり、これの中間レベルの表現は次のようなものになります。
and v0 v1 -> v2
LIRはプラットフォームに依存し、and
操作の簡単な例を考慮し、プラットフォームをx86として指定すると、コードスニペットは次のようになります。
x86_and v1 v0 -> v1
x86_move v1 -> v2
and
演算は2つのオペランドを取ります。最初のオペランドは宛先、もう1つはソースであり、次に結果値を別の「変数」に入れます。次の段階は「レジスタ割り当て」です。x86プラットフォーム(およびおそらく他のほとんどのプラットフォーム)は、変数(中間表現など)やスタック(バイトコードなど)ではなく、レジスタを処理するためです。ここで、コードスニペットは次のようになります。
x86_and eax ecx -> eax
ここで、「移動」操作がないことに気付くことができます。コードには1行しか含まれていなかったため、JVMは新しい仮想変数を作成する必要がないことを理解しました。 eax
レジスタを再利用できます。コードが十分に大きく、多くの変数があり、それらを集中的に操作する場合(たとえば、下のどこかでeaxを使用しているため、その値を変更できない場合)、マシンコードに移動操作が残っていることがわかります。それは再び最適化についてです:)
これはJITフローでしたが、VMの実装によっては、もう1つのステップがあります。コードがコンパイルされ(「ホット」である)、それでも何度も実行される場合、JVMはそのコードの最適化をスケジュールします。 (例:インライン化を使用)。
結論として、バイトコードからマシンコードへのパスは非常に興味深く、少し予測不可能であり、多くのことに依存しています。
ところで、上記のプロセスは「混合モード解釈」と呼ばれ(JVMが最初にバイトコードを解釈し、次にJITコンパイルを使用する場合)、そのようなJVMの例はHotSpotです。一部のJVM(OracleのJRockitなど)は、JITコンパイルのみを使用します。
これはそこで起こっていることの非常に簡単な説明でした。 JVM内のフローを非常に高いレベルで理解し、バイトコードとバイナリコードの違いに関する質問を対象にするのに役立つことを願っています。参考資料、およびここに記載されておらず、そのトピックに関連するその他の問題については、同様のトピックをお読みください " なぜコンパイルされるJava Cコンパイル済みファイルよりも小さいクラスファイル? " 。
また、この答えを自由に批評し、私の間違いや誤解を指摘してください。私は常にJVMに関する知識を向上させたいと思っています:)
「machine-independent-bytecode」のようなものはありません(考えてみれば意味がありません)。バイトコードは(この回答の目的で)仮想マシンなどにのみ使用されます。 VM(JVMなど)[〜#〜] interpret [〜#〜]バイトコードを使用し、巧妙で複雑なジャストインタイムコンパイルを使用します([〜#〜] is [〜#〜]マシン/プラットフォームに依存)最終製品を提供します。
したがって、ある意味では、両方の答えが正しいことと間違っていることです。 Javaコンパイラは、コードをJavaバイトコード(マシンに依存しない)にコンパイルします。*.class
バイトコードが配置されているファイルはバイナリです-結局のところ、それらは実行可能です。仮想マシンは後でこれらのバイナリを解釈します*.class
ファイル(注:ファイルをバイナリとして説明する場合、それは多少誤解されます)、さまざまな素晴らしいことを行います。多くの場合、JVMはJIT(ジャストインタイムコンパイル)と呼ばれるものを使用します。これは、実行のさまざまな部分を高速化するプラットフォーム固有またはマシン固有の命令を生成します。ただし、JITは別の日の別のトピックです。
編集:
Java File (.Java) -> [javac.exe] -> ByteCode File (.class) -> [JVM/Java Interpreter] -> Running it(by first converting it into binary code specific to the machine)
これは正しくありません。 JVMは何も「変換」しません。バイトコードを解釈するだけです。バイトコードを「変換」するJVMの唯一の部分は、JITコンパイラが呼び出されたときです。これは特殊なケースであり、一般化するべきではありません。
C/C++(例として)とJavaプログラムの両方がバイナリコードにコンパイルされます。この一般的な用語は、新しく作成されたファイルが人間が読める方法で命令をエンコードしないことを意味します(つまり、コンパイルされたファイルをテキストプログラムで開いて読み取ることはできません)。
一方、バイナリ0と1がエンコード(または表現)するものは、コンパイラが生成したものによって異なります。 Javaの場合、JVMによって解釈されるBytecodeという命令が生成されます。その他の場合、他の言語の場合、IA-32またはSPARC命令を生成することがあります。
結論として、用語バイナリコードおよびJavaバイトコード互いに反対しているのは誤解を招く恐れがあります。その理由は、マシンに依存する通常のバイナリコードと、そうでないJavaバイトコード(これもバイナリコード)を区別するためです。
上記の質問に対して今日見つけた回答:
ソース: [〜#〜] jls [〜#〜]
ロードとは、特定の名前を持つクラスまたはインターフェイスタイプのバイナリ形式を見つけるプロセスを指します。おそらくその場で計算しますが、より一般的には、以前にソースコードからJavaコンパイラ、およびそのバイナリ形式から、クラスまたはインターフェイスを表すClassオブジェクトを構築します。
ロードの正確なセマンティクスは、Java仮想マシン仕様、Java SE 7 Editionの第5章に記載されています。ここでは、プロセスの概要を示します。 Javaプログラミング言語の視点。
クラスまたはインターフェイスのバイナリ形式は通常、Java仮想マシン仕様、= Java SE 7 Editionは上記で引用しましたが、§13.1で指定された要件を満たしていれば、他の形式も可能です。クラスClassLoaderのメソッドdefineClassを使用して、クラスのバイナリ表現からClassオブジェクトを構築できますファイル形式。
話がプログラムについて起こっているとき、用語バイナリコードは通常、バイナリ形式(ビットのシーケンスとしてエンコードされた)の実行可能プログラムを示します。言い換えれば、バイナリコードは任意のコンパイルされたプログラムであり、テキストの形式で配布および実行(解釈)されるスクリプトとは対照的です。
バイナリコードマシンコードとバイトコードの2種類があります。 マシンコードは、実際のハードウェアマイクロプロセッサの仕様に従ってエンコードされたプログラムです。したがって、他のソフトウェアを介さずに、ターゲットのマイクロプロセッサで直接実行できます。対照的に、bytecodeは、一部の仮想マイクロプロセッサ(仮想マシン)の仕様に従ってエンコードされたプログラムです。したがって、実行のために、それを解釈するか、マシンコードに変換してから直接実行することができます。
このように、すべてのバイトコードはバイナリコードですが、すべてのバイナリコードがバイトコードであるとは限りません。あなたの質問の文脈では、「Javaバイトコード」は無条件に「バイナリコード」ですが、「バイナリコード」は「Javaバイトコード」である必要はなく、「Javaバイトコード」である可能性があります。