Javaのスタックメモリとヒープスペース

1前書き

アプリケーションを最適な方法で実行するために、JVMはメモリをスタックメモリとヒープメモリに分割します。 ** 新しい変数やオブジェクトを宣言するとき、新しいメソッドを呼び出すとき、 String を宣言するとき、または同様の操作を実行するときはいつでも、JVMはスタックメモリまたはヒープスペースからこれらの操作に対してメモリを指定します。

このチュートリアルでは、これらのメモリモデルについて説明します。それらの間のいくつかの重要な違い、それらがRAMにどのように格納されるか、それらが提供する機能、そしてそれらをどこで使用するかについて、私たちは参加します。

2 Java のスタックメモリ

  • Javaのスタックメモリは、静的メモリの割り当てとスレッドの実行に使用されます** メソッドに固有のプリミティブ値と、そのメソッドから参照されるヒープ内のオブジェクトへの参照を含みます。

このメモリへのアクセスは後入れ先出し(LIFO)の順序で行われます。新しいメソッドが呼び出されるたびに、プリミティブ変数やオブジェクトへの参照のように、そのメソッドに固有の値を含むスタックの最上部に新しいブロックが作成されます。

メソッドが実行を終了すると、対応するスタックフレームがフラッシュされ、フローは呼び出し元のメソッドに戻り、次のメソッドに使用できるスペースができます。

2.1. スタックメモリの主な特長

これまで説明してきたこととは別に、以下はスタックメモリの他の機能です。

  • 新しいメソッドが呼び出されて返されるにつれて、拡大縮小します。

それぞれ ** スタック内の変数は、作成したメソッドが存在する限り存在します。

彼らは走っています ** メソッドが終了すると自動的に割り当てと割り当て解除が行われます

実行 ** このメモリがいっぱいの場合、Javaは java.lang.StackOverFlowError をスローします。

  • このメモリへのアクセスは、ヒープメモリに比べて速いです。

  • 各スレッドは独自のスタックで動作するため、このメモリはスレッドセーフ

3 Java のヒープスペース

  • Javaのヒープスペースは、実行時にJavaオブジェクトおよびJREクラスの動的メモリ割り当てに使用されます。新しいオブジェクトは常にヒープスペースに作成され、このオブジェクトへの参照はスタックメモリに格納されます。

これらのオブジェクトはグローバルアクセスを持ち、アプリケーション内のどこからでもアクセスできます。

この記憶モデルは世代と呼ばれるより小さな部分にさらに分割されます、これらは以下の通りです:

  1. Young Generation - これはすべての新しいオブジェクトが割り当てられる場所です.

歳です。これがいっぱいになると、マイナーガベージコレクションが発生します。 。 Old or Tenured Generation - ここは、長く生き残った物が存在する場所です。

保存しました。オブジェクトが若い世代に保存されている場合、 オブジェクトの年齢が設定され、そのしきい値に達すると、オブジェクトの 古い世代に移動します 。 パーマネントジェネレーション - これはランタイム用のJVMメタデータで構成されています。

クラスとアプリケーションメソッド

JVM、JRE、およびJDKの違い では、これらのさまざまな部分についても説明しています。

必要に応じていつでもヒープメモリのサイズを操作できます。

詳細については、https://www.baeldung.com/jvm-parameters[linked Baeldung article]を参照してください。

3.1. Javaヒープメモリの主な機能

これまで説明してきたこととは別に、ヒープスペースのその他の機能を次に示します。

  • 複雑なメモリ管理技術を介してアクセスされます。

ヤングジェネレーション、オールドまたはテニュアジェネレーション、およびパーマネントを含む 世代 ** ヒープスペースがいっぱいの場合、Javaは java.lang.OutOfMemoryError をスローします。

  • このメモリへのアクセスはスタックメモリよりも比較的遅いです。

  • このメモリは、スタックとは対照的に、自動的に解放されるわけではありません。それ

未使用のオブジェクトを解放するためにGarbage Collectorが必要です。 メモリ使用効率 ** スタックとは異なり、ヒープはスレッドセーフではなく、次のものによって保護される必要があります。

コードを正しく同期させる

4例

これまでに学んだことに基づいて、簡単なJavaコードを分析し、ここでメモリの管理方法を評価しましょう。

class Person {
    int pid;
    String name;

   //constructor, setters/getters
}

public class Driver {
    public static void main(String[]args) {
        int id = 23;
        String pName = "Jon";
        Person p = null;
        p = new Person(id, pName);
    }
}

このステップをステップごとに分析しましょう。

  1. main() メソッドに入ると、スタックメモリのスペースは次のようになります.

このメソッドのプリミティブと参照を格納するために作成されます。 ** 整数 id のプリミティブ値は直接スタックに格納されます

記憶 ** 型 __Person の参照変数 p __も作成されます

ヒープ内の実際のオブジェクトを指すスタックメモリ内 。パラメータ化されたコンストラクタ Person(int、String) からの呼び出し

main() は、前のスタックの上にさらにメモリを割り当てます。これは格納されます:

  • スタックメモリ内の呼び出し元オブジェクトの this オブジェクト参照

  • スタックメモリのプリミティブ値 _id _

  • String 引数 personName の参照変数

ヒープメモリ内の文字列プールからの実際の文字列を指す 。このデフォルトコンストラクタはさらに setPersonName() methodを呼び出しています。

それ以降の割り当ては、前のスタックメモリの上のスタックメモリで行われます。これもまた、上記の方法で変数を格納します。

  1. ただし、タイプ Person の新しく作成されたオブジェクト __p __では、すべて

インスタンス変数はヒープメモリに格納されます。

この割り当ては、この図で説明されています。

画像

5概要

この記事を締めくくる前に、Stack MemoryとHeap Spaceの違いについて簡単に要約しましょう。

| =================================================== =================== | |パラメータ|スタックメモリ|ヒープスペース|アプリケーション|スタックは、スレッドの実行中に一度に1つずつ使用されます。実行時にアプリケーション全体がヒープスペースを使用する

|サイズ|スタックはOSによってサイズに制限があり、通常はヒープよりも小さいです|ヒープにはサイズの制限はありません

| Storage |ヒープスペースに作成されたオブジェクトへのプリミティブ変数と参照だけを保存します

|順序|後入れ先出し(LIFO)メモリー割り振りシステムを使用してアクセスされます|このメモリーには、若い世代、古い世代または古い世代、および永続的世代を含む複雑なメモリー管理技術を介してアクセスします。

| Life |スタックメモリは現在のメソッドが実行されている限り存在します|ヒープスペースはアプリケーションが実行されている限り存在します

|効率|ヒープと比べて割り振りが比較的高速

|割り当て/割り当て解除|このメモリは、それぞれメソッドが呼び出され返されるときに自動的に割り当ておよび割り当て解除されます|新しいオブジェクトが作成され、参照されなくなったときにGargabe Collectorによって割り当て解除されるときにヒープスペースが割り当てられます| ======= ==================================================== =============

6. 結論

スタックとヒープは、Javaがメモリを割り当てる2つの方法です。この記事では、それらがどのように機能するのか、そしてより良いJavaプログラムを開発するためにいつそれらを使用するのかを理解しました。

Javaでのメモリ管理の詳細については、https://www.baeldung.com/java-memory-management-interview-questionsをご覧ください。 この記事の最後に で簡単に説明されているJVMガベージコレクタについても説明しました。