この記事では、Java のメモリ機構に関する関連知識を中心に紹介します。非常に参考になる内容です。エディターで見てみましょう。
Java では、メモリが 2 種類に分けられます。1 つはスタック メモリ、もう 1 つはヒープです。メモリ。 関数内で定義されたいくつかの基本的なタイプの変数とオブジェクト参照変数は、関数のスタック メモリに割り当てられます。変数がコード ブロック内で定義されると、Java はスタック内の変数にメモリ領域を割り当てます。変数のスコープ (たとえば、関数 A で関数 B を呼び出し、関数 B で変数 a を定義します。変数 a のスコープは関数 B のみです。関数 B の実行後、変数 a は自動的に破棄されます。それに割り当てられた値)メモリはリサイクルされます)、Java は変数に割り当てられたメモリ領域を自動的に解放し、そのメモリ領域を他の目的にすぐに使用できるようになります。
ヒープメモリは、newによって作成されたメモリ配列を格納するために使用されます。ヒープに割り当てられたメモリは、Java仮想マシンの自動ガベージコレクタによって管理されます。ヒープ内に配列またはオブジェクトを生成した後、スタック内の変数の値がヒープ メモリ内の配列またはオブジェクトの最初のアドレスと等しくなるように、スタック内に特殊な変数を定義することもできます。スタックは配列またはオブジェクトの参照変数を取得した後、プログラム内でスタック内の変数を使用してヒープ内の配列またはオブジェクトにアクセスできます。参照変数は配列またはオブジェクトに名前を付けることと同じです。参照変数は、定義時にスタックに割り当てられる通常の変数で、プログラムが他のスコープ外で実行された後に解放されます。配列とオブジェクトはヒープ内に割り当てられます。new によって生成された配列またはオブジェクト ステートメントが配置されているコード ブロックの外でプログラムが実行された場合でも、配列とオブジェクトによって占有されていたメモリは解放されません。配列とオブジェクトを指す参照変数が存在しない場合、それらはガベージとなり、後で不定の時点でガベージ コレクターによって収集 (解放) されます。これは、Java がより多くのメモリを消費する理由でもあります。実際、スタック内の変数は、Java のポインタであるヒープ メモリ内の変数を指します。
コード例 Demo1: 単一オブジェクトの作成
class Person { String name ; int age ; public void tell() { System.out.println("姓名:"+name+",年龄:"+age); } } public class Demo1 { public static void main(String[] args) { Person per = new Person() ; } }
上記のプログラムでは、インスタンス化プロセス中に、スタック メモリとヒープ メモリを含むメモリ内の領域を解放する必要があります。メモリ割り当ては次の図に示されています:
図 1-1 オブジェクトのインスタンス化プロセス
上の図から、オブジェクト名ごとにスタック メモリに保存されていることがわかります (より正確には、スタック メモリに保存されるのはヒープ メモリ空間のアクセス アドレス) であり、属性名前や年齢などのオブジェクトの特定の内容がヒープ メモリに保存されます。 per オブジェクトはインスタンス化されただけで特定の値が割り当てられていないため、デフォルト値が設定されています。 stringのデフォルト値はnull、int型のデフォルト値は0です。前述したように、ヒープ メモリ空間は new キーワードを使用して開く必要があります。
コード例 Demo2: 複数のオブジェクトの作成
class Person { String name ; int age ; public void tell() { System.out.println("姓名:"+name+",年龄:"+age); } } public class Demo2 { public static void main(String[] args) { Person per1 = new Person() ; Person per2 = new Person() ; per1.name="张三" ; per1.age=30 ; per2.age=33 ; per1.tell(); per2.tell(); } }
図 1-2 2 つのオブジェクトをインスタンス化する
主要な概念: 配列と同様、クラスは参照型であり、参照型は同じ A ヒープ メモリを参照します複数のスタック メモリによってポイントされる可能性があります。参照渡しの簡単な例を見てみましょう。
コード例 Demo3: オブジェクト参照転送1
class Person { String name ; int age ; public void tell() { System.out.println("姓名:"+name+",年龄:"+age); } } public class Demo3 { public static void main(String[] args) { Person per1 = new Person() ; Person per2 = per1 ;//-------注意-------- per1.name="张三" ; per1.age=30 ; per2.age=33 ; per1.tell(); per2.tell(); } }
プログラムの実行結果は次のとおりです:
プログラムの実行結果から、2つのオブジェクトが出力する内容は同じであることがわかります。実際、いわゆる参照転送とは、1 つのヒープ メモリ空間の使用権を複数のスタック メモリ空間に与えることです。各スタック メモリ空間は、ヒープ メモリ空間の内容を変更できます。このプログラムのメモリ割り当て図は次のとおりです。
図 1-3 オブジェクト参照のメモリ割り当ての受け渡し
図 1-3 オブジェクト参照のメモリ割り当ての受け渡し (続き)
注: 上記の例では、オブジェクトper2 にはヒープ メモリ領域がありません。これは、オブジェクト per2 が宣言操作のみを実行するためであり、インスタンス化操作もありません。 new キーワードを使用するだけで、インスタンス化後にヒープ メモリ領域が確保されます
コード例 Demo4: オブジェクト参照転送 2
class Person { String name ; int age ; public void tell() { System.out.println("姓名:"+name+",年龄:"+age); } } public class Demo4 { public static void main(String[] args) { Person per1 = new Person() ; Person per2 = new Person() ; per1.name="张三" ; per1.age=30 ; per2.name="李四" ; per2.age=33 ; per2=per1 ;//-----注意---- per1.tell(); per2.tell(); } }
上記のプログラムの実行結果は次のとおりです:
プログラムの出力から、Demo3 と似ていることがわかります。ただし、以下に示すように、メモリ割り当てにいくつかの変更が加えられています。
図 1-4 (ガベージ オブジェクト) の生成
注:
1. Java 自体がガベージ コレクション メカニズム (ガベージ コレクション、 GC) は、オブジェクトが使用されなくなっている限り、上記のヒープ メモリ内の name="李思";age=33 などの領域が GC によって解放されるまで待機します。 。
2. スタック メモリは 1 つのヒープ メモリ空間のみを指すことができ、他のヒープ メモリ空間を指す場合は、新しいポインタを割り当てる前に、まず既存のポインタを切断する必要があります。
Javaの共通メモリ領域
Javaには主に4つのメモリ空間があり、これらのメモリの名前と機能は次のとおりです:
1.スタックメモリ空間:すべてのオブジェクトの名前を保存します。
2. ヒープメモリ空間: 各オブジェクトの特定の属性内容を保存します。
3. グローバルデータ領域:静的型の属性値を保存します。
4. グローバルコード領域: すべてのメソッド定義を保存します。
以上がJavaのメモリの仕組みを画像と文章で詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。