現在、jconsoleを使用してJavaアプリケーションを監視しています。[メモリ]タブでは、次のいずれかを選択できます。
Heap Memory Usage
Non-Heap Memory Usage
Memory Pool “Eden Space”
Memory Pool “Survivor Space”
Memory Pool “Tenured Gen”
Memory Pool “Code Cache”
Memory Pool “Perm Gen”
それらの違いは何ですか?
ヒープメモリは、JavaVMがすべてのクラスインスタンスと配列にメモリを割り当てるランタイムデータ領域です。ヒープは、固定サイズでも可変サイズでもかまいません。ガベージコレクタは、オブジェクトのヒープメモリを再利用する自動メモリ管理システムです。
Eden Space:ほとんどのオブジェクトにメモリが最初に割り当てられるプール。
サバイバースペース:エデンスペースのガベージコレクションを生き残ったオブジェクトを含むプール。
TenuredGenerationまたはOldGen:サバイバースペースにしばらく存在していたオブジェクトを含むプール。
非ヒープメモリには、すべてのスレッド間で共有されるメソッド領域と、JavaVMの内部処理または最適化に必要なメモリが含まれます。ランタイム定数プール、フィールドとメソッドのデータ、メソッドとコンストラクターのコードなどのクラスごとの構造を格納します。メソッド領域は論理的にはヒープの一部ですが、実装によっては、JavaVMがガベージコレクションや圧縮を行わない場合があります。ヒープメモリと同様に、メソッド領域は固定サイズでも可変サイズでもかまいません。メソッド領域のメモリは連続している必要はありません。
永続的な生成:クラスオブジェクトやメソッドオブジェクトなど、仮想マシン自体のすべてのリフレクティブデータを含むプール。クラスデータ共有を使用するJavaVMでは、この世代は読み取り専用領域と読み取り/書き込み領域に分けられます。
コードキャッシュ:HotSpot Java VMには、ネイティブコードのコンパイルと保存に使用されるメモリを含むコードキャッシュも含まれています。
キーワードはnew、Javaヒープにメモリを割り当てます。ヒープはメモリのメインプールであり、アプリケーション全体にアクセスできます。そのオブジェクトに割り当てるのに十分なメモリがない場合、JVMはガベージコレクションを使用してヒープからメモリを再利用しようとします。それでも十分なメモリを取得できない場合は、OutOfMemoryErrorがスローされ、JVMが終了します。
ヒープは、世代と呼ばれるいくつかの異なるセクションに分割されます。オブジェクトがより多くのガベージコレクションを生き残るにつれて、オブジェクトはさまざまな世代に昇格します。古い世代は、ガベージコレクションが頻繁に行われることはありません。これらのオブジェクトはすでに長寿命であることが証明されているため、ガベージコレクションされる可能性は低くなります。
オブジェクトが最初に構築されるとき、それらはエデンスペースに割り当てられます。ガベージコレクションを生き延びた場合、サバイバースペースに昇格し、そこで十分に長く生きた場合、テニュア世代に割り当てられます。この世代は、ガベージコレクションの頻度がはるかに少なくなっています。
パーマネントジェネレーション、またはPermGenと呼ばれる第4世代もあります。ここにあるオブジェクトはガベージコレクションの対象ではなく、通常、クラス定義や文字列定数プールなど、JVMの実行に必要な不変の状態が含まれています。PermGenスペースはJava8から削除される予定であり、ネイティブメモリに保持されるMetaspaceと呼ばれる新しいスペースに置き換えられることに注意してください。参照:http://www.programcreek.com/2013/04/jvm-run-time-data-areas/
Java8では、非ヒープ領域にPermGenは含まれなくなりましたが、Java8の主要な変更であるMetaspaceは、クラスデータにjvmが必要とするスペースに応じてメタスペースのサイズを増やすことができるため、Javaでのメモリエラーを取り除くことになっています。
Javaヒープメモリは、オペレーティングシステムによってJVMに割り当てられたメモリの一部です。
オブジェクトは、ヒープと呼ばれる領域に存在します。ヒープはJVMの起動時に作成され、アプリケーションの実行中にサイズが増減する場合があります。ヒープがいっぱいになると、ゴミが収集されます。
Eden Space、Survivor Space、Tenured Space、Permanent Generationの詳細については、以下のSEの質問をご覧ください。
PermGenは、Java8のリリース以降Metaspaceに置き換えられました。
あなたの質問に関して:
コードキャッシュ: Java仮想マシン(JVM)は、ネイティブコードを生成し、コードキャッシュと呼ばれるメモリ領域に格納します。JVMは、動的に生成されたインタープリターループ、Java Native Interface(JNI)スタブ、ジャストインタイム(JIT)コンパイラーによってネイティブコードにコンパイルされるJavaメソッドなど、さまざまな理由でネイティブコードを生成します。JITは、コードキャッシュの最大のユーザーです。
ヒープは、次のように若い世代と古い世代に分けられます。
若い世代:オブジェクトが短期間住んでいた場所であり、2つのスペースに分かれています。
Old Generation:このプールには、基本的に、所有権のある仮想(予約済み)スペースが含まれており、YoungGenerationからのガベージコレクション後に存続したオブジェクトを保持します。
説明
アプリケーションが開始されたばかりだと想像してみましょう。
したがって、この時点で、これら3つのスペースはすべて空です(Eden、S0、S1)。
新しいオブジェクトが作成されるたびに、そのオブジェクトはEdenスペースに配置されます。
Edenスペースがいっぱいになると、ガベージコレクションプロセス(マイナーGC)がEdenスペースで実行され、残っているオブジェクトはすべてS0に移動されます。
その後、アプリケーションは実行を継続し、次にガベージコレクションプロセスが実行されるときにEdenスペースに新しいオブジェクトが作成され、EdenスペースとS0のすべてを調べ、存続するオブジェクトはすべてS1に移動されます。
PS:サバイバースペースでオブジェクトが存続する時間の構成に基づいて、オブジェクトはS0とS1に前後に移動し、しきい値に達すると、オブジェクトは旧世代のヒープスペースに移動されます。