Javaメモリプールはどのように分割されますか?


224

現在、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”

それらの違いは何ですか?


Sun JDKを使用していると仮定すると、最良の答えはそれらのドキュメントにあります:ガベージコレクションのチューニング(JDK 1.5)およびガベージコレクションFAQ(JDK 1.4)
kdgregory 09

回答:


327

ヒープメモリ

ヒープメモリは、Java VMがすべてのクラスインスタンスと配列にメモリを割り当てるランタイムデータ領域です。ヒープのサイズは、固定でも可変でもかまいません。ガベージコレクターは、オブジェクトのヒープメモリを再利用する自動メモリ管理システムです。

  • Eden Space:ほとんどのオブジェクトにメモリが最初に割り当てられるプール。

  • Survivor Space:Edenスペースのガベージコレクションを生き残ったオブジェクトを含むプール。

  • Tenured GenerationまたはOld Gen:サバイバースペースにしばらくの間存在していたオブジェクトを含むプール。

ヒープ以外のメモリ

非ヒープメモリには、すべてのスレッドで共有されるメソッド領域と、Java VMの内部処理または最適化に必要なメモリが含まれます。ランタイム定数プール、フィールドとメソッドのデータ、メソッドとコンストラクターのコードなど、クラスごとの構造を格納します。メソッド領域は論理的にはヒープの一部ですが、実装によっては、Java VMがガベージコレクションや圧縮を行わない場合があります。ヒープメモリと同様に、メソッド領域のサイズは固定または可変です。メソッド領域のメモリは連続している必要はありません。

  • Permanent Generation:クラスやメソッドオブジェクトなど、仮想マシン自体のすべてのリフレクティブデータを含むプール。クラスデータ共有を使用するJava VMでは、この生成は読み取り専用領域と読み書き領域に分けられます。

  • コードキャッシュ:HotSpot Java VMには、ネイティブコードのコンパイルと保存に使用されるメモリを含むコードキャッシュも含まれています。

Jconsoleの使用方法に関するドキュメントをいくつか示します


4
Java仮想マシン仕様が明確に述べているため、@ dfaが完全に正しいかどうかはわかりません。「メソッド領域は論理的にはヒープの一部ですが、単純な実装ではガベージコレクトもコンパクト化もしない場合があります。」ただし、jconsoleがコードキャッシュと永続生成を非ヒープとして表示することは明らかであり、仕様とは矛盾しているようです。誰もがこの矛盾をより明確にすることができますか?
James Bloom

@JamesBloom-私は同じことを考えていました。基本的な定義では、どのメモリプールがどのタイプ(ヒープ/非ヒープ)に属しているかを示していますが、明示的に状態を変更できますか?
Umang Desai 2013

2
これはseminglyからニックされたドキュメント:docs.intergral.com/pages/viewpage.action?pageId=22478944ドキュメントはJVM、価値ブラウズに関するいくつかの他の良い情報が含まれ
スティーブシーベルト

1
多くの賛成投票にもかかわらず、実際にはそれほど意味のある答えではありません。たとえば、「エデン空間のガベージコレクションを生き残ったオブジェクト」とはどういう意味ですか?これらのオブジェクトは生き残った後、エデンからサバイバースペースに移動されますか、それともエデン内のオブジェクトはサバイバースペースと見なされますか?そして、Edenスペース以外のプールでのガベージコレクションはどうなりますか?まったくわからない。
Mikhail Batcer 2016年

スタック(非ヒープ側)を忘れないでください:)
Toothless Seer 2017年

70

新しいキーワードは、Javaヒープにメモリを割り当てます。ヒープは、アプリケーション全体からアクセス可能なメモリのメインプールです。そのオブジェクトに割り当てるのに十分なメモリがない場合、JVMはガベージコレクションを使用してヒープからメモリを回収しようとします。それでも十分なメモリを取得できない場合は、OutOfMemoryErrorがスローされ、JVMが終了します。

ヒープは、世代と呼ばれるいくつかの異なるセクションに分割されます。オブジェクトがガベージコレクションを存続させるにつれて、オブジェクトはさまざまな世代に昇格します。古い世代は、ガベージコレクションの頻度が高くありません。これらのオブジェクトはすでに長寿命であることが証明されているため、ガベージコレクションされる可能性は低くなります。

オブジェクトが最初に構築されるとき、それらはエデンスペースに割り当てられます。ガベージコレクションを生き残った場合、それらはサバイバースペースに昇格し、そこで十分に長く生きると、Tenured Generationに割り当てられます。この世代は、ガベージコレクションの頻度がはるかに低くなります。

また、Permanent Generation(PermGen)と呼ばれる第4世代もあります。ここにあるオブジェクトはガベージコレクションの対象ではなく、通常、クラス定義や文字列定数プールなど、JVMの実行に必要な不変の状態が含まれています。PermGenスペースはJava 8から削除される予定で、ネイティブメモリーに保持されるMetaspaceと呼ばれる新しいスペースに置き換えられることに注意してください。参照:http : //www.programcreek.com/2013/04/jvm-run-time-data-areas/

ここに画像の説明を入力してください ここに画像の説明を入力してください


図は非常に自明に見えます...これは任意のGCアルゴリズムに有効ですか。G1は別のセットを持っています。
Venkateswara Rao

@Pythoner濃い紫色の旗は、その上で既に定義されているものであるべきで-XX:PermSize、そう-XX:MaxPermSizeではないはずです。
Anurag

35

Java8では、非ヒープ領域にPermGenは含まれていませんが、メタスペースはJava8の主要な変更であり、メタデータのサイズは、jvmがクラスデータに必要とするスペースに応じて増加する可能性があるため、Javaのメモリ不足エラーを取り除くことになっています。


1
実際には、メタスペースとクラススペースがあります。 docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/...
mrswadge

23

Javaヒープメモリは、オペレーティングシステムによってJVMに割り当てられたメモリの一部です。

オブジェクトは、ヒープと呼ばれる領域にあります。ヒープは、JVMの起動時に作成され、アプリケーションの実行中にサイズが増減する場合があります。ヒープがいっぱいになると、ガーベッジが収集されます。

ここに画像の説明を入力してください

Eden Space、Survivor Space、Tenured Space、Permanent Generationの詳細については、以下のSEの質問をご覧ください。

若い、テニュア、パーマ世代

PermGenは、Java 8リリース以降、メタスペースに置き換えられました。

あなたの質問について:

  1. Eden Space、Survivor Space、Tenured Spaceはヒープメモリの一部です
  2. メタスペースとコードキャッシュは、非ヒープメモリの一部です。

コードキャッシュ: Java仮想マシン(JVM)はネイティブコードを生成し、コードキャッシュと呼ばれるメモリ領域に格納します。JVMは、動的に生成されるインタープリターループ、Java Native Interface(JNI)スタブ、ジャストインタイム(JIT)コンパイラーによってネイティブコードにコンパイルされるJavaメソッドなど、さまざまな理由でネイティブコードを生成します。JITは、コードキャッシュの最大のユーザーです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.