JVM仮想マシンの全体構造とオブジェクトメモリ割り当ての分析

JVM仮想マシンの全体構造とオブジェクトメモリ割り当ての分析

[[414275]]

JVM仮想マシンの全体構造の分析

全体構造の紹介

  • jvm は次のように分かれています:
  • -スタックメソッド領域ヒープローカルメソッドスタックプログラムカウンタ

スタック

スタックは JVM の重要な部分です。新しいスレッドごとに、JVM はスタック上にメモリを割り当てます。スレッドにはスタック フレームとプログラム カウンターがあります。さらに、スレッド スタック メモリのサイズによってスレッドの数が決まります。スレッド スタック メモリ サイズを大きく設定すると、同時に存在できるスレッドの数は少なくなり、逆もまた同様です。さらに、スタック内で最も一般的なエラーは StackOverflowError です。次のコードを参照してください。

  1. パブリッククラスStackOverflowTest {
  2. 静的 整数 カウント= 0;
  3. 静的void redo() {
  4. カウント++;
  5. やり直し();
  6. }
  7. 公共 静的void main(String[] args) {
  8. 試す {
  9. やり直し();
  10. } キャッチ (Throwable t) {
  11. t.printStackTrace();
  12. System.out .println ( count );
  13. }
  14. }
  15. }
  16. 操作結果:
  17. java.lang.StackOverflowError

パラメータの影響: -Xss 256KB (デフォルト 1M) スタック サイズを設定します。スタックのサイズはカウント数に影響します。 -Xss で設定されたサイズが大きいほど、カウント数も大きくなり、逆もまた同様です。

スタックフレーム構造

ローカル変数テーブル: 主に宣言されたローカル変数とメソッド パラメーター情報を保存するために使用されます。ローカル変数テーブルは現在のメソッドに対して作用します。メソッドが実行されると、メモリを解放するためにローカル変数テーブルも削除されます。また、ローカル変数テーブルは、変数スロットと呼ばれる情報を格納するために使用されます。

オペランド スタック: 名前が示すように、オペランド スタックは本質的にはスタックであり、プッシュとポップの 2 つの操作があります。たとえば、a+b を実行するには、まずローカル変数テーブル内の a と b をそれぞれスタックにプッシュし、次に加算演算を実行し、最後にスタックをポップします。

動的リンク: プログラム実行中にシンボリック参照を直接参照に置き換えることを動的リンクと呼びます。動的リンクが存在するので、当然、静的リンクも存在します。一部のシンボリック参照は、クラスのロード フェーズ (解析) 中に直接参照に変換されます。この変換は静的リンクと呼ばれます。

メソッドの戻りアドレス: メソッドが終了した後 (通常実行/例外的な戻り)、メソッドが呼び出された場所に戻ります。

スタック構造図


プログラムカウンタレジスタ

プログラム カウンター (PC レジスタとも呼ばれます) は、JVM の非常に重要な構造です。これはスレッドプライベートであり、各スレッドには独自のコピーがあります。次に実行される命令のアドレスを格納するために使用されます。たとえば、スレッドがブロックされてから起動されると、命令のアドレスがプログラム カウンターから読み取られ、実行が続行されます。

ネイティブメソッドスタック

ローカル メソッド スタックは主にネイティブ メソッドの実行とネイティブ メソッド エントリ領域のアドレスの保存に使用されるため、ローカル メソッド スタックもスレッド専用のメモリ領域です。

メソッド領域(メタスペース)

すべてのスレッドで共有されます。メソッド領域には、すべてのクラス変数と静的変数、クラスメソッドコード、変数名、メソッド名、アクセス権限、戻り値が含まれており、よく話題になる定数プールとランタイム定数プールもすべてメソッド領域にあります。

ヒープ

ヒープは、ほぼすべての(すべてではない)オブジェクトを管理する非常に重要な領域です。私たちがよく話題にするガベージコレクションの主な領域は、この領域で発生します。ヒープは若い世代と古い世代に分かれています。若い世代はエデンとサバイバーのエリアに分かれています。サバイバーエリアは、From エリアと To エリアに分かれています。これらの領域には Java オブジェクトが格納されます。領域のメモリが不足するとGCが発生します。 GC には、マイナー GC (Young GC) とフル GC の 2 つの主な種類があります。 JVM チューニングでは、主にコードに応じて JVM パラメータを調整し、Full GC の数を減らします。

