Sunの標準的なJVM実装は、かなり洗練された最適化をバイトコードに適用して、コードが数回実行された後、ネイティブに近い実行速度を取得します。
問題は、このコンパイルされたコードが、同じ関数/クラスの後続の使用中に使用するためにディスクにキャッシュされないのはなぜですか?
現状では、プログラムが実行されるたびに、JITコンパイラーは、コンパイル済みのバージョンのコードを使用するのではなく、新たに起動します。この機能を追加すると、バイトコードが本質的に解釈されているときに、プログラムの初期実行時間が大幅に向上しませんか?
@MYYNが投稿したリンクのカットアンドペーストに頼らずに、JVMが実行する最適化は静的ではなく動的であり、データパターンとコードパターンに基づいているためです。これらのデータパターンはアプリケーションの存続期間中に変更され、キャッシュされた最適化が最適ではなくなる可能性があります。
そのため、保存された最適化がまだ最適であるかどうかを確認するメカニズムが必要です。
OracleのJVM は確かにそのように文書化されています-Oracleを引用して、
コンパイラーは、Oracle JVMのクラス解決モデルを利用して、オプションでコンパイルされたJavaメソッドをデータベース呼び出し、セッション、またはインスタンスにわたって永続化します。このような永続性により、意味的にJavaコードは変更されていません。
洗練されたすべてのVM実装が同様のオプションを提供しない理由はわかりません。
既存の回答の更新-Java 8には、これを解決するためのJEPがあります。
=> JEP 145:コンパイルされたコードのキャッシュ。 新しいリンク 。
非常に高いレベルでは、その表明された目標は:
大規模なJavaアプリケーションの起動時間を改善するために、以前の実行からコンパイルされたネイティブコードを保存して再利用します。
お役に立てれば。
Excelsior JETには、2001年にリリースされたバージョン2.0以降のキャッシュJITコンパイラがあります。さらに、AOTコンパイラはキャッシュを再コンパイルする場合がありますすべての最適化を使用して単一のDLL /共有オブジェクトに。
実際の理由はわかりませんが、JVM実装に関与しているわけではありませんが、いくつか考えられる理由を考えることができます。
しかし、私は本当に推測しています、そしてご覧のとおり、私の理由のどれも実際のショーストッパーであるとは本当に思っていません。私はSunがこのサポートを優先事項として考慮していないと考えています。おそらく私の最初の理由は真実に近いでしょう。これを習慣的に行うと、人々がJavaクラスファイルには本当に必要であるクロスプラットフォームではなく、VMごとに個別のバージョン.
私の優先する方法は、実際に前もってこのようなことを明示的に行うために使用できる個別のバイトコードからネイティブへのトランスレータを持ち、特定のVM用に明示的に構築されたクラスファイルを作成することです。異なるVMでも実行できます。しかし、それはおそらく私の経験によるものです。私は主にJava MEを行っています。ここで、Javaコンパイラはコンパイルについて賢くありません。