.
JVMには、n個のメモリー空間に対して5つのセクションがあります:
- プログラムカウンター
- Java 仮想マシンスタック
- ネイティブメソッドスタック
- ヒープ
- メソッド領域
JDK 1.8のメタスペースはパーマネント世代に取って代わります。メタスペースは、JVM仕様のメソッド領域の実装であるという点で、パーマネント世代と性質が似ています。しかし、メタスペースとパーマネント世代の最大の違いは、メタデータスペースが仮想マシン内になく、ローカルメモリを使用することです。
プログラムカウンター
プログラムカウンターの定義
プログラムカウンタは、現在のスレッドが実行しているバイトコード命令のアドレスであるメモリ空間の小さな断片です。現在のスレッドがローカルメソッドを実行している場合、プログラムカウンタは未定義です。
プログラム・カウンターの役割
- バイトコードインタープリタは、コードのフロー制御を可能にするためにプログラムカウンタを変更することにより、命令を順次読み取ります。
- マルチスレッドの場合、プログラム・カウンタは現在のスレッドがどこで実行されているかを記録し、スレッドが切り替わったときに、そのスレッドがどこで実行されたかを知ることができます。
プログラムカウンターの特徴
- スレッドはプライベートで、各スレッドは独自のプログラム・カウンタを持っています。
- ライフサイクル:スレッドが作成されると作成され、スレッドが終了すると破棄されます。
- はOOMが発生しない唯一のメモリ領域です。
仮想マシンスタック
定義
Java仮想マシン・スタックは、Javaメソッドの実行プロセスを記述するメモリ・モデルです。
Java VMスタックは、実行しようとしているJavaメソッドごとに「スタック・フレーム」と呼ばれる領域を作成し、メソッドの実行時にメソッドに関するいくつかの情報を格納するために使用されます。
スタックを押し出します:
メソッド実行中にローカル変数を作成する必要がある場合、ローカル変数の値はスタックフレームのローカル変数テーブルに格納されます。
Java VM スタックの最上位にあるスタック・フレームは、現在実行中のアクティブ・スタックであり、PC レジスタはこのアドレスを指します。このアクティブ・スタック・フレームのローカル変数だけが、オペランド・スタックで使用できます。 このスタック・フレームで別のメソッドが呼び出されると、対応するスタック・フレームが再び作成され、新しく作成されたスタック・フレームがスタックの先頭に押し込まれ、現在のアクティブ・スタック・フレームになります。
メソッドの終了時に、現在のスタック・フレームは削除され、スタック・フレームの戻り値は、新しいアクティブなスタック・フレームのオペランド・スタックのオペランドになります。戻り値がない場合、新しいアクティブなスタック・フレームのオペランド・スタックのオペランドは変更されません。
スタックはスレッド専用で、データの一貫性に問題はなく、ロックもありません。
Java 仮想マシンスタックの特徴
- ローカル変数テーブルはスタック・フレームの作成と同時に作成され、そのサイズはコンパイル時に決定され、作成時にあらかじめ指定されたサイズのみが割り当てられます。ローカル変数テーブルのサイズは、メソッドの実行中に変更されることはありません。
- JavaのVMスタックもスレッドプライベートで、スレッドが作成されると作成され、スレッドが終了すると破棄されます。
ネイティブメソッドスタック
ネイティブ・メソッド・スタックは、JVMがネイティブ・メソッドを実行するために用意されたスペースで、多くのネイティブ・メソッドがC言語で実装されているため、しばしばCスタックと呼ばれます。ネイティブ・メソッドを実行するプロセスを記述するメモリ・モデルであることを除けば、Java VMスタックと似ています。ネイティブ・メソッド・スタックがネイティブ・メソッドを実行するプロセスを記述するメモリ・モデルであることを除けば、Java VMスタックに似ています。
ヒープ
ヒープはオブジェクトを格納するためのメモリ空間で、ほとんどすべてのオブジェクトがヒープに格納されます。
ヒープの特徴
- スレッド共有、Java仮想マシン全体のヒープは1つだけで、すべてのスレッドが同じヒープにアクセスします。プログラム・カウンタ、Java VMスタック、ローカル・メソッド・スタックはすべて、スレッドごとに1つです。
- 廃棄物のリサイクルの主要な場所です。
- 新世代と旧世代。
地域によってライフサイクルの異なるオブジェクトを保存しているため、地域によって異なるゴミ収集アルゴリズムを使用することができ、よりターゲットを絞ることができます。
メソッド領域
Jメソッド・エリアは以下の情報を保持します:
- 仮想マシンによってロードされたクラスに関する情報
- 定数
- 静的変数
- オンザフライ・コンパイラでコンパイルされたコード
メソッド領域の特徴
- スレッド共有。 メソッド領域はヒープの論理的な一部であるため、ヒープと同様にスレッド共有されます。メソッド領域は仮想マシン全体で1つしかありません。
- 永久世代。 メソッド領域の情報は一般的に長く存在する必要があり、ヒープの論理的な分割であるため、ヒープ分割法を用いてメソッド領域を「永久世代」と呼びます。
- メモリの再利用は非効率的です。 メソッド領域の情報は一般的に長い間存在する必要があり、一度再利用した後に無効になる情報はわずかです。主な再利用目標は、定数プールの再利用、型のアンロードです。
- Java仮想マシンの仕様は、メソッド領域に関してより緩やかです。 ヒープと同様、固定サイズも動的拡張も許されており、ゴミコレクションを実装しないことも許されています。
ランタイム定数プール
メソッド・エリアには、クラス情報、定数、静的変数、即時コンパイラによってコンパイルされたコードが格納されます。定数はランタイム定数プールに格納されます。
クラスがJava仮想マシンによってロードされると、.classファイル内の定数がメソッド・エリアのランタイム定数プールに格納されます。そして実行時に、新しい定数をプールに追加することができます。例えば、String クラスの intern() メソッドは、実行時に文字列定数をプールに追加します。
ヒープとスタックの違いヒープとスタックの違い
ヒープとスタックの関係
連絡先:オブジェクトや配列を参照する場合、スタックに定義された変数はヒープ内のターゲットの先頭アドレスを保持します。
相違点
スペースサイズ:スタックはヒープより小さい。
アロケーションモード:スタックは静的アロケーションと動的アロケーションをサポートし、ヒープは動的アロケーションのみをサポートします。
* 効率性:スタックはヒープよりも効率的です。