web-dev-qa-db-ja.com

Javaコンパイルはどのように行われますか?

Javaコンパイルプロセスに混乱

わかりました。これは知っています:Javaソースコードを書き、プラットフォームに依存しないコンパイラがそれをバイトコードに変換し、プラットフォームに依存するjvmがそれをマシンコードに変換します。

そのため、最初からJavaソースコードを記述します。コンパイラjavac.exeは.exeファイルです。この.exeファイルとは正確には何ですか? JavaコンパイラはJavaで書かれていないのですが、どうしてそれを実行する.exeファイルがありますか?コンパイラコードがJavaで記述されている場合、jvmがJavaコードを実行するため、コンパイラコードはコンパイル段階で実行されます。言語自体はどのようにして独自の言語コードをコンパイルできますか?それはすべて私にとって鶏と卵の問題のように思えます。

.classファイルには正確に何が含まれていますか?テキスト形式の抽象構文ツリーですか、表形式の情報ですか?

Javaソースコードがマシンコードでどのように変換されるかについて、誰もが明確で詳細な方法を教えてくれますか。

58
nash

わかりました。これはわかっています:Javaソースコードを記述します。プラットフォームに依存しないコンパイラがそれをバイトコードに変換し、

実際には、コンパイラ自体worksネイティブ実行可能ファイル(したがってjavac.exe)として。そして実際、ソースファイルをバイトコードに変換します。バイトコードは、Java仮想マシンを対象としているため、プラットフォームに依存しません。

プラットフォームに依存するjvmは、それをマシンコードに変換します。

常にではない。 SunのJVMについては、クライアントとサーバーの2つのjvmがあります。どちらもネイティブコードにコンパイルできますが、必ずコンパイルする必要はありません。

そのため、最初からJavaソースコードを記述します。コンパイラjavac.exeは.exeファイルです。この.exeファイルとは正確には何ですか? JavaコンパイラはJavaで書かれていないのに、どうしてそれを実行する.exeファイルがありますか?

このexeファイルは、ラップされたJavaバイトコードです。複雑なバッチスクリプトを避けるためです。 JVMを起動し、コンパイラーを実行します。

コンパイラコードがJavaで記述されている場合、jvmがJavaコードを実行するため、コンパイラコードはコンパイル段階で実行されます。

それがまさにラッピングコードの機能です。

言語自体はどのようにして独自の言語コードをコンパイルできますか?それはすべて私にとって鶏と卵の問題のようです。

確かに、一見混乱します。ただし、それはJavaのイディオムだけではありません。 AdaのコンパイラもAda自体で記述されています。 「鶏と卵の問題」のように見えるかもしれませんが、実際にはブートストラップの問題にすぎません。

.classファイルには正確に何が含まれていますか?テキスト形式の抽象的な構文ツリーですか、表形式の情報ですか?

抽象構文ツリーではありません。 ASTは、メモリ内のコードを表すために、コンパイル時にトークナイザーとコンパイラーによってのみ使用されます。 .classファイルはアセンブリに似ていますが、JVM用です。 JVMは、仮想マシンのみを対象とする特殊なマシン言語を実行できる抽象マシンです。最も簡単なのは、.classファイルの構造が通常のアセンブリと非常に似ていることです。最初にすべての静的変数が宣言され、その後、外部関数のシグネチャと最後にマシンコードの表がいくつかあります。

本当に興味があれば、「javap」ユーティリティを使用してクラスファイルを掘り下げることができます。 javap -c Main呼び出しのサンプル(難読化された)出力を次に示します。

0:   new #2; //class SomeObject
3:   dup
4:   invokespecial   #3; //Method SomeObject."<init>":()V
7:   astore_1
8:   aload_1
9:   invokevirtual   #4; //Method SomeObject.doSomething:()V
12:  return

それで、あなたはすでにそれが本当に何であるかを考えているはずです。

Javaソースコードがマシンコードでどのように変換されるかについて、誰もが明確で詳細な方法を教えてくれますか。

今はもっと明確にすべきだと思いますが、簡単な要約を以下に示します。

  • ソースコードファイルを指すjavacを呼び出します。 javacの内部リーダー(またはトークナイザー)はファイルを読み取り、そこから実際のASTを構築します。すべての構文エラーはこの段階で発生します。

  • javacはまだ仕事を終えていません。 ASTがある場合、真のコンパイルを開始できます。ビジターパターンを使用してASTをトラバースし、外部依存関係を解決してコードに意味(セマンティクス)を追加します。完成した製品は、バイトコードを含む.classファイルとして保存されます。

  • さあ、物事を実行します。 .classファイルの名前でJavaを呼び出します。これでJVMが再び起動しますが、解釈になります。 JVMは、抽象バイトコードをネイティブアセンブリにコンパイルする場合としない場合があります。 SunのHotSpotコンパイラは、必要に応じてJust In Timeコンパイルと連動します。実行中のコードはJVMによって常にプロファイリングされ、特定のルールが満たされるとネイティブコードに再コンパイルされます。最も一般的には、hotコードが最初にネイティブにコンパイルされます。

編集:javacなしでは、次のようなものを使用してコンパイラを起動する必要があります。

%JDK_HOME%/bin/Java.exe -cp:myclasspath com.Sun.tools.javac.Main fileToCompile

ご覧のとおり、SunのプライベートAPIを呼び出しているため、Sun JDK実装にバインドされています。それはビルドシステムをそれに依存させるでしょう。他のJDKに切り替えた場合(ウィキリスト5はSun以外)、変更を反映するために上記のコードを更新する必要があります(コンパイラがcom.Sun.tools.javacパッケージに存在する可能性は低いため)。他のコンパイラは、ネイティブコードで記述できます。

