JVM ランタイム メモリ生成構造

JVM ランタイム メモリ生成構造

Java アプリケーションの場合、Java ヒープは仮想マシンによって管理されるメモリの最大の部分です。 Java ヒープはすべてのスレッドで共有されるメモリ領域であり、仮想マシンの起動時に作成されます。このメモリ領域の唯一の目的はオブジェクト インスタンスを格納することであり、すべてのオブジェクト インスタンスにここでメモリが割り当てられます。

Java ヒープは、ガベージ コレクターによって管理されるメモリ領域です。メモリ回復の観点から見ると、ほとんどのガベージ コレクターは世代別コレクション理論に基づいて設計されているため、Java ヒープには「新しい世代」、「古い世代」、「永久世代」、「Eden 空間」、「Survivor 空間から」、「Survivor 空間へ」などの領域が頻繁に出現します。これらの領域分割は、特定の Java 仮想マシン実装の固有のメモリ レイアウトではなく、一部のガベージ コレクターの一般的な特性または設計スタイルにすぎず、Java 仮想マシン仕様における Java ヒープに関する公式の定義でもありません。たとえば、Shenandoah と ZGC は世代をサポートしていません。

JDK 1.7 世代構造

JDK 1.7 以前では、ヒープ領域は新しい世代、古い世代、永続的な世代の 3 つの部分に分かれています。そして、新しい世代はエデンエリアと 2 つのサバイバーエリアに分割されます。下の図に示すように


JDK 1.8 世代構造

JDK 1.8 以降では、永続世代はヒープ領域から削除されます。永続世代が削除される理由については、次のドキュメントを参照してください: http://openjdk.java.net/jeps/122。主な理由は次のとおりです。これは、Hotspot と JRockit 仮想マシンの融合です。 JRockit クライアントは、永続的な世代を構成する必要はありません (JRockit には永続的な世代がないため)。また、永続的な世代を構成しないのが通例です。メタスペースを追加すると、クラスのロードに必要なメモリ領域が解決され、メタスペースはデフォルトで自動的に拡張されます。これにより、メモリ オーバーフローの可能性が軽減されます。ヒープ領域から永続世代が削除された後、ヒープ領域の構造は次のようになります。

ランタイム データ領域の構造を次の図に示します。


G1コレクター

G1 は、新世代と旧世代間の物理的な空間分割を解除します。代わりに、G1 アルゴリズムはヒープ領域を複数の領域に分割しますが、これは依然として世代別コレクターです。ただし、これらの領域の一部には新しい世代が含まれており、新しい世代のガベージ コレクションでは、すべてのアプリケーション スレッドを一時停止して、生き残ったオブジェクトを古い世代または Survivor スペースにコピーする方法が引き続き使用されます。古い世代も多くの領域に分割されており、G1 コレクターはオブジェクトをある領域から別の領域にコピーすることでクリーンアップを完了します。つまり、通常の処理中に、G1 はヒープ (少なくともヒープの一部) の圧縮を完了するため、CMS メモリの断片化の問題は発生しません。

G1には、Humongousエリアと呼ばれる特別なエリアもあります。オブジェクトがパーティション容量の 50% 以上を占める場合、G1 コレクターはそれを巨大オブジェクトと見なします。これらの巨大オブジェクトは、デフォルトでは古い世代に直接割り当てられますが、寿命の短い巨大オブジェクトの場合は、ガベージ コレクターに悪影響を及ぼします。この問題を解決するために、G1 は巨大なオブジェクトを保管するために使用される Humongous 領域を分割します。巨大なオブジェクトが 1 つの H 領域に収まらない場合、G1 はそれを保存するために連続する H パーティションを探します。連続した H 領域を見つけるために、Full GC を開始する必要がある場合があります。

オブジェクトメモリの割り当て

オブジェクト メモリの割り当てプロセスは次のとおりです。

メモリ割り当てルールの具体的な説明は次のとおりです。

オブジェクトはまずEden領域に割り当てられます

