記事ディレクトリ
1. JVMはどのようにメモリを管理しますか?
次の図は、Java仮想マシンのメモリ管理図を示しています。
1.プログラムカウンタ
- 概念:現在のスレッドによって実行されるバイトコードの行番号インジケーターと見なすことができます
- 特徴:スレッドプライベートメモリ
2.Java仮想マシンスタック
- 概念:Javaメソッド実行のメモリモデルについて説明します。(各メソッドを実行すると、ローカル変数テーブル、操作スタックフレーム、動的リンク、メソッド終了などの情報を格納するスタックフレームが作成されます。呼び出しから完了までの各メソッドのプロセスは、スタックに入ってからスタックに入るまでのスタックフレームに対応します。ポッププロセス)
- 特徴:スレッドはプライベートであり、ライフサイクルはスレッドのライフサイクルと同じです。この領域には2つの例外があります。StackOverflowError-スレッド要求の深さが仮想マシンで許可されている深さよりも大きい場合。OutOfMemoryError-仮想マシンを動的に拡張できる場合、バーサーカーが十分なメモリを適用できない場合。
3.ローカルメソッドスタック
- 概念:これは、仮想マシンスタックが果たす役割に似ています。違いは、java仮想マシンスタックがjavaメソッドを実行するのに対し、ローカルメソッドスタックはローカルメソッドを実行することです。
- 機能:スレッドはプライベートであり、2つの異なるStackOverflowErrorとOutOfMemoryErrorもスローされます。
4.スタック領域
- 概念:仮想マシンの起動時に作成される、すべてのスレッドによって共有される領域です
- 機能:スレッド共有、オブジェクトインスタンス(すべてのオブジェクトインスタンスと配列)の保存、GC管理のメインエリア。物理的に不連続なメモリ空間にある可能性があります。
5.メソッドエリア
- 概念:仮想マシンによってロードされた、クラス情報、定数、静的変数、ジャストインタイムコンパイラーによってコンパイルされたコードなどのデータを格納します。
- 機能:スレッド共有領域は、例外OutOfMemory例外をスローします-メソッド領域がメモリ割り当て要件を満たすことができない場合。
初心者にとって、知っておく必要のあるJava仮想マシンの3つの主要なメモリ空間は、「仮想マシンスタック」(スタックと呼ばれる)、「メソッド領域」、および「ヒープ領域」です。
- メソッドエリア:ストレージクラス情報
- スタック:メソッドの実行時にスタックフレームとローカル変数を格納します
- ヒープ:主に新しいオブジェクトとインスタンス変数をオブジェクト内に格納します
プログラムが実行される前にクラスがロードされるため、メソッド領域には最初にデータがあります。メソッドが継続的に実行および終了され、スタックがプッシュおよびポップされるため、スタックメモリアクティビティは最も面倒です。
2.オブジェクトが作成されたときのJVM仮想マシンのメモリ変更について簡単に説明します
コード:
public class StudentTest {
public static void main(String[] args) {
int i=10;
Student s1=new Student();
}
}
学生コード:
class Student{
int no;
String name;
int age;
boolean sex;
}
上記のコードの実行中のメモリの変更は次のとおりです。
- 最初のステップは、クラスをロードすることです
- 2番目のステップは、mainメソッドを呼び出して、スタックフレームをmainメソッドに割り当てる(スタックをプッシュする)ことです。
- 3番目のステップは、int i = 10を実行することです。
- 4番目のステップは、新しいstudent()を実行してヒープ内にオブジェクトを作成し、インスタンス変数を初期化することです。
- 5番目のステップは、ヒープ領域の学生オブジェクトのメモリアドレスをローカル変数s1に割り当てることです。
注:図の
i変数とs1変数は、どちらもスタックメモリ内のローカル変数ですが、iは基本です。データタイプintおよびs1は参照データタイプStudentです。
ヒープ内に作成されたオブジェクトs1の場合、オブジェクトの内部属性no、name、age、sexはすべてインスタンス変数です。これらの変数は、オブジェクトが新しいときに初期化されます。手動で割り当てられていない場合、システムによって割り当てられます。デフォルトでは。
「参照」の理解:
上図のヒープ領域での「オブジェクト」の作成が完了すると、ヒープ領域でのオブジェクトのメモリアドレスは0x1111になります。プログラムの=は、 0x1111のヒープメモリがs1変数に割り当てられます。つまり、s1変数はヒープメモリオブジェクトのメモリアドレスを保持します。s1はオブジェクトではなく、オブジェクトへの参照です、オブジェクトは実際にはヒープ領域にあり、s1はこのオブジェクトのメモリアドレスを保持します。
Javaにはポインタの概念がないため、Javaプログラマはヒープメモリを直接操作する権利がなく、「参照」を介してのみヒープメモリ内のオブジェクトにアクセスできます。
総括する
上記の説明を通じて、ローカル変数はスタック領域に格納され、インスタンス変数はヒープ領域に格納されることを知っておく必要があります。インスタンス変数の初期化は、オブジェクトの作成中に値を初期化して割り当てることです。Javaは、オブジェクト名と属性を介してオブジェクトのインスタンス変数にアクセスします。