[JVM] jvm 仮想マシンのヒープ

1. JVM アーキテクチャ

ここに画像の説明を挿入次にお話しするJVMのランタイムデータ領域のヒープ領域(Heap Area)です。

2. Java ヒープの紹介

Java アプリケーションの場合、Java ヒープ (Java ヒープ) は、仮想マシンによって管理されるメモリの最大の部分です。Java ヒープは、すべてのスレッドで共有される領域であり、仮想マシンの起動時に作成されます。このメモリ領域の唯一の目的は、オブジェクト インスタンスを格納することであり、Java 世界の「ほとんど」すべてのオブジェクト インスタンスがここにメモリを割り当てます。「Java 仮想マシン仕様」における Java ヒープの説明は、「すべてのオブジェクト インスタンスと配列はヒープに割り当てる必要がある」です。

2.1 ヒープの特徴

  1. JVM インスタンスには 1 つのヒープ メモリしかありません堆也是Java内存管理的核心区域
  2. Java ヒープ領域は JVM の起動時に作成され、その領域サイズが決定されます。これは、JVM によって管理される最大のメモリ空間です。しかし堆内存的大小是可以调节的
  3. 《Java虚拟机规范》は、ヒープ**物理上不连续**が のが、**逻辑上**として扱う必要があります连续的
  4. ヒープは JVM プロセスに固有です。つまり、プロセスには JVM が 1 つしかありませんが、プロセスには多个线程,他们是共享同一堆空间的.
  5. すべてのスレッドが Java ヒープを共有し、thread-private 缓冲区( **Thread Local Allocation Buffer, TLAB**)も分割可能

2.2 ヒープ領域の細分化

ここに画像の説明を挿入上の図から、ヒープ領域は多くの領域に分割できることがわかります。

  1. 年轻代(Young Gen)
  2. 老年代(Old Gen)
  3. 永久代(Perm Gen)

その中で、若い世代はEden 空间Survivor 1空间( From区)、Survivor 0空间( To 区) に分けられ、注: 空いている人が 1 人ですTo区

  • すべてのオブジェクトはエデン エリアで生まれ、オブジェクトの年齢は 0 です。Eden 領域がいっぱいになると、マイナー GC がトリガーされ、マイナー GC は若い世代で再利用する必要があるオブジェクトのみをリサイクルします。マイナー GC ごとに、オブジェクトがリサイクルされない場合、オブジェクトの経過時間は + 1 になります。オブジェクトがしきい値に達すると、オブジェクトは古い世代に入ります (android のしきい値は 6)。
  • 古い世代のスペースがいっぱいになると、完全な GC がトリガーされ、完全な GC は、若い世代と古い世代で同時にリサイクルする必要があるすべてのオブジェクトをリサイクルします。

2.3 ヒープ空間の世代的な考え方

若い世代、古い世代、永続的な世代

  • 若い世代は、一時的なオブジェクトまたはライフサイクルの短いオブジェクトを配置するために使用されます
  • 古い世代は、寿命の長いオブジェクトを配置するために使用されます
  • 定数を格納するために使用される永続的な世代またはメタ空間
  • マイナー GC ( 轻GC) は若い世代のみを管理し、フル GC ( 重GC) は若い世代と古い世代の両方を管理します。

なんで世代?利点は何ですか?

  • 研究によると、さまざまなオブジェクトのライフサイクルには一貫性がないことが示されていますが、特定の使用プロセスでは、オブジェクトの 70% ~ 90% が一時的なオブジェクトです。
  • 世代別生成の唯一の理由は、GC のパフォーマンスを最適化することです. 世代別世代がない場合, すべてのオブジェクトは 1 つの空間にあります. GC がリサイクルしたい場合, GC はすべてのオブジェクトを記述する必要があります. 世代別生成の後, 長期保持オブジェクトピッキングすることができ、短期保有オブジェクトをリサイクルのために 1 つの場所に固定することができ、スペース利用の大部分を節約できます。

2.4 ヒープのデフォルトサイズ

  • 初期サイズ: コンピュータの物理メモリの 1/64
  • 最大メモリ サイズ: コンピュータの物理メモリの 1/4

ランタイム クラス: このクラスに対応する JVM ランタイム データ領域

long initialMemory = Runtime.getRuntime().totalMemory();
long maxMemory = Runtime.getRuntime().maxMemory();
long freeMemory = Runtime.getRuntime().freeMemory();

3. JVMヒープメモリ共通パラメータ

