目次
1. はじめに
2. 古典的な割り当て戦略
1. オブジェクトは最初に Eden に割り当てられます
2. ラージ オブジェクトは古い世代で直接割り当てられます。
3. 長期的に存続するオブジェクトは古い世代に入ります
4. 動的なオブジェクトの経過時間の決定
5. スペース割り当ての保証
3. 一般的に使用される JVM パラメータ設定
4番目、補足
ホームページ Java &#&チュートリアル Java のメモリ割り当てとリサイクル戦略に関する簡単な説明

Java のメモリ割り当てとリサイクル戦略に関する簡単な説明

Jun 26, 2017 am 10:41 AM
java メモリ 配布する リサイクル

1. はじめに

Java テクノロジー システムで言及されている自動メモリ管理は、最終的には 2 つの問題です: メモリ割り当てとリサイクルです。今日は、Java リサイクルの存在についてお話しましょう。メモリ内の Java オブジェクトの割り当て。平たく言えば、オブジェクトのメモリ割り当てはヒープ上の割り当てです。オブジェクトは主に新しい世代の Eden に割り当てられます (メモリ内のオブジェクトの生成はガベージ コレクション中に補充されます)。詳しく知りたい場合は、次のことを確認してください。 「Java 仮想マシンの詳細な理解」も参照してください)。ローカル スレッド割り当てバッファが開始されると、スレッドの優先順位に従って TLAB 上に割り当てられます。場合によっては、古い世代に直接割り当てられることもあります。

2. 古典的な割り当て戦略

1. オブジェクトは最初に Eden に割り当てられます

一般に、Eden に割り当てのための十分なスペースがない場合、jvm はマイナー GC を開始します。それでも十分なスペース割り当てがない場合は、後で説明する他の対策もあります。

仮想マシンの奇数ログパラメータ -XX:+PrintGCDetails を設定すると、ガベージコレクション中にメモリリサイクルログが出力され、プロセス終了時に各メモリ領域の現在の割り当てが出力されます。具体的な例を見てみましょう。まず、jvm パラメータ -Xms20m -Xmx20m -Xmn10m を設定する必要があります。これらの 3 つのパラメータは、Java ヒープ サイズが 20M で、残りの 10M は拡張できないことを示します。古い世代に割り当てられます。 -XX:SurvivorRatio=8 は、新世代の jvm における Eden と Survivor のデフォルトの比率です。デフォルトは 8:1 です。その理由は、新しい世代のオブジェクトの 98% が次の GC でリサイクルされるため、ガベージ コレクションにコピー アルゴリズムを使用するのが非常に適しているためです。そのため、新しい世代の 10M メモリのうち 8M が Eden になります。 1M は Survivor で、残りの 1M は未使用です。コピー アルゴリズムと連携するメモリ ブロックも Survivor です。

 1 public class ReflectTest { 2  3     private static final int _1MB = 1024*1024; 4      5     public static void testAllocation(){ 6         byte[] allocation1 , allocation2 , allocation3 , allocation4; 7         allocation1 = new byte[2 * _1MB]; 8         allocation2 = new byte[2 * _1MB]; 9         allocation3 = new byte[2 * _1MB];10         allocation4 = new byte[6 * _1MB];11     }12     13     public static void main(String[] args) {14         ReflectTest.testAllocation();15     }16     17 }
ログイン後にコピー

出力は次のとおりです

Heap
 PSYoungGen      total 9216K, used 6651K [0x000000000b520000, 0x000000000bf20000, 0x000000000bf20000)
  eden space 8192K, 81% used [0x000000000b520000,0x000000000bb9ef28,0x000000000bd20000)
  from space 1024K, 0% used [0x000000000be20000,0x000000000be20000,0x000000000bf20000)
  to   space 1024K, 0% used [0x000000000bd20000,0x000000000bd20000,0x000000000be20000)
 PSOldGen        total 10240K, used 6144K [0x000000000ab20000, 0x000000000b520000, 0x000000000b520000)
  object space 10240K, 60% used [0x000000000ab20000,0x000000000b120018,0x000000000b520000)
 PSPermGen       total 21248K, used 2973K [0x0000000005720000, 0x0000000006be0000, 0x000000000ab20000)
  object space 21248K, 13% used [0x0000000005720000,0x0000000005a07498,0x0000000006be0000)