ヒープ構造図


脱出分析

まず、皆さんが一番よく耳にするのは、新しいオブジェクトはヒープ内に格納されるということですが、上記のテキストでは、ほぼすべてのオブジェクトがヒープ内に存在すると書かれています。では、なぜほぼそうなるのでしょうか?一部のオブジェクトがスタックに格納されているためです。すごいと思いませんか?次に、次のコードを見てみましょう。

  1. // 方法 1
  2. パブリックPersontest1() {
  3. Person person = 新しい Person();
  4. 1. ユーザIDを設定します。
  5. 帰国
  6. }
  7. // 方法 2
  8. パブリックボイドtest2() {
  9. ユーザーperson = 新しい person();
  10. 1. ユーザIDを設定します。
  11. }

上記のコードから、test1 メソッドの personr オブジェクトが返されるため、このオブジェクトが他のメソッドによって参照される可能性があることがわかります。 test2 メソッドの personr オブジェクトは、メソッドの終了時には無効なオブジェクトとなり、他の場所では参照されません。このようなオブジェクトの場合、JVM はそれをスタック メモリに割り当てます。これにより、メソッドの終了時にスタック メモリとともにリサイクルされ、ヒープ メモリのリサイクルが削減されます。この場合、JVM はエスケープ分析パラメータ (-XX:+DoEscapeAnalysis) をオンにすることで、オブジェクト メモリの割り当て場所を最適化できます。 JDK7 以降では、エスケープ分析がデフォルトでオンになっています。オフにしたい場合は、パラメータ(-XX:-DoEscapeAnalysis)を使用します。

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

オブジェクトメモリ割り当てフローチャート


オブジェクトスタックの割り当て

すべてのオブジェクトがメモリ内に割り当てられるわけではありません。いくつかのオブジェクトはスタック上に割り当てられます。この場合、JVM は、エスケープ解析パラメータ (-XX:+DoEscapeAnalysis) をオンにすることで、スカラー置換 (スタックへの割り当て) によってスタック上に優先的に割り当てられるように、オブジェクトのメモリ割り当て場所を最適化できます。 JDK7 以降では、エスケープ分析がデフォルトでオンになっています。オフにしたい場合は、パラメータ(-XX:-DoEscapeAnalysis)を使用します。

スカラー置換: エスケープ分析により、オブジェクトが外部からアクセスされず、さらに分解できると判断された場合、JVM はオブジェクトを作成しません。代わりに、オブジェクトのメンバー変数をこのメソッドで使用される複数のメンバー変数に分解し、置き換えます。これらの置き換えられたメンバー変数はスタック フレームまたはレジスタ上にスペースを割り当てるため、連続したスペースの大きなブロックが不足しているためにオブジェクト メモリの割り当てが不十分になることがありません。

JDK7 以降ではデフォルトで有効になっているスカラー置換パラメータ (-XX:+EliminateAllocations) を有効にします。

スカラーと集合量: スカラーはそれ以上分解できない量、またはそれ以上分解できない原子量であると言えます。 JAVA の基本データ型はスカラー (int、long などの基本データ型や参照型など) です。スカラーの反対はさらに分解できる量であり、この種の量は総量と呼ばれます。 JAVA では、オブジェクトはさらに分解できる集合体です。

結論: スタック割り当てはエスケープ解析とスカラー置換に依存している

オブジェクトはエデンエリアに割り当てられます

オブジェクトが作成された直後は、Eden 領域に割り当てられます。エデン領域がいっぱいになると、マイナー GC がトリガーされます。オブジェクトの 99% 以上がガベージ コレクションされ、残りの生き残ったオブジェクトは空のサバイバー領域に移動されます。次にエデン領域がいっぱいになると、マイナー GC が再度トリガーされ、エデン領域とサバイバー領域のガベージ オブジェクトが収集され、残りのサバイバー オブジェクトが別の空のサバイバー領域に一度に移動します。新しい世代のオブジェクトの寿命値と生存時間は非常に短いため、JVM のデフォルトの比率 8:1:1 は非常に合理的な比率値です。したがって、エデンエリアを可能な限り大きくし、サバイバーエリアを十分な大きさにする必要があります。