パラメータ 例証する
-Xms m (メガバイト)、g (G) 単位のヒープ メモリの初期サイズ
-Xmx(最大ヒープサイズ) ヒープ メモリの最大許容サイズ。通常、物理メモリの 80% を超えません。
-XX:パーマサイズ 非ヒープ メモリの初期サイズ、一般的なアプリケーション設定は 200m に初期化され、最大 1024m で十分です
-XX:MaxPermSize 非ヒープ メモリの最大許容サイズ
-XX:NewSize(-Xns) 若い世代のメモリの初期サイズ
-XX:MaxNewSize(-Xmn) Young 世代のメモリの最大許容サイズ。短縮することもできます
-XX:SurvivorRatio=8 Young 世代の Eden 領域と Survivor 領域の容量比率。デフォルトは 8、つまり 8:1 です。
-Xss スタックメモリサイズ

4. ガベージ コレクション アルゴリズム (GC、ガベージ コレクション)

以下の種類のガベージ コレクション アルゴリズムは初心者向けです. 具体的で詳細なアルゴリズムの説明は自分で検索して学習する必要があります. アルゴリズムはたくさんあるので、学ぶべきことがたくさんあります.

赤は非アクティブ オブジェクト、緑はアクティブ オブジェクトです。

4.1 マークスイープ

GC は、マーキングとスイープの 2 つのフェーズに分かれています。最初にすべてのリサイクル可能なオブジェクトにマークを付け、マーキングが完了したら、マークされたすべてのオブジェクトを均一にリサイクルします。同時に、不連続なメモリ断片化が生成されます。過度の断片化は、プログラムが後で大きなオブジェクトを割り当てる必要があるときに、十分な連続したメモリを見つけることができず、最後の手段として GC を再度トリガーする必要があります。
ここに画像の説明を挿入

4.2 コピー

メモリを容量に応じて 2 つのブロックに分割し、一度に 1 つのみ使用します。このメモリが使い果たされたら、生き残ったオブジェクトを別のピースにコピーし、使用済みのメモリ領域を一度にクリーンアップします。このように、メモリ領域の半分が毎回再利用され、メモリの断片化の問題を考慮する必要がなく、シンプルで効率的です。不利な点は、2 倍のメモリ空間が必要です。
ここに画像の説明を挿入

4.3 マークコンパクト(マークコンパクト)

これも2段階に分かれており、まずリサイクル可能な物に印をつけ、生き残った物を片端に移動させ、境界外の記憶を片付ける。この方法は、マーク スイープ アルゴリズムのフラグメンテーションの問題を回避し、コピー アルゴリズムのスペースの問題も回避します。

一般に、若い世代で GC が実行された後、少数のオブジェクトが生き残り、コピー アルゴリズムが使用され、生き残ったオブジェクトをコピーするためのわずかなコストを支払うだけでコレクションを完了することができます。

古い世代では、オブジェクトの生存率が高く、追加のメモリ空間の割り当てがないため、リサイクルには mark-clean または mark-compact アルゴリズムを使用する必要があります。
ここに画像の説明を挿入

5.よくある間違い

5.1 ヒープメモリがオーバーフローするのはなぜですか?

若い世代で GC を生き残ったオブジェクトは、古い世代にコピーされます。古い世代のスペースが不十分な場合、JVM は古い世代で完全なガベージ コレクション (フル GC) を実行します。Survivor 領域からコピーされたオブジェクトが GC 後に格納できない場合、OOM (Out of Memory) が発生します。
OOM (メモリ不足) 例外は、次の理由で一般的です。

  1. 老年代内存不足:java.lang.OutOfMemoryError:Javaheapspace
  2. 永久代内存不足:java.lang.OutOfMemoryError:PermGenspace
  3. 代码bug,占用内存无法及时回收

これらのメモリ領域に OOM が発生することがありますが、実際に OOM に遭遇した場合、例外情報からどの領域でメモリ オーバーフローが発生したかを特定できます。

パラメーターを追加して、-XX:+HeapDumpOnOutMemoryErrorメモリ オーバーフローの例外が発生した場合に、仮想マシンが分析後の現在のメモリ ヒープ ダンプ スナップショットをダンプできるようにすることができます。

JAVA メモリ管理メカニズムと構成パラメータに精通しているため、JAVA アプリケーション起動オプションのチューニング構成は次のとおりです。

JAVA_OPTS=“-server -Xms512m -Xmx2g -XX:+UseG1GC -XX:SurvivorRatio=6 -XX:MaxGCPauseMillis=400 -XX:G1ReservePercent=15 -XX:ParallelGCThreads=4 -XX: ConcGCThreads=1 -XX:InitiatingHeapOccupancyPercent=
40 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:…/logs/gc.log」

ヒープメモリの最小値と最大値を設定します。最大値は過去の使用率設定を参照します

GC ガベージ コレクタを G1 に設定する

後で分析するために GC ログを有効にする

終わり!

おすすめ

転載: blog.csdn.net/weixin_44299027/article/details/128401494