Java仮想マシン-ランタイムデータ領域
JVM仕様は、プログラムの実行中に必要となる特定の実行時データ領域を定義します。それらのいくつかは、JVMの起動中に作成されます。その他はスレッドに対してローカルであり、スレッドが作成されたときにのみ作成されます(そして、スレッドが破棄されたときに破棄されます)。これらは以下にリストされています-
PC(プログラムカウンタ)レジスタ
これは各スレッドに対してローカルであり、スレッドが現在実行しているJVM命令のアドレスが含まれています。
スタック
これは各スレッドに対してローカルであり、メソッド呼び出し中にパラメーター、ローカル変数、および戻りアドレスを格納します。スレッドが許可されているよりも多くのスタックスペースを要求すると、StackOverflowエラーが発生する可能性があります。スタックが動的に拡張可能である場合でも、OutOfMemoryErrorをスローする可能性があります。
ヒープ
これはすべてのスレッド間で共有され、実行時に作成されるオブジェクト、クラスのメタデータ、配列などが含まれます。これは、JVMの起動時に作成され、JVMのシャットダウン時に破棄されます。特定のフラグを使用して、JVMがOSに要求するヒープの量を制御できます(これについては後で詳しく説明します)。パフォーマンスに重要な影響を与えるため、メモリの要求が少なすぎたり多すぎたりしないように注意する必要があります。さらに、GCはこのスペースを管理し、死んだオブジェクトを継続的に削除してスペースを解放します。
メソッドエリア
このランタイム領域はすべてのスレッドに共通であり、JVMの起動時に作成されます。定数プール(これについては後で詳しく説明します)、コンストラクターとメソッドのコード、メソッドデータなどのクラスごとの構造を格納します。JLSは、この領域をガベージコレクションする必要があるかどうかを指定しないため、 JVMはGCを無視することを選択できます。さらに、これはアプリケーションのニーズに応じて拡張される場合と拡張されない場合があります。JLSはこれに関して何も義務付けていません。
実行時定数プール
JVMは、ロードされたクラスをリンクしている間、シンボルテーブル(その多くの役割の1つ)として機能するクラスごと/タイプごとのデータ構造を維持します。
ネイティブメソッドスタック
スレッドがネイティブメソッドを呼び出すと、Java仮想マシンの構造とセキュリティ制限がその自由を妨げない新しい世界に入ります。ネイティブメソッドは、仮想マシンのランタイムデータ領域にアクセスできる可能性があります(ネイティブメソッドのインターフェイスによって異なります)が、それ以外のことも実行できます。
ガベージコレクション
JVMは、Javaのオブジェクトのライフサイクル全体を管理します。オブジェクトが作成されると、開発者はそれについて心配する必要がなくなります。オブジェクトが停止した場合(つまり、オブジェクトへの参照がなくなった場合)、シリアルGC、CMS、G1などの多くのアルゴリズムのいずれかを使用してGCによってヒープから排出されます。
GCプロセス中に、オブジェクトはメモリ内で移動されます。したがって、これらのオブジェクトは、プロセスの進行中は使用できません。プロセスの間、アプリケーション全体を停止する必要があります。このような一時停止は「stop-the-world」一時停止と呼ばれ、大きなオーバーヘッドになります。GCアルゴリズムは、主にこの時間を短縮することを目的としています。これについては、次の章で詳しく説明します。
GCのおかげで、Javaではメモリリークは非常にまれですが、発生する可能性があります。後の章で、Javaでメモリリークを作成する方法を説明します。