ほとんどの場合、オブジェクトは新世代の Eden 領域に割り当てられます。 Eden 領域に割り当てるための十分なスペースがない場合、仮想マシンはマイナー GC を開始します。 HotSpot 仮想マシンは、コレクター ログ パラメータ -XX:+PrintGCDetails を提供します。これは、ガベージ コレクションが発生したときにメモリ回復ログを印刷し、プロセスが終了したときに各領域の現在のメモリ割り当てステータスを出力するように仮想マシンに指示します。テストコード:

  1. /**
  2. * -XX:+PrintGC詳細
  3. */
  4. パブリッククラスGCTest{
  5.  
  6. 公共 静的void main(String[] args) {
  7. byte[] allcation2 = 新しいbyte[8000 * 1024];
  8. }
  9. }

出力

  1. ヒープ
  2. PSYoungGen 合計 38400K、使用済み 11353K [0x0000000795580000、0x0000000798000000、0x00000007c0000000)
  3. エデンスペース33280K、34% 使用済み [0x0000000795580000,0x00000007960966f8,0x0000000797600000)
  4. から スペース5120K、使用率 0% [0x0000000797b00000、0x0000000797b00000、0x0000000798000000)
  5.    スペース5120K、使用率 0% [0x0000000797600000、0x0000000797600000、0x0000000797b00000)
  6. ParOldGen 合計 87552K、使用済み 0K [0x0000000740000000、0x0000000745580000、0x0000000795580000)
  7. オブジェクトスペース87552K、使用率 0% [0x0000000740000000,0x0000000740000000,0x0000000745580000)
  8. メタスペース使用 3017K、容量 4556K、コミット済み4864K、予約済み 1056768K
  9. クラススペース使用済み 319K、容量 392K、コミット済み512K、予約済み 1048576K

メモリ空間の分布から、allocation2 が eden 領域に割り当てられていることがわかります。

大きなオブジェクトは直接古い世代に送られます

ラージ オブジェクトとは、大量の連続したメモリ領域を必要とする Java オブジェクト (文字列や配列など) を指します。 JVM パラメータ -XX:PretenureSizeThreshold を使用すると、大きなオブジェクトのサイズを設定でき、設定された値より大きいオブジェクトは古い世代に直接割り当てられ、若い世代には入らないように指定できます。このパラメータは、Serial および ParNew コレクターでのみ有効です。たとえば、JVM パラメータ: -XX:PretenureSizeThreshold=1000000 (ユニット直接) -XX:+UseSerialGC を設定すると、上記の最初のプログラムを実行すると、大きなオブジェクトが直接古い世代に移動されることがわかります。これを行う目的は、Eden 領域と 2 つの Survivor 領域間でのコピーを回避することです。コピーが行われると、大量のメモリ コピー操作が発生します。

長寿命オブジェクトは古い世代に入ります

HotSpot 仮想マシンのほとんどのコレクターは、世代別コレクションを使用してヒープ メモリを管理します。メモリがリサイクルされるとき、どの残存オブジェクトを新しい世代に配置し、どの残存オブジェクトを古い世代に配置するかを決定できる必要があります。これを行うために、仮想マシンは各オブジェクトのオブジェクト年齢カウンタを定義し、それをオブジェクト ヘッダーに格納します。オブジェクトは通常、エデン領域で生成されます。最初のマイナー GC 後もオブジェクトが存続し、Survivor スペースに収容できる場合、オブジェクトは Survivor スペースに移動され、オブジェクトの年齢は 1 年に設定されます。オブジェクトがサバイバー領域でマイナー GC を生き延びるたびに、そのオブジェクトの年齢は 1 年増加します。年齢が一定のレベル (デフォルトは 15) に達すると、古い世代に昇格されます。古い世代に昇格されるオブジェクトの年齢しきい値は、-XX:MaxTenuringThreshold パラメータを使用して設定できます。

動的オブジェクト年齢判定

さまざまなプログラムのメモリ条件に適切に適応するために、HotSpot 仮想マシンでは、オブジェクトを古い世代に昇格させる前に、必ずしもオブジェクトの年齢が -XX:MaxTenuringThreshold に達する必要はありません。 Survivor スペース内の同じ年齢のすべてのオブジェクトのサイズの合計が Survivor スペースの半分より大きい場合、その年齢以上のオブジェクトは、-XX:MaxTenuringThreshold で必要な年齢まで待たずに、直接古い世代に入ることができます。