JVM にはデフォルトでこのパラメータ -XX:+UseAdaptiveSizePolicy (デフォルトで有効) があり、これにより 8:1:1 の比率が自動的に変更されます。

この比率を変えたくない場合は、パラメータを設定できます

-XX:-UseAdaptiveSizePolicy

エデンエリアのメモリが不足するとどうなりますか?

新しいオブジェクトにメモリを割り当てるときに、Eden 領域のメモリがほぼ完全に割り当て済みで、割り当てに十分な Eden 領域がない場合、仮想マシンはマイナー GC を開始します。 GC 中に、仮想マシンは新しいオブジェクトを Survior スペースに格納できないことを検出するため、事前に新しい世代のオブジェクトを古い世代に転送する必要があります。古い世代のスペースは新しいオブジェクトを格納するのに十分であるため、Full GC は発生しません。マイナー GC を実行した後、後で割り当てられたオブジェクトが eden 領域に格納できる場合は、引き続き eden 領域にメモリが割り当てられます。

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

ラージ オブジェクトとは、大量の連続したメモリ領域を必要とするオブジェクトです (例: 文字列、配列)。 JVMパラメータ

-XX:PretenureSizeThreshold は大きなオブジェクトのサイズを設定できます。オブジェクトが設定されたサイズを超えた場合、オブジェクトは直接古い世代に入り、若い世代には入りません。このパラメータは、Serial および ParNew コレクターでのみ有効です (コレクターについては後で説明します)。

たとえば、JVM パラメータの設定:

-XX:PretenureSizeThreshold=1000000 (バイト単位) -XX:+UseSerialGC に設定し、大きなオブジェクトを含むプログラムを実行すると、大きなオブジェクトが直接古い世代に配置されることがわかります。

これを実行するとどのような利点がありますか?

これは、大きなオブジェクトにメモリを割り当てるときにコピー操作の非効率性を回避するためです。

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

仮想マシンはメモリの管理に世代別コレクションの考え方を採用しているため、メモリがリサイクルされるときにどのオブジェクトを新しい世代に配置し、どのオブジェクトを古い世代に配置するかを識別できる必要があります。これを実現するために、仮想マシンは各オブジェクトにオブジェクト経過時間カウンターを付与します。オブジェクトが Eden で生成され、最初の Minor GC を通過した後も存続でき、Survivor スペースに収容できる場合、そのオブジェクトは Survivor スペースに移動され、オブジェクトの年齢は 1 に設定されます。オブジェクトが Survivor で MinorGC を存続するたびに、その年齢は 1 年増加します。経過年数が一定のレベル (デフォルトでは 15 年、CMS コレクターの場合はデフォルトで 6 年、ガベージ コレクターによって若干異なります) に達すると、古い世代に昇格されます。オブジェクトは古い世代に昇格されます

年齢の閾値。

JVM パラメータ設定 -XX:MaxTenuringThreshold 。

物体の動的年齢判定

オブジェクトが現在配置されている Survivor 領域 (領域の 1 つ、オブジェクトが配置されている領域) で、オブジェクトのバッチの合計サイズがこの Survivor 領域のメモリ サイズを超えています。

50% (-XX:TargetSurvivorRatio を指定できます) の場合、このオブジェクトのバッチの最大年齢以上のオブジェクトは、直接古い世代に入ることができます。

例えば、生存者エリアに多数のオブジェクトがあり、年齢1+年齢2+年齢nの複数の年齢オブジェクトの合計が生存者エリアの50%を超える場合、

n (含む) より古いすべてのオブジェクトを古い世代に配置します。このルールは、実際には長期間存続する可能性のあるオブジェクトができるだけ早く古い世代に入ることを期待しています。オブジェクトダイナミック年

年齢判定メカニズムは、通常、マイナーGCの後に起動されます。

旧世代のスペース割り当て保証メカニズム

若い世代の各マイナー GC の前に、JVM は古い世代に残っている使用可能なスペースを計算します。この利用可能なスペースが、若い世代に存在するすべてのオブジェクト(ガベージオブジェクトを含む)のサイズの合計よりも小さい場合は、「

