(最初に、コンパイラと仮想マシン(別名)は私にとってまったく未知のフィールドであることを明確にする必要があります)
私が理解しているように、Java / C#/ ...アプリケーションが実行されるたびにVMが呼び出され、中間コード(バイトコード、CILなど)を機械語命令に変換します。
しかし、なぜこの操作を一度だけしか実行できないのですか?
(最初に、コンパイラと仮想マシン(別名)は私にとってまったく未知のフィールドであることを明確にする必要があります)
私が理解しているように、Java / C#/ ...アプリケーションが実行されるたびにVMが呼び出され、中間コード(バイトコード、CILなど)を機械語命令に変換します。
しかし、なぜこの操作を一度だけしか実行できないのですか?
回答:
Javaの場合、JVMはライブラリの境界を越える最適化を実行できます。たとえば、ライブラリのメソッドを独自のクライアントコードにインライン化できます。ライブラリは実行前に変更される可能性があるため、このタイプの最適化はコンパイル時には実行できませんでした。再コンパイルせずにlibfoo-1.0をlibfoo-1.1に置き換えることは完全に可能です。その場合、コンパイル時に行われるライブラリ間のインラインは完全に無効になります。
実行時にのみ最適化を実行することにより、ライブラリの変更により最適化が無効になる心配はありません。
これにより、多くの機能を使用できなくなります。たとえば、JITは実行時にロードされたDLLから新しいジェネリックインスタンスをどのように生成できますか?これらのDLLはインストール時には存在しません。
これは、少なくとも.NETアプリケーションでは可能です。ネイティブイメージジェネレーターを参照
管理対象アプリケーションのパフォーマンスを向上させるツール。Ngen.exeは、コンパイルされたプロセッサ固有のマシンコードを含むファイルであるネイティブイメージを作成し、ローカルコンピューターのネイティブイメージキャッシュにインストールします。ランタイムは、ジャストインタイム(JIT)コンパイラーを使用して元のアセンブリをコンパイルする代わりに、キャッシュからネイティブイメージを使用できます...
説明に従って質問を言い換えると、次のようになります。
プログラムを初めて実行したときに、バイトコードをネイティブコードにコンパイルできないのはなぜですか。
次の問題が発生します。
結果はどこに保存されますか?バイトコードを含むファイルが書き込み可能であるとは限りません。開発者がテストを実行するたびに新しい.exeを永続ストレージにダンプすることによって、開発者のマシンを膨らませたくありません。また、ファイルを一時ストレージに保存すると、次回の再起動時にファイルが失われるため、それほど多くは得られません。
毎回わずかに遅いスタートアップを、非常に遅いスタートアップに交換します。クライアントに大きな印象を残さない。
動的クラスローディングで重大な問題が発生します。