1。概要
Java では、メモリは 2 つのタイプに分けられます。1 つはスタック メモリで、もう 1 つはヒープ メモリです。
プログラムの実行中、JAVA はメモリ内のスペースを 5 つに分割してデータを保存します。彼らです:
- 登録。
- ネイティブメソッドエリア
- メソッドエリア。
- スタック。
- ヒープ。
1.1 ヒープ
200テーブルあるレストラン、つまり同時に最大200テーブルのゲストを収容でき、ゲストのグループが来たときにいくつかのテーブルを配置することができます.ある日、テーブル数が200を超えると、それ以上のゲストを受け入れることができなくなります。
もちろん、夕食に来るゲストは同時にはできません. 早い人もいれば遅い人もいます. 上司は、最初に食事をしたゲストを手配し、チェックアウトして出発します.新しいゲスト。
ここで、ヒープはレストランで、最大容量の 200 テーブルはヒープ メモリのサイズです.ボスは GC (ガベージ コレクション).スペースに相当します.
1.2スタック
煙突を放置された井戸と比較してみましょう. この井戸は長年使用されたために水がなくなりました. 所有者は現在、自家醸造のワインを保管する場所として使用しています. ワインを保管するとき, 彼はワインの瓶をロープで引っ掛けて.ゆっくりと下げ、瓶を一つずつ積み上げていき、ワインを飲むときは一番上の瓶から取っていきます。
2.ヒープメモリ
2.1 ヒープメモリとは?
ヒープ メモリは一種の Java メモリです. その機能はJava にオブジェクトと配列を格納することです. 新しいオブジェクトを作成したり配列を作成したりすると, ヒープ メモリ内にスペースが開かれます. ストレージで使用します.
2.2 ヒープメモリの特徴は?
最初のポイント: ヒープは実際にはパイプラインと見なすことができるか、またはチケットを購入するためにキューに並ぶ状況が似ているため、ヒープ メモリの特性は、先入れ、先出し、後入れ、後出し、つまり、あなたは最初に列に並びます、わかりました、あなたは最初にチケットを購入します。
2 番目のポイント: ヒープはメモリ サイズを動的に割り当てることができ、ランタイムは実行時にメモリを動的に割り当てるため、事前にコンパイラに通知する必要はありませんが、実行時にメモリが動的に割り当てられるため、アクセス速度は遅いです。
2.3 新しいオブジェクトはどのようにヒープに割り当てられますか?
Java 仮想マシンの自動ガベージ コレクタによって管理される
3. スタックメモリ
3.1 スタックメモリとは?
スタック メモリは Java の別の種類のメモリで、主にプログラムの実行に使用されます。たとえば、基本型の変数やオブジェクトの参照変数などです。
3.2 スタックメモリの特徴
1点目:スタックメモリーはミネラルウォーターのボトルのようなもので、何かを入れると最初の1本が底に沈むので、先入れ先出し、後入れ先出しが特徴です。
2点目:アクセス速度はレジスターに次ぐヒープより速く、スタックデータは共有できるが、スタック内のデータサイズや寿命を決めなければならず、柔軟性に欠けるというデメリットがある
3.3 スタックメモリのメモリ割り当てメカニズム
スタック メモリはレベル 1 キャッシュと呼ばれ、ガベージ コレクタによって自動的に再利用されます。
3.4 データ共有
例:
int a = 3;
int b = 3;
処理の最初のステップ:
1. コンパイラは最初に int a = 3; を処理します
2. 変数 a への参照を作成します
3. スタックに 3 の値があるかどうかを確認します
4 . 見つからない場合は、3 が格納され、a は 3 を指します
処理の 2 番目のステップ:
1. b=3 を処理します
2. 変数 b への参照を作成します
3. それを見つけて直接割り当てます
3 番目のステップは次のように変わります:
次に
a = 4;
上記と同じ方法で
a の値が変化し、a は 4 を指します. b の値は変化しません.
2 つのオブジェクトがある場合は異なります. オブジェクトは同じ参照を指します.一方が変われば、もう一方も変わる。
4. スタックとヒープの違い
JVM はスタックベースの仮想マシン. JVM は、新しく作成されたスレッドごとにスタックを割り当てます。つまり、Java プログラムの場合、スタックの操作によってその操作が完了します。スタックはスレッドの状態をフレーム単位で保存します。JVM はスタック上で 2 つの操作のみを実行します。フレーム単位でのプッシュ操作とポップ操作です。
4.1 相違点
1. ヒープ メモリは、new によって作成されたオブジェクトと配列を格納するために使用されます。
2. スタック メモリは、メソッドまたはローカル変数などを格納するために使用されます。
3. ヒープは、先入れ先出し、後入れ後出しです。
4. スタックは、先入れ後出、後出しです。 -先入れ先出し
4.2 同じ
1. Java メモリの一種です
2. システムが自動的にリサイクルしますが、ヒープ メモリの場合は開発者が自動的にリサイクルします
5. インタビューの質問: Java ヒープとスタックの違い
Java スタックは各スレッドに関連付けられています. JVM が各スレッドを作成するとき, 主にスレッド実行中のローカル変数, メソッドの戻り値, 基本型の変数 (, int , short、long、byte、float、double、boolean、char) およびメソッド呼び出しのコンテキスト。スレッドの終了に伴いスタック空間は解放されるスタックの利点は、ヒープよりもアクセス速度が速く、スタックデータを共有できることである。ただし、欠点は、スタックに格納されるデータのサイズと有効期間を決定する必要があり、柔軟性に欠けることです。スタックには非常に重要な特徴があります。つまり、スタックに格納されたデータを共有できます。
Java のヒープは、すべてのスレッドによって共有されるメモリ領域です. ヒープは、配列、スレッド オブジェクトなどのさまざまな Java オブジェクトを保存するために使用されます. Java ヒープはランタイム データ領域であり、クラス (オブジェクトはそこから領域を割り当てます) . これらのオブジェクトは、new、newarray、anewarray、および multianewarray などの命令によって作成され、プログラム コードを明示的に解放する必要はありません. ヒープはガベージ コレクションを担当します. ヒープの利点は、メモリ サイズを動的に割り当てることができることです. Java のガベージ コレクタは、実行時にメモリを動的に割り当てるため、これらの使用されなくなったデータは自動的に削除されますが、欠点は、実行時にメモリが動的に割り当てられるため、アクセス速度が遅い。
適用する方法
- スタック:システムによって自動的に割り当てられます。たとえば、関数のローカル変数 int b を宣言すると、システムはスタック内に b 用のスペースを自動的に作成します。
- ヒープ: プログラマーが自分で申請し、サイズを指定する必要があります. C では malloc 関数を使用し、C++ では new 演算子を使用します.
申請後のシステム対応
- スタック: スタックの残りのスペースが要求されたスペースよりも大きい限り、システムはプログラムにメモリを提供します。それ以外の場合は、スタック オーバーフローを示す例外が報告されます。
- ヒープ: オペレーティング システムには、スペースのメモリ アドレスを記録するリンク リストがあります。システムがプログラムからアプリケーションを受け取ると、リンク リストを走査して、要求されたスペースよりも大きいスペースを持つ最初のヒープ ノードを見つけます。次に、空きメモリ ノードのリンク リストからノードを削除し、このノードの領域をプログラムに割り当てます。ほとんどのオペレーティング システムでは、この割り当てのサイズはこのメモリ空間の最初のアドレスに記録されるため、コード内の delete ステートメントはこのメモリ空間を正しく解放できます。さらに、検出されたペア ノードのサイズが要求されたサイズと正確に等しいとは限らないため、システムは自動的に冗長部分をリンク リストに戻します。
アプリケーションのサイズ制限
スタック: Windows では、スタックは下位アドレスに拡張されるデータ構造であり、連続したメモリ領域です。ステーション アドレスとスタックのサイズはシステムによって事前に決定されており、要求されたメモリ空間がスタックの残りの空間を超えると、スタック オーバーフローが通知されます。
ヒープ: ヒープは、上位アドレスに展開するメモリ構造であり、不連続なメモリ領域です。システムはリンク リストを使用して、不連続な空きメモリ アドレスを格納します。
アプリケーション効率の比較
- スタック: システムによって自動的に割り当てられ、高速です。しかし、プログラマーは制御できません。
- ヒープ: new によって割り当てられるメモリは一般的に遅く、メモリの断片化が発生しやすいですが、使用すると便利です。
**拡張:** Windows オペレーティング システムでは、VirtualAlloc を使用してメモリを割り当てる最良の方法。ヒープ上ではなく、スタック上ではなく、メモリ空間にメモリのブロックを確保します. 使用するのは不便ですが、高速で柔軟です.
ヒープとスタックの格納内容
- スタック: 関数が呼び出されると、最初にスタックにプッシュされるのは、メイン関数の次の命令のアドレス (関数呼び出しの次の実行ステートメント)、次に関数のパラメーターです。C コンパイラでは、パラメーターはスタックに右から左にプッシュされ、次に関数のローカル変数にプッシュされます。静的変数はスタックにプッシュされません。
- ヒープ: 通常、ヒープの先頭にヒープのサイズを格納するために 1 バイトが使用されます。ヒープの具体的な内容は、プログラマによって調整されます。
データ構造の面でのヒープとスタックは、上記のものとは異なります。ここでのヒープは優先度キューのデータ構造を指し、最初の要素が最も優先度が高く、スタックは実際には先入れ後出しの性質を満たす数学的構造またはデータ構造です。
参考記事(侵略と削除):
Javaヒープとスタックの違い、
Javaにおけるヒープとスタックを1分で徹底解説