-XX:-HandlePromotionFailure" (jdk1.8 ではデフォルトで設定) パラメータが設定されています。このパラメータが設定されている場合、各マイナー GC 後に古い世代の使用可能なメモリ サイズが古い世代に入ったオブジェクトの平均サイズより大きいかどうかがチェックされます。前の手順の結果が上記のパラメータより小さい場合、または設定されていない場合は、古い世代と若い世代のガベージを一緒にリサイクルするためにフル GC がトリガーされます。コレクションの後でも新しいオブジェクトを格納するのに十分なスペースがない場合は、「OOM」が発生します。もちろん、マイナー GC 後に古い世代に移動する必要がある残りの存続オブジェクトのサイズが古い世代の使用可能なスペースよりもまだ大きい場合は、フル GC がトリガーされます。フル GC 後にマイナー GC 後に存続オブジェクト用のスペースがまだない場合は、「OOM」が発生します。

要約する

  1. ランタイム データ領域は、主にヒープ、スタック、プログラム カウンター、メソッド領域、ローカル メソッド スタックで構成されます。
  2. スレッドプライベート領域: スレッド スタック、プログラム カウンター、ローカル メソッド スタック。スレッド共有領域: ヒープ、メソッド領域。
  3. ヒープは、新しい世代(Eden、survivor(From、To)のデフォルト比率は8:1:1)、古い世代に分割されます。
  4. すべてのオブジェクトがヒープ内にあるわけではありません。脱出後に条件を満たすオブジェクトはスタック内にあります。
  5. JVMの全体的な構造は次のようになります。

<<:  世界初の「クラウドネイティブ」量子チップ設計サービスクラウドプラットフォームがリリース

>>:  カフカについて話しましょう!

推薦する

中国のモバイルインターネットサーファー:剣を抜き、混乱した心で周囲を見回す

中国のモバイルインターネット分野にはビジネスモデルの革新者が不足していないが、革新者に追随する模倣者...

新しい消費者保護法により、オンラインショッピングの返品手続きが困難に。オンラインストアは依然として理由のない返品は受け付けないとしている。

新華網長春5月3日(記者 趙孟卓)新しい消費者保護法が施行されて1か月以上が経過した。多くのオンライ...

電子商取引のトレンド分析: モバイル、ソーシャル、垂直市場の台頭

ベンチャーキャピタル会社メイフィールド・ファンドは30億ドル以上の資金を管理しており、その投資分野に...

インターネットマーケティングを学ぶ方法(パート2)

インターネットマーケティングを学ぶ方法(パート2)前回の記事「インターネット マーケティングの学習は...

ウェブマスターネットワークニュース:51 Fanli.comのキャッシュバック方式が批判され、Sinaはポルノで510万元の罰金を科せられた

1. 51Fanli.comのキャッシュバック方式は批判され、79万元全額を換金するには12年かかる...

ビッグデータの 5 つの課題を克服する - クラウドが答えを持っている

組織は、ビッグデータイニシアチブの実装で課題に直面すると、落胆することがよくあります。ビッグ データ...

digital-vm: シンガポールの 10Gbps 帯域幅 VPS レビュー、月間 20T トラフィック、データ更新予定

digital-vm の日本のデータセンターで 10Gbps 帯域幅の VPS をテストした後 (d...

クラウド移行の課題と利点は何ですか?

クラウドコンピューティング技術企業の IT リソースをクラウドに移行する理由は、3 つの柱に基づいて...

メインサイトが含まれる前にセカンダリドメイン名を拡張することは、自ら墓穴を掘ることです

インターネット上のドメイン名の価格は非常に安定しています。一般的に、.comドメイン名の登録価格は5...

クラウド管理はIT部門にとって次の大きな課題となる

調査会社 Gartner は毎年、グローバル マジック クアドラント評価で、世界のパブリック クラウ...

オンライン外国語教育ウェブサイトMemriseが110万ドルの資金調達を完了

2月17日の海外メディアの報道によると、オンライン言語学習コミュニティのMemriseは本日、110...

Kube-vip を使用して高可用性の Kubernetes クラスターを構築する (フル バージョン)

[[422792]]前回のコースのクラスターはシングルマスター クラスターであり、実稼働環境にはリス...

dotvps-限定版低価格 UK KVM-1g メモリ 7 ドル

dotvps.co は 2011 年に設立されました。ダラス、シカゴ、ニューヨーク、メイデンヘッド ...