したがって、標準的な方法は、javacラッパーをJDKに同梱することです。

59
Rekin

JavaコンパイラはJavaで書かれていませんが、それを実行する.exeファイルがあるのはなぜですか?

この情報はどこから入手しますか? javac実行可能ファイルは、任意のプログラミング言語で作成できますが、無関係です。重要なのは、.Javaファイルを.classファイル。

.classファイルのバイナリ仕様の詳細については、 Java言語仕様 でこれらの章を見つけることができます(多少技術的かもしれませんが):

仮想マシン仕様 もご覧ください。

16
matt b

コンパイラjavac.exeは.exeファイルです。この.exeファイルとは正確には何ですか? JavaコンパイラはJavaで書かれていませんが、それを実行する.exeファイルがあるのはなぜですか?

Javaコンパイラ(少なくともSun/Oracle JDKに付属しているもの)は、実際にJavaで書かれています。javac.exeは、コマンドライン引数を処理する単なるランチャーであり、その一部はコンパイラーを実行するJVMに渡され、その他はコンパイラー自体に渡されます。

コンパイラコードがJavaで記述されている場合、jvmがJavaコードを実行する。言語コード?それはすべて私にとって鶏と卵の問題のようです。

多くの(ほとんどではないにしても)コンパイラーは、コンパイルする言語で書かれています。明らかに、初期段階では、コンパイラ自体を別の何かでコンパイルする必要がありましたが、その「ブートストラップ」の後、コンパイラの新しいバージョンは古いバージョンでコンパイルできます。

.classファイルには正確に何が含まれていますか?テキスト形式の抽象的な構文ツリーですか、表形式の情報ですか?

クラスファイル形式の詳細は、 Java仮想マシン仕様 で説明されています。

11

まあ、javacとjvmは通常、ネイティブバイナリです。それらはCで書かれています。 Javaでそれらを書くことは確かに可能ですが、最初に必要なのはネイティブバージョンだけです。これは「ブートストラップ」と呼ばれます。

楽しい事実:ネイティブコードにコンパイルするほとんどのコンパイラは、独自の言語で書かれています。ただし、最初に別の言語(通常はC)で記述されたネイティブバージョンを用意する必要がありました。これに対して、最初のCコンパイラはアセンブラーで作成されました。最初のアセンブラはマシンコードで書かれていると思います。 (または、 蝶を使用 ;)

.classファイルは、javacによって生成されたバイトコードです。テキストではなく、マシンコードに似たバイナリコードです(ただし、異なる命令セットとアーキテクチャを使用)。

Jvmには、実行時に2つのオプションがあります。バイトコードを解釈する(CPUそのものを装う)か、JIT(ジャストインタイム)でネイティブマシンコードにコンパイルできます。後者はもちろん高速ですが、より複雑です。

5
Mike Caron

.classファイルには、非常に 高レベルアセンブリ のようなsort ofであるバイトコードが含まれています。コンパイラはJavaで非常にうまく作成できますが、鶏肉/卵の問題を回避するには、JVMをネイティブコードにコンパイルする必要があります。標準ライブラリの下位レベルと同様に、Cで書かれていると思います。 JVMを実行すると、ジャストインタイムコンパイルが実行され、そのバイトコードがネイティブ命令に変換されます。

3
ZoFreX

簡単な説明

テキストエディタでコードを記述し、コンパイラが理解できる形式で保存します- "。Java"ファイル拡張子、javac(Javaコンパイラ)これを "。class"形式ファイル(バイトコード-クラスファイル)に変換します。 JVMは、それが存在するオペレーティングシステムで.classファイルを実行します。

長い説明

Javaはオペレーティングシステムが認識するベース言語ではありません。JavaソースコードはJava Virtual Machine(JVM)。JVMは、エディターで記述するコードを理解できないため、コンパイルされたコードが必要です。

すべてのコンピュータープロセスは、メモリ操作にふける。テキストエディタでコードを記述してコンパイルすることはできません。コンピューターのメモリに保存する必要があります。つまり、コンパイルする前に保存します。

保存されたテキストをjavac(Javaコンパイラ)がどのようにコンパイルするものとして認識するのか?-コンパイラが認識する別のテキスト形式、つまり.Java。ファイルを.Java拡張子で保存すると、コンパイラはそれを認識し、要求されたらコンパイルします。

コンパイル中はどうなりますか? -コンパイラは、プロセスに関係する2番目の翻訳者(専門用語ではない)で、ユーザーが理解できる言語(Java)をJVMが理解できる言語(バイトコード-.class形式)に変換します。

コンパイル後はどうなりますか? -コンパイラーは、JVMが理解できる.classファイルを生成します。その後、プログラムが実行されます。つまり、オペレーティングシステム上のJVMによって.classファイルが実行されます。

知っておくべき事実

1)Javaではなくmulti-platformplatform independent

2)JVMはC/C++を使用して開発されています。人々がJava C/C++よりも遅い言語を呼び出す理由の1つ

3)Javaバイトコード(.class)は "アセンブリ言語"、JVMが理解できる唯一の言語です。classを生成するコードコンパイル時のファイルまたは生成されたバイトコードは、JVMで実行できます。

2

WindowsはJavaランタイムをインストールする前にJavaプログラムを呼び出す方法を知らず、Sunはjar-suffixをバインドする代わりに引数を収集してJVMを呼び出すネイティブコマンドを選択しましたJavaエンジンに。