ログイン後にコピー

eden が 81% を占めていることがわかり、allocation1、allocation2、allocation3 がすべて新世代 Eden に割り当てられていることを示します。

2. ラージ オブジェクトは古い世代で直接割り当てられます。

ラージ オブジェクトとは、非常に長い文字列や配列と同様に、格納するために大量の連続メモリ領域を必要とするオブジェクトを指します。大きなオブジェクトは仮想マシンのメモリ分散にとって好ましくありません。1 ラウンドしか存続しない大きなオブジェクトが多数発生すると、コードを作成するときにそのような問題を回避する必要があります。 -XX:PretenureSizeThreshold パラメータは、この値より大きいオブジェクトが古い世代に直接割り当てられます。これは、Eden 領域と Survivor 領域の間で大量のメモリがコピーされることを避けるためです。前に述べた リサイクルアルゴリズムとコピーアルゴリズムについては前に述べたので、詳細は説明しません。

public class ReflectTestBig {private static final int _1MB = 1024*1024;    public static void testAllocation(){byte[] allocation2 , allocation3 , allocation4;allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB];
        allocation4 = new byte[6 * _1MB];
    }    public static void main(String[] args) {
        ReflectTestBig.testAllocation();
    }
    
}
ログイン後にコピー

出力は以下の通りです

Heap
 PSYoungGen      total 8960K, used 4597K [0x000000000b510000, 0x000000000bf10000, 0x000000000bf10000)
  eden space 7680K, 59% used [0x000000000b510000,0x000000000b98d458,0x000000000bc90000)
  from space 1280K, 0% used [0x000000000bdd0000,0x000000000bdd0000,0x000000000bf10000)
  to   space 1280K, 0% used [0x000000000bc90000,0x000000000bc90000,0x000000000bdd0000)
 PSOldGen        total 10240K, used 6144K [0x000000000ab10000, 0x000000000b510000, 0x000000000b510000)
  object space 10240K, 60% used [0x000000000ab10000,0x000000000b110018,0x000000000b510000)
 PSPermGen       total 21248K, used 2973K [0x0000000005710000, 0x0000000006bd0000, 0x000000000ab10000)
  object space 21248K, 13% used [0x0000000005710000,0x00000000059f7460,0x0000000006bd0000)
ログイン後にコピー

割り当て4が設定した-XX:PretenureSizeThreshold=3145728を超えており、割り当て4が旧世代に直接割り当てられ、旧世代の占有率が60%になっていることがわかります。 。設定 -XX:PretenureSizeThreshold=3145728 を -XX:PretenureSizeThreshold=3m として記述することはできないことに注意してください。そうしないと、jvm がそれを認識しません。

3. 長期的に存続するオブジェクトは古い世代に入ります

