アプリケーション仮想化ソフトウェアとは、アプリケーション仮想マシンと、それらを実装するソフトウェアの両方を指します。アプリケーション仮想マシンは通常、アプリケーションのバイトコードを様々なコンピュータアーキテクチャやオペレーティングシステム上で移植可能にするために使用されます。アプリケーションは通常、インタプリタまたはジャストインタイムコンパイル(JIT)を使用してコンピュータ上で実行されます。多くの場合、1つの仮想マシンには複数の実装が存在し、それぞれが異なる機能セットをカバーしています。
ここに示す表は、仮想マシンの設計において効率性を高めることを目的とした要素をまとめたものであり、個々の実装に存在する機能の一覧ではありません。
仮想マシンの命令は、スタックマシン、レジスタマシン、またはランダムアクセスマシン(メモリマシンとも呼ばれる)といった主要な計算モデルを用いて、ローカル変数内のデータを処理します。これら3つの方式が採用されるのは、仮想マシンと物理マシンにおける、解釈、コンパイル、セキュリティ検証の容易さといった、それぞれ異なるトレードオフが存在するためです。
これらのポータブル仮想マシンにおけるメモリ管理は、物理マシンよりも高い抽象度で扱われます。人気の高いJava仮想マシン(JVM)など、一部の仮想マシンはアドレスを扱う際に、ポインタ参照をトレースして安全な自動メモリ管理を行う必要があり、マシン命令によるメモリへのポインタの手動構築を禁止しています。一方、LLVMなどの他の仮想マシンは、従来の物理マシンに近く、ポインタの直接使用と操作が可能です。Common Intermediate Language(CIL)は、その中間的なハイブリッドであり、メモリの制御された使用(安全な自動メモリ管理を可能にするJVMと同様)と、型境界や権限に違反する可能性のある直接的なポインタ操作を可能にする「安全でない」モードの両方を提供します。
コードセキュリティとは一般的に、ポータブル仮想マシンがコードを実行する際に、あらかじめ定められた機能のみを提供する能力を指します。例えば、仮想マシンはコードが特定の関数やデータにのみアクセスすることを許可する場合があります。自動メモリ管理を可能にし、仮想マシンが型安全なデータアクセスを保証するために用いられるポインタ制御は、コード断片がメモリの特定の要素にのみアクセスでき、仮想マシン自体を迂回できないようにするためにも使用されます。さらに、コード検証器、スタック検証器、その他の手法といったセキュリティメカニズムが、その上に重ねて適用されます。
インタプリタを使用すると、仮想命令で構成されたプログラムを、ネイティブマシン命令へのコンパイルというコストのかかる処理を経ることなく、すぐにロードして実行できます。実行可能な仮想マシンであれば、どのようなものでもインタプリタで実行できるため、この列の指定は、設計に効率的なインタプリタ処理(一般的な使用を想定した)のための機能が含まれているかどうかを示しています。
ジャストインタイムコンパイル(JIT)とは、プログラムの実行直前または実行中に、可能な限り遅いタイミングでネイティブ命令にコンパイルする方法を指します。JITの課題は、仮想マシンの設計というよりも実装上の課題ですが、最近の設計では効率性を向上させるための配慮がなされ始めています。最も単純なJIT方式は、オフラインコンパイラと同様に、コード断片にコンパイルするだけです。しかし、より複雑な方式が用いられることが多く、コンパイルされたコード断片を、実行時にのみ判明するパラメータに合わせて特化します(適応最適化を参照)。
事前コンパイル(AOT)とは、プリコンパイラを使用して、プログラムの実行中に変更されない一連のネイティブ命令を生成する、より古典的な手法を指します。積極的なコンパイルと最適化には時間がかかるため、プリコンパイルされたプログラムは、JITのみで実行されるプログラムよりも高速に起動する可能性があります。JVMの実装では、JITによってネイティブコード断片が生成されるまで、初期段階で解釈を行うことで起動時間を短縮し、この起動コストを軽減しています。
共有ライブラリは、複数の実行中のプログラム間でネイティブコードのセグメントを再利用するための機能です。最新のオペレーティングシステムでは、これは一般的に、仮想メモリを使用して、共有ライブラリを含むメモリ ページを、メモリ保護によって互いに保護された異なるプロセス間で共有することを意味します。適応型最適化などの積極的な JIT 手法では、プロセス間またはプログラムの連続実行間で共有するのに適さないコード フラグメントが生成されることが多く、プリコンパイルされた共有コードの効率性と、適応的に特化されたコードの利点との間でトレードオフを行う必要があるのは興味深い点です。たとえば、CIL には、より特化した JIT コードを犠牲にすることで、効率的な共有ライブラリを可能にするための設計規定がいくつかあります。OS Xの JVM 実装では、Java Shared Archive [ 4 ]を使用して、共有ライブラリの利点の一部を提供しています。
上記で説明したポータブル仮想マシンに加えて、仮想マシンは個々のスクリプト言語の実行モデルとしてもよく利用され、通常はインタプリタによって実行されます。この表には、上記のポータブル仮想マシンとスクリプト言語仮想マシンの両方について、具体的な仮想マシンの実装例を示します。