スペース割り当て保証

マイナー GC が発生する前に、仮想マシンはまず、古い世代で使用可能な連続領域の最大サイズが、新しい世代のすべてのオブジェクトの合計領域よりも大きいかどうかを確認する必要があります。

この記事はWeChatの公開アカウント「運営保守開発ストーリー」から転載したものです。

【編集者のおすすめ】

  1. 鴻蒙公式戦略協力と建設——HarmonyOS技術コミュニティ
  2. クラウド内のコンテナ: どのような選択肢がありますか?
  3. 5Gメッセージングは​​開発段階に入る
  4. ドメインハイジャックとは何ですか?ドメイン名のハイジャックに対処する方法
  5. プログラミングを独学する場合、まずどの言語を選べばいいでしょうか?
  6. ウェブクローラーの完全な歴史

<<:  Pythonの仮想環境は非常に簡単です。これを読めばすぐにわかるでしょう。

>>:  スマートトラベルに焦点を当てたJDリテールクラウドのJDミニプログラムは、人と車のためのフルシナリオエコシステムの構築に役立ちます。

推薦する

2019年有料市場半期レポート:モバイルゲームとゲームライブストリーミングが最も収益性が高い

本日は有料ユーザーに関するレポートをシェアし、各プラットフォームの有料会員の状況や、eコマース以外で...

SaaS は終わりました。ソフトウェアの次は何でしょう?

[[228228]]前世紀の前半には、多くの電気機器が伝統的な手動機器に取って代わり、人々に多大な富...

優れた SEO 担当者になりたいなら、これらをお持ちですか?

SEO スキルや SEO 知識についてはよく話題になりますが、これらは人気があるように思われるかもし...

ウェブサイトを分析する良い習慣を身につけましょう

4月10日の朝、私は会社に到着すると、同僚たちと集まって、あるウェブサイトがどのようにして百度のホー...

ステーショングループ?勝てるかどうかわからない戦いには出かけないでください!

サイト グループを設定する理由については、人それぞれ理由があります。私が説明したい理由は非常に単純で...

WeChat マーケティングに影響を与える主な要因は何ですか?

WeChatマーケティングは長い間非常に人気があり、大規模なユーザーベースを持ち、急速に成長しており...

医療電子商取引が「携帯電話による医薬品購入」モデルを試行

南方日報(記者/趙炳慧)スマートフォンの急速な発展により、医療電子商取引はそこに潜むチャンスに気づき...

外部リンク運用サイクルに影響を与える要因は何ですか?

外部リンクは、ウェブサイトの最適化において非常に重要な要素です。外部リンクは、ウェブサイトの重みを蓄...

優れたネットワークアライアンスプロモーションポジションを定義する方法

ウェブサイトを選択する際、人々は通常、ウェブサイトのトラフィック データ、広告スペースのサイズなど、...

年次レビュー | 2019年のブランドマーケティングの3つのキーワード

はじめに:頻繁なコラボレーション、頻繁な飢餓マーケティング、頻繁なイノベーション、頻繁な限定販売、頻...

Baidu が頻繁に新製品をリリースしていることについての SEO 専門家の推測

2012年はBaiduにとって激動の年であり、私たちウェブマスターにとっても激動の年でした。長年SE...

Weibo でフォロワーを増やす楽しみは無限大。Weibo のトップユーザーによる体験談 - A5 Webmaster Network

みなさんこんにちは!私はテンセント微博の福州精神公社(アカウント番号fzmj5i)の担当者です。最近...

クラウドスキルのギャップはデジタル変革の成功の大きな障壁となっている

SoftwareOne のレポートによると、世界中の企業の 98% がクラウド スキルのギャップに直...

GDPRとクラウドコンピューティング: 知っておくべきこと

欧州からの新しいデータ規制は、クラウド コンピューティングを使用する企業にいくつかの問題を引き起こす...

百度のフェニックスネスト買収で何が起こったかは、フェニックスネストの将来を物語るだろう

私は2009年に百度の入札に接して以来、ずっと百度の入札を観察してきました。詳細に研究したとは言えま...