web-dev-qa-db-ja.com

JVMがJITコンパイル済みコードをキャッシュしないのはなぜですか?

Sunの標準的なJVM実装は、かなり洗練された最適化をバイトコードに適用して、コードが数回実行された後、ネイティブに近い実行速度を取得します。

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

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

106
Chinmay Kanchi

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

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

25
skaffman

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

コンパイラーは、Oracle JVMのクラス解決モデルを利用して、オプションでコンパイルされたJavaメソッドをデータベース呼び出し、セッション、またはインスタンスにわたって永続化します。このような永続性により、意味的にJavaコードは変更されていません。

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

25
Alex Martelli

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

=> JEP 145:コンパイルされたコードのキャッシュ新しいリンク

非常に高いレベルでは、その表明された目標は

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

お役に立てれば。

14
Eugen

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

5
Dmitry Leskov

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

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

しかし、私は本当に推測しています、そしてご覧のとおり、私の理由のどれも実際のショーストッパーであるとは本当に思っていません。私はSunがこのサポートを優先事項として考慮していないと考えています。おそらく私の最初の理由は真実に近いでしょう。これを習慣的に行うと、人々がJavaクラスファイルには本当に必要であるクロスプラットフォームではなく、VMごとに個別のバージョン.

私の優先する方法は、実際に前もってこのようなことを明示的に行うために使用できる個別のバイトコードからネイティブへのトランスレータを持ち、特定のVM用に明示的に構築されたクラスファイルを作成することです。異なるVMでも実行できます。しかし、それはおそらく私の経験によるものです。私は主にJava MEを行っています。ここで、Javaコンパイラはコンパイルについて賢くありません。

0
JaakkoK