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の全体的な構造は次のようになります。

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

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

推薦する

SEO はなぜますます混乱を招くのでしょうか?

私は鄭州でほぼ 1 年間働いており、4 ~ 5 か月間 Web サイトの最適化に取り組んできました。...

ワン・ツー・ワン・コードは、新しい小売時代のマーケティングツールであり、ブランド企業の変革に役立ちます。

月収10万元の起業の夢を実現するミニプログラム起業支援プラン自転車に乗るためにコードをスキャンする、...

ニュースと広告を効果的に組み合わせる方法

2012年、インターネットは急速に発展し、ニュースマーケティングはもはやそれほどハイエンドなものでは...

2020 年に IT プロフェッショナルが取得すべき 8 つの優れたクラウド セキュリティ認定資格

認定資格は、セキュリティ専門家が情報セキュリティに関する基礎知識を証明するのに役立ちます。これらの優...

#3angfor# って何だかご存知ですか?

3月13日13時33分、50名を超えるITメディアおよび業界アナリストが北京に集まり、2019年Sa...

8年間の経験、SEOをより効率的にする5つの最適化のヒント

私が誤ってウェブマスターになった2005年から、この8年間は何度か経過しましたが、私はインターネット...

エッジコンピューティングと5Gがパンデミック後の経済回復を推進

[[429757]]エッジコンピューティングと5GはCOVID-19後の経済成長を牽引するでしょうか...

タオバオがバーチャルスーパーマーケット「Buy Convenience」をオープン、インパクトNo.1店舗に

昨日、タオバオの「買物便利」(24.taobao.com)が正式に開始され、北京と杭州が最初の試験運...

中国のバレンタインデーの観点から見たオンラインマーケティング

毎年恒例の七夕祭りがまたやって来ました。朝、仕事に出かけると、街のいたるところで大きなバラの花束を持...

私は 400 件以上のブログ記事を書いています。なぜ SEO ブログの更新にこだわるのか、その理由をお話ししましょう。

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますこれまでに...

SAP、Humi.com、重慶ハイテクゾーンが共同で「重慶中小企業インテリジェントエンパワーメントセンター」を建設

最近、SAPはHumi.comおよび重慶ハイテクゾーンと三者戦略提携を結び、「重慶中小企業インテリジ...

2019 年のクラウド コンピューティング?待ってください、まずはこの3つの課題に備えてください

クラウド セキュリティやコンプライアンスなどの要素は、長年にわたって IT チームに課題をもたらして...

ビッグデータとクラウドコンピューティングが企業ネットワークを圧倒

海外メディアの報道によると、今日、企業ネットワークはますます大きな圧力にさらされている。企業は新しい...

ベテランウェブマスターがウェブサイトの単一ページを最適化する方法を教えます

どのようなウェブサイトであっても、それは間違いなくページから構成される全体です。ウェブサイト全体の重...

私たちの支払い方法はWeChatの影響を受け始めているのでしょうか?

滴滴出行と快滴行のタクシー配車アプリへの補助金が意味をなさなくなると、その背後にある2つのインターネ...