仮想マシンはバンドコレクションの考え方を採用してメモリを管理するため、メモリのリサイクルではどのオブジェクトを新しい世代に配置する必要があるかを特定する必要があります。旧世代に置かれます。この目的を達成するために、jvm はオブジェクトごとに年齢カウンター (Age) を定義します。オブジェクトが Eden で生まれ、最初のマイナー GC を生き延び、Survivor に保存できる場合、そのオブジェクトは Survivor に移動され、オブジェクトの年齢は 1 に設定されます。オブジェクトがマイナー GC をエスケープするたびに、その年齢は 1 ずつ増加します。オブジェクトの年齢がしきい値の 1 年を超えると、オブジェクトは古い世代に昇格します。このしきい値 jvm のデフォルトは 15 で、-XX:MaxTenuringThreshold で設定できます。

   m = 1024 * 1024  [] a1 =  [1 * m / 4[] a2 =  [7 *[] a3 =  [3 * m];
ログイン後にコピー

出力は以下の通りです

[GC [DefNew: 7767K->403K(9216K), 0.0062209 secs] 7767K->7571K(19456K), 0.0062482 secs]   
[Times: user=0.00 sys=0.00, real=0.01 secs]   
a3 ok  
Heap  
 def new generation   total 9216K, used 3639K [0x331d0000, 0x33bd0000, 0x33bd0000)  
  eden space 8192K,  39% used [0x331d0000, 0x334f9040, 0x339d0000)  
  from space 1024K,  39% used [0x33ad0000, 0x33b34de8, 0x33bd0000)  
  to   space 1024K,   0% used [0x339d0000, 0x339d0000, 0x33ad0000)  
 tenured generation   total 10240K, used 7168K [0x33bd0000, 0x345d0000, 0x345d0000)  
   the space 10240K,  70% used [0x33bd0000, 0x342d0010, 0x342d0200, 0x345d0000)  
 compacting perm gen  total 12288K, used 381K [0x345d0000, 0x351d0000, 0x385d0000)  
   the space 12288K,   3% used [0x345d0000, 0x3462f548, 0x3462f600, 0x351d0000)  
    ro space 10240K,  55% used [0x385d0000, 0x38b51140, 0x38b51200, 0x38fd0000)  
    rw space 12288K,  55% used [0x38fd0000, 0x396744c8, 0x39674600, 0x39bd0000)
ログイン後にコピー

a2 は一度生き残っており、その年齢は 1 で、設定 -XX:MaxTenuringThreshold=1 を満たしているため、a2 は古い世代に入り、a3 は新しい世代に入っていることがわかります。

4. 動的なオブジェクトの経過時間の決定

さまざまなプログラムのメモリ状態に適切に適応するために、仮想マシンはオブジェクトの経過時間が -XX:MaxTenuringThreshold で設定された値に達する必要があるとは限りません。 Survivor スペース内の同じ年齢のすべてのオブジェクトのサイズの合計が Survivor スペースの半分より大きい場合、古い世代に昇格する必要はありません。 -XX:MaxTenuringThreshold で設定された値に達しました。

5. スペース割り当ての保証

マイナー GC が発生すると、仮想マシンは古い世代への各昇格の平均サイズが古い世代の残りのスペースより大きいかどうかを検出します。直接実行されます。未満の場合は、HandlerPromotionFailyre 設定で保証失敗が許可されているかどうかを確認します。許可されている場合は、マイナー GC のみが実行されます。許可されていない場合は、FUll GC も改善されます。つまり、新世代 Eden が変更されたオブジェクトを保存できない場合、オブジェクトは旧世代に保存されます。

3. 一般的に使用される JVM パラメータ設定

1. -Xms: 初期ヒープ サイズ、デフォルト (MinHeapFreeRatio パラメータは調整可能) 空きヒープ メモリが 40% 未満の場合、JVM は最大制限までヒープを増加します。 -XMX。

2.

3. -Xmn: 若い世代のサイズ (1.4 または lator)、ここでのサイズは (eden+2 survivor space) であり、jmap -heap で示される新しい世代とは異なります。
ヒープ全体のサイズ = 若い世代のサイズ + 古い世代のサイズ + 永続的な世代のサイズ。
若い世代を増やした後は、古い世代のサイズが減少します。この値は、ヒープ全体の 3/8 の構成をシステムのパフォーマンスに大きく影響します。

4. -XX:NewSize: 若い世代のサイズを設定します (1.3/1.4 の場合)。

5. -XX:MaxNewSize: 若い世代の最大値 (1.3/1.4 の場合)。

6. -XX:PermSize: 永続世代 (perm gen) の初期値を設定します。

7. -XX:MaxPermSize: 永続世代の最大サイズを設定します。

8、-Xss: 各スレッドのスタック サイズ。JDK5.0 以降、各スレッドのスタック サイズは 1M でした。アプリケーション スレッドが必要とするメモリ サイズは 256K でした。同じ物理アンダーメモリでは、この値を減らすとより多くのスレッドを生成できますが、オペレーティング システムにはプロセス内のスレッド数に制限があり、経験値は約 3000 ~ です。 5000。

9、-XX:NewRatio: 古い世代 (永続世代を除く) に対する若い世代 (エデンと 2 つの Survivor エリアを含む) の比率、-XX:NewRatio=4 は、若い世代と古い世代の比率を意味します。古い世代は 1:4、若い世代はスタック全体の 1/5 を占めます。 Xms=XmxかつXmnを設定した場合、本パラメータの設定は不要です。

10、-XX:SurvivorRatio: Eden エリアと Survivor エリアのサイズ比を 8 に設定すると、2 つの Survivor エリアと 1 つの Eden エリアの比率は 2:8 となり、1 つの Survivor エリアは 1/10 を占めます。若い世代全体の。

11. -XX:LargePageSizeInBytes: Perm のサイズに影響を与えるため、メモリ ページのサイズをあまり大きく設定することはできません。

12、-XX:+DisableExplicitGC: System.gc() をオフにします

13、-XX:MaxTenuringThreshold: ガベージの最大存続期間を 0 に設定すると、若い世代のオブジェクトは Survivor 領域を経由せずに直接実行されます。古い世代を多数含むアプリケーションの場合、この値をより大きな値に設定すると、若い世代のオブジェクトが Survivor 領域に複数回コピーされるため、生存時間が長くなる可能性があります。若い世代のオブジェクトの数を増やし、若い世代がリサイクルされる確率。このパラメータはシリアル GC でのみ有効です。

14、-XX:PretenureSizeThreshold: サイズを超える場合、オブジェクトは古い世代に直接割り当てられます。新しい世代が Parallel Scavenge GC を使用する場合、ユニット バイトは無効になります。大きな配列オブジェクト、およびその配列には外部参照オブジェクトがありません。

15、-XX:TLABWasteTargetPercent: eden エリア内の TLAB の割合。

4番目、補足

マイナーGCとフルGCの違い:

新世代GC(マイナーGC):ほとんどのJavaオブジェクトはGCの最初のラウンドを回避できないため、新世代で発生するガベージコレクションアクションを指します。 , そのため、マイナー GC は非常に頻繁に使用され、一般的に回復速度は比較的速いです。

古い世代の GC (FULL GC/Major GC): 古い世代で発生する GC を指します。Major GC が出現する場合、多くの場合、少なくとも 1 つのマイナー GC が伴います (ただし、絶対ではなく、直接 GC に含まれます)。 ParallelScavenge コレクターの収集戦略)、メジャー GC 選択プロセスを実行します。メジャー GC の速度は、通常、マイナー GC よりも 10 倍以上遅くなります。

以上がJava のメモリ割り当てとリサイクル戦略に関する簡単な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

関係者によると、サムスン電子とSKハイニックスは2026年以降に積層型モバイルメモリを商品化する予定 関係者によると、サムスン電子とSKハイニックスは2026年以降に積層型モバイルメモリを商品化する予定 Sep 03, 2024 pm 02:15 PM

9月3日の当ウェブサイトのニュースによると、韓国メディアetnewsは昨日(現地時間)、サムスン電子とSKハイニックスの「HBM類似」積層構造モバイルメモリ製品が2026年以降に商品化されると報じた。関係者によると、韓国のメモリ大手2社はスタック型モバイルメモリを将来の重要な収益源と考えており、エンドサイドAIに電力を供給するために「HBMのようなメモリ」をスマートフォン、タブレット、ラップトップに拡張する計画だという。このサイトの以前のレポートによると、Samsung Electronics の製品は LPwide I/O メモリと呼ばれ、SK Hynix はこのテクノロジーを VFO と呼んでいます。両社はほぼ同じ技術的ルート、つまりファンアウト パッケージングと垂直チャネルを組み合わせたものを使用しました。 Samsung Electronics の LPwide I/O メモリのビット幅は 512

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプ Java での日付までのタイムスタンプ Aug 30, 2024 pm 04:28 PM

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

カプセルの量を見つけるためのJavaプログラム カプセルの量を見つけるためのJavaプログラム Feb 07, 2025 am 11:37 AM

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

See all articles