web-dev-qa-db-ja.com

Java AOTコンパイラはどのように機能しますか?

いくつかのツール( Excelsior JET など)があり、Javaアプリをネイティブ実行可能ファイル(*.exe)。ただし、これらのツールが実際にシェルまたはコマンドラインからJavaを呼び出し/実行するネイティブラッパーを作成しているだけである理解です。

その理解が正しくない場合、私はそれがどのようになり得るのかわかりません。実行中のJVM(Javaプロセス)が本質的に高性能インタープリターであり、Javaクラスファイルをその場で)からバイトコードをロードする場合、Javaアプリ(JVMへの入力として機能するバイトコードファイルのコレクション)は、実際に実行可能ファイルに変換できます。

これは、JVMプロセスがバイトコードファイルのセットを入力として受け取るネイティブ実行可能ファイルがすでにであるためです。これらのバイトコードファイルとJVMプロセスを単一の統合されたネイティブ実行可能ファイルにマージすることは、JVMを完全に書き直し、JVM仕様から脱線しない限り、不可能に思えます。

だから私は尋ねます:これらのツールはどうやって実際に「変換」Javaクラスファイルをネイティブ実行可能ファイルに変換するか、またはそれらを実行します?

19
smeeb

すべてのプログラムにはランタイム環境があります。私たちはこれを忘れがちですが、そこにあります。オペレーティングシステムへのシステムコールをラップするCの標準lib。 Objective-Cには、メッセージパッシングのすべてをラップするランタイムがあります。

Javaでは、ランタイムはJVMです。よく知られているJava実装のほとんどは、バイトコードインタープリタおよびJITコンパイラであるHotSpot JVMに似ています。

これが唯一の実装である必要はありません。 Javaの標準のlib-esqueランタイムをビルドして、コードをネイティブマシンコードにコンパイルし、新しいオブジェクトの呼び出しをmallocsに処理するランタイム内で実行できないということは絶対にありません。マシンのシステムコールへのファイルアクセス。これが、Ahead Of Time(JITではなくAOT)コンパイラーが行うことです。そのランタイムを何と呼びますか。JVM実装と呼ぶことができますdoesは、JVM仕様に準拠します)、Javaのランタイム環境または標準libですが、基本的に同じことを行います。

これは、javacを再実装してネイティブマシンをターゲットにすることで行うことができます(これは [〜#〜] gcj [〜#〜] が行ったことの一種です)。または、javacによって生成されたバイトコードを別のマシンのマシン(またはバイト)コードに変換することで実行できます。これは、Androidが行うことです。---に基づく Wikipedia それはExcelsior JETも同じことです( "コンパイラはポータブルJavaバイトコードを目的のハードウェアとオペレーティングシステム(OS)に最適化された実行可能ファイルに変換します")。そして同じことが当てはまります。 RoboVM

Javaを使用すると、さらに複雑になります。つまり、これはveryを排他的なアプローチとして実行するのが難しいことを意味します。クラスの動的ロード(class.forName())または プロキシオブジェクト AOTコンパイラが簡単に提供できないダイナミクスを必要とするため、それぞれのJVMにはJITコンパイラ(Excelsior JET)またはインタープリタ(GCJ)も含める必要がありますネイティブにプリコンパイルできなかったクラスを処理するため。

JVMは仕様です多くの実装 を思い出してください。 C標準ライブラリは これも仕様 であり、さまざまな実装があります。

Java8では、AOTコンパイルに関してかなりの作業が行われています。せいぜい、一般的に、テキストボックスの範囲内でのみAOTを要約できます。ただし、2015年のJVM言語サミット(2015年8月)では、プレゼンテーション Java Goes AOT (youtubeビデオ)がありました。このビデオは40分で、より深い技術的側面とパフォーマンスベンチマークの多くを取り上げています。

27
user40980