117

Sun の正規の JVM 実装では、かなり高度な最適化がバイトコードに適用され、コードが数回実行された後にネイティブに近い実行速度が得られます。

問題は、このコンパイルされたコードが、同じ関数/クラスを後で使用するときに使用するためにディスクにキャッシュされないのはなぜですか?

現状では、プログラムが実行されるたびに、JIT コンパイラーはコンパイル済みのバージョンのコードを使用するのではなく、新たに起動します。この機能を追加すると、バイトコードが本質的に解釈されているときに、プログラムの初期実行時間が大幅に短縮されるのではないでしょうか?

4

5 に答える 5

31

@MYYN が投稿したリンクの切り貼りに頼ることなく、これは、JVM が実行する最適化が静的ではなく、コード パターンと同様にデータ パターンに基づいて動的であるためだと思われます。これらのデータ パターンは、アプリケーションの有効期間中に変更され、キャッシュされた最適化が最適でなくなる可能性があります。

したがって、保存された最適化がまだ最適であったかどうかを確認するメカニズムが必要です。

于 2010-01-02T19:18:54.533 に答える
31

Oracle の JVMは実際にそうするように文書化されています -- Oracle を引用して、

コンパイラは、Oracle JVM のクラス解決モデルを利用して、オプションでコンパイル済みの Java メソッドをデータベース呼び出し、セッション、またはインスタンス間で永続化できます。Java コードが意味的に変更されていないことがわかっている場合、このような永続性により、セッションまたはインスタンス間での不要な再コンパイルのオーバーヘッドが回避されます。

すべての洗練された VM 実装が同様のオプションを提供しない理由はわかりません。

于 2010-01-02T19:14:06.323 に答える
19

既存の回答の更新 - Java 8 には、これを解決する専用の JEP があります。

=> JEP 145: コンパイル済みコードのキャッシュ. 新しいリンク

非常に高いレベルで、その目標は次のとおりです。

大規模な Java アプリケーションの起動時間を改善するために、以前の実行からコンパイルされたネイティブ コードを保存して再利用します。

お役に立てれば。

于 2013-12-31T14:55:45.967 に答える
8

Excelsior JETには、2001 年にリリースされたバージョン 2.0 以降のキャッシュ JIT コンパイラがあります。さらに、その AOT コンパイラは、すべての最適化を使用してキャッシュを単一の DLL/共有オブジェクトに再コンパイルする場合があります。

于 2010-01-21T06:04:09.763 に答える
1

JVMの実装にはまったく関与していないため、実際の理由はわかりませんが、いくつかのもっともらしい理由を考えることができます。

  • Java の考え方は、write-once-run-anywhere 言語であることであり、プリコンパイルされたものをクラス ファイルに入れることは、一種の違反です (もちろん、実際のバイト コードはまだそこにあるため、"ある種" にすぎません)。
  • 同じコードが複数回存在するため、クラス ファイルのサイズが大きくなります。特に、複数の異なる JVM で同じプログラムを実行する場合 (異なるバージョンが異なる JVM であると考えると、これは珍しいことではありません)。本当にしなければならない)
  • クラスファイル自体は書き込み可能ではない可能性があります(ただし、それを確認するのは非常に簡単です)
  • JVM の最適化は部分的に実行時の情報に基づいており、他の実行では適用できない場合があります (ただし、いくつかの利点はあるはずです)。

しかし、私は本当に推測していて、ご覧のとおり、私の理由のどれも実際のショーストッパーではないと思います. Sun はこのサポートを優先事項とは考えていないだけだと思います。私の最初の理由は真実に近いかもしれません。クロスプラットフォーム。

私の好みの方法は、実際には、このようなことを事前に明示的に行うために使用できる別のバイトコードからネイティブへのトランスレーターを用意し、特定の VM 用に明示的にビルドされたクラス ファイルを作成し、おそらく元のバイトコードを含めて、異なる VM でも実行できます。しかし、それはおそらく私の経験から来ています.

于 2010-01-02T19:22:14.760 に答える