Javaメモリ分布のまとめの詳細

2878 ワード

Javaメモリの分散:Java仮想マシンはJavaプログラムを実行する過程で管理するメモリをいくつかの異なるデータ領域に分けます:メソッド領域、仮想マシンスタック、ローカルメソッドスタック、スタック、プログラムカウンタ.
1.プログラムカウンタ
プログラムカウンタは、現在のスレッドで実行されているバイトコードの行番号インジケータと見なすことができる小さなメモリ領域です.仮想マシンのコンセプトモデルでは、バイトコード解釈器が動作するときに、このカウンタの値を変更することによって、実行する必要があるバイトコード命令を選択します.
ブランチ、ループ、ジャンプ、異常処理、スレッドリカバリなどの基礎機能は、このカウンタに依存して完了する必要があります.
スレッド切り替え後に正しい実行位置に復元するには、各スレッドに独立したプログラムカウンタが必要であり、各スレッド間のカウンタは互いに影響を及ぼさず、独立して格納されるため、このクラスのメモリ領域は「スレッドプライベート」のメモリである.
スレッドがJavaメソッドを実行している場合、このカウンタは実行中の仮想マシンバイトコード命令のアドレスを記録します.Nativeメソッドが実行されている場合、このカウンタ値は空です.このメモリ領域は、Java仮想マシン仕様にOutOfMemoryErrorが規定されていない唯一のサブエリアです.
2.Java仮想マシンスタック
プログラムカウンタと同様に、Java仮想マシンスタックもスレッドプライベートであり、ライフサイクルとスレッドは同じです.仮想マシンスタックはJavaメソッドが実行するメモリモデルを記述する.各メソッドは、実行と同時に、ローカル変数テーブル、オペランドスタック、ダイナミックリンク、メソッド出口などの情報を格納するスタックフレームを作成します.
各メソッドは、呼び出しから実行が完了するまで、仮想マシンスタックにスタックフレームをスタックしてスタックを出るプロセスに対応します.
ローカル変数テーブルには、コンパイル時に知られる様々な基本データ型、オブジェクト参照(オブジェクトと等しくなく、オブジェクトへの参照)、returnAddressタイプが格納されます.スレッド要求のスタックの深さが仮想マシンが許容する深さより大きい場合、StackOverflowError例外が放出され、十分なメモリを申請できない場合、OutOfMemory例外が放出されます.
3.ローカルメソッドスタック
ローカルメソッドスタックと仮想マシンスタックの違いは、仮想マシンスタックが仮想マシンで実行されるJava(バイトコード)サービスであり、ローカルメソッドスタックが仮想マシンで使用されるNativeメソッドサービスであることである.
4.Javaスタック
Javaスタックは、すべてのスレッドで共有されるメモリ領域であり、仮想マシンの起動時に作成されます.このメモリ領域の唯一の目的は、オブジェクトインスタンスを格納することです.Javaスタックはゴミ回収器管理の主な領域です.
5.メソッド領域
メソッド領域はJavaスタックと同様に,各スレッドが共有するメモリ領域であり,仮想マシンにロードされたクラス情報,定数,静的変数,インスタントコンパイラによってコンパイルされたコードなどのデータを格納するために用いられる.
6.運転時定数プール
ランタイムプールはメソッド領域の一部です.Classファイルには、クラスのバージョン、フィールド、メソッド、インタフェースなどの記述情報のほかに、コンパイル中に生成された様々な字面量と記号参照を格納する定数プールがあります.この部分は、クラスがロードされた後にメソッド領域に入る実行時定数プールに格納されます.
ネット上の多くの解釈定数プールは文字列を例に挙げます.
たとえば

String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hel" + "lo";
String s4 = "Hel" + new String("lo");
String s5 = new String("Hello");
String s6 = s5.intern();
String s7 = "H";
String s8 = "ello";
String s9 = s7 + s8;
 
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // true
System.out.println(s1 == s4); // false
System.out.println(s1 == s9); // false
System.out.println(s4 == s5); // false
System.out.println(s1 == s6); // true

s 1=s 2はtrueでよく理解され、同じ定数プールのメモリアドレスを指します.
s 1=s 3はtrue:s 3にとって、つなぎ合わせるのはすべて字面量なので、コンパイラは最適化して、実はs 3=“Hello”を指します
s 1==s 4はfalse:new String(「lo」)は字面量ではなく変数であるため、コンパイラは変数が変化する可能性があるため最適化されません.
s 1==s 9はfalse:上と同じ理屈です.
s 4=s 5:2つの異なるオブジェクトの参照はもちろん異なります.
s 1=s 6:Stringのため.intern()メソッドとは、定数プールにこのStringオブジェクトに等しい文字列がすでに含まれている場合(オブジェクトがequals(Object)メソッドで決定されている場合)に、プール内の文字列を返します.そうでなければ、このStringオブジェクトをプールに追加し、このStringオブジェクトの参照を返します.任意の2つの文字列sおよびtに従い、s.equals(t)がtrueである場合にのみ、s.intern()==t.intern()がtrueとなる.
この文章があなたの役に立つことを望みます