***
以前の記事では、jvmのメモリモデルとゴミ回収メカニズムについて説明しましたが、この記事では、いくつかのJVMのオブジェクトがメモリの割り当てに従うべきポリシーについて説明します.結局,プログラムを最適化するには,ごみ回収の過程だけでなく,オブジェクトメモリの割り当ての観点からgcの代価を減らす必要がある.
一、gcログフォーマット
ここではまずgcログのフォーマットを紹介し、gcログを分析することはgcプロセスを理解する最も直接的な方法である.大量のログ分析に対して、直接ログファイルを見るのはもちろん不便で、私たちは一般的にログ分析ツールを使って、後で紹介しますが、短いログ(十数条など)に対しては、一般的に直接見ればいいです.ログ出力を有効にするJVMパラメータは次のとおりです.
対応するログ出力フォーマットは次のとおりです(異なるパラメータまたは異なる仮想マシンで異なる場合がありますが、ほとんど同じです).
2014-03-09T18:10:47.639+0800: 36.408: [GC 36.408: [DefNew: 35072K->4352K(39424K), 0.0108988 secs] 75088K->45293K(126848K), 0.0109419 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 2014-03-09T18:10:48.562+0800: 37.331: [Full GC 37.343: [Tenured: 40941K->42890K(87424K), 0.1340821 secs] 62210K->42890K(126848K), [Perm : 36863K->36863K(36864K)], 0.1341736 secs] [Times: user=0.13 sys=0.00, real=0.15 secs]
35072 K->4352 K(39424 K):gcの前にメモリサイズを使用->gcの後にサイズを使用(この領域の合計サイズ) 2014-03-09 T 18:10:47.639+0800:gc時間 36.408: gc消費時間 GC 36.408: 停止タイプと停止時間を表し、FullであればgcがStop-The-worldであることを表す. DefNew: Tenured: Perm : gcが発生した地域、DefNewの若者;Tenuredの年老いた世代;Perm永続世代 Times: user=0.13 sys=0.00, real=0.15 secs user:ユーザー状態に時間がかかる;Sys:カーネル状態に時間がかかる;real:gc消費開始から終了までのWall Clock Time消費時間(壁時計、名前がおかしい、各種非演算の待機時間とcpu消費時間を含む)
二、メモリ分配策略
1、対象はEdenに優先的に割り当てる
新しいオブジェクトの多くはEdenで割り当てられます.これにより、Eden領域に十分なスペースがない場合、JVMはまずMinor Gcを行い、Edenのみをgcし、条件に合致するオブジェクトを年老いた世代に移動します.これにより,Edenがgc後に新しいオブジェクトの空間的要件を満たすと,Full GCを回避できる.
2、大きい相手は直接年老いた世代に入る
この点はよく理解され、多くの場合、大きなオブジェクトのライフサイクルは比較的長いが、大きなオブジェクトがEdenに割り当てられると、大量の空間を占有するだけでなく、gcをトリガするだけでなく、Eden領域/2つのSurvivor領域の間で回復し、リソースを消費する可能性がある.したがって、多くの場合、大きなオブジェクトについては、年老いた世代に直接割り当てるべきであり、-X:PertenuesizeThresholdパラメータを使用して年老いた世代に直接割り当てるサイズを指定し始めます.
3、長期生存の対象は年老いた世代に入る
一般的に何度もミノルGCを経て死なない相手は、生き続ける可能性がもっと大きいので、年老いた世代に入るべきだ.どのオブジェクトが長期にわたって生存しているかを判断するために、仮想マシンは各オブジェクトにAgeカウンタを定義し、一度もMinor GCを経験せずに+1し、-XX:MaxTenuringThresholdの値によってageがどれだけの年齢に入るかを決定することができます.
4、動的対象年齢判断
異なるプログラムのメモリ状況に適応するために、仮想マシンは常にオブジェクトの年齢がMaxTenuringThresholdに達しなければ古い年代を昇進できないことを要求するわけではありません.Survivor空間で同じ年齢のすべてのオブジェクトのサイズの総和がSurvivor空間の半分より大きく、その年齢以上のオブジェクトが直接古い年代に入ることができます.MaxTenuringThresholdで要求される年齢まで待つ必要はありません.
5、空間配分保証
Minor GCが発生した場合,仮想機会検出の前に古い年代に昇格するたびの平均サイズが古い年代の残りの空間サイズより大きいかどうか,より大きい場合は直接Full GCに変更する.より小さい場合は、HandlePromotionFailureの設定が保証に失敗することを許可しているかどうかを確認します.許可されれば、Minor GCしか行われません.許可しない場合は、フルGCも1回行うように変更します. 前述したように、新生世代はレプリケーション収集アルゴリズムを使用するが、メモリ使用率のために1つのSurvivor空間のみをローテーションバックアップとして使用するため、Minor GC後も多数のオブジェクトが生存している場合(最も極端にはメモリ回収後に新生世代に存在するオブジェクトが生存している場合)には、古い世代の割り当て保証が必要となる.Survivorが収容できない対象を直接古い年代に入れる.生活の中のローン保証と同様に、古い年代はこのような保証を行い、古い年代自体にこれらの対象を収容する余剰スペースがあることを前提とし、全部でどれだけの対象が生き残るかは、実際にメモリ回収を完了するまでは明確に分からないので、以前の回収ごとに古い年代の対象容量に昇進した平均サイズ値を経験値として取るしかない.旧世代の余剰空間と比較し,Full GCを行って旧世代により多くの空間を空けるかどうかを決定する.
本編では、JVMモニタリングに関するツールについて説明します.
一、gcログフォーマット
ここではまずgcログのフォーマットを紹介し、gcログを分析することはgcプロセスを理解する最も直接的な方法である.大量のログ分析に対して、直接ログファイルを見るのはもちろん不便で、私たちは一般的にログ分析ツールを使って、後で紹介しますが、短いログ(十数条など)に対しては、一般的に直接見ればいいです.ログ出力を有効にするJVMパラメータは次のとおりです.
-XX:+PrintGCDetails // gc
-XX:+PrintGCDateStamps //
-Xloggc:gc.log //
対応するログ出力フォーマットは次のとおりです(異なるパラメータまたは異なる仮想マシンで異なる場合がありますが、ほとんど同じです).
2014-03-09T18:10:47.639+0800: 36.408: [GC 36.408: [DefNew: 35072K->4352K(39424K), 0.0108988 secs] 75088K->45293K(126848K), 0.0109419 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 2014-03-09T18:10:48.562+0800: 37.331: [Full GC 37.343: [Tenured: 40941K->42890K(87424K), 0.1340821 secs] 62210K->42890K(126848K), [Perm : 36863K->36863K(36864K)], 0.1341736 secs] [Times: user=0.13 sys=0.00, real=0.15 secs]
35072 K->4352 K(39424 K):gcの前にメモリサイズを使用->gcの後にサイズを使用(この領域の合計サイズ) 2014-03-09 T 18:10:47.639+0800:gc時間 36.408: gc消費時間 GC 36.408: 停止タイプと停止時間を表し、FullであればgcがStop-The-worldであることを表す. DefNew: Tenured: Perm : gcが発生した地域、DefNewの若者;Tenuredの年老いた世代;Perm永続世代 Times: user=0.13 sys=0.00, real=0.15 secs user:ユーザー状態に時間がかかる;Sys:カーネル状態に時間がかかる;real:gc消費開始から終了までのWall Clock Time消費時間(壁時計、名前がおかしい、各種非演算の待機時間とcpu消費時間を含む)
二、メモリ分配策略
1、対象はEdenに優先的に割り当てる
新しいオブジェクトの多くはEdenで割り当てられます.これにより、Eden領域に十分なスペースがない場合、JVMはまずMinor Gcを行い、Edenのみをgcし、条件に合致するオブジェクトを年老いた世代に移動します.これにより,Edenがgc後に新しいオブジェクトの空間的要件を満たすと,Full GCを回避できる.
2、大きい相手は直接年老いた世代に入る
この点はよく理解され、多くの場合、大きなオブジェクトのライフサイクルは比較的長いが、大きなオブジェクトがEdenに割り当てられると、大量の空間を占有するだけでなく、gcをトリガするだけでなく、Eden領域/2つのSurvivor領域の間で回復し、リソースを消費する可能性がある.したがって、多くの場合、大きなオブジェクトについては、年老いた世代に直接割り当てるべきであり、-X:PertenuesizeThresholdパラメータを使用して年老いた世代に直接割り当てるサイズを指定し始めます.
3、長期生存の対象は年老いた世代に入る
一般的に何度もミノルGCを経て死なない相手は、生き続ける可能性がもっと大きいので、年老いた世代に入るべきだ.どのオブジェクトが長期にわたって生存しているかを判断するために、仮想マシンは各オブジェクトにAgeカウンタを定義し、一度もMinor GCを経験せずに+1し、-XX:MaxTenuringThresholdの値によってageがどれだけの年齢に入るかを決定することができます.
4、動的対象年齢判断
異なるプログラムのメモリ状況に適応するために、仮想マシンは常にオブジェクトの年齢がMaxTenuringThresholdに達しなければ古い年代を昇進できないことを要求するわけではありません.Survivor空間で同じ年齢のすべてのオブジェクトのサイズの総和がSurvivor空間の半分より大きく、その年齢以上のオブジェクトが直接古い年代に入ることができます.MaxTenuringThresholdで要求される年齢まで待つ必要はありません.
5、空間配分保証
Minor GCが発生した場合,仮想機会検出の前に古い年代に昇格するたびの平均サイズが古い年代の残りの空間サイズより大きいかどうか,より大きい場合は直接Full GCに変更する.より小さい場合は、HandlePromotionFailureの設定が保証に失敗することを許可しているかどうかを確認します.許可されれば、Minor GCしか行われません.許可しない場合は、フルGCも1回行うように変更します. 前述したように、新生世代はレプリケーション収集アルゴリズムを使用するが、メモリ使用率のために1つのSurvivor空間のみをローテーションバックアップとして使用するため、Minor GC後も多数のオブジェクトが生存している場合(最も極端にはメモリ回収後に新生世代に存在するオブジェクトが生存している場合)には、古い世代の割り当て保証が必要となる.Survivorが収容できない対象を直接古い年代に入れる.生活の中のローン保証と同様に、古い年代はこのような保証を行い、古い年代自体にこれらの対象を収容する余剰スペースがあることを前提とし、全部でどれだけの対象が生き残るかは、実際にメモリ回収を完了するまでは明確に分からないので、以前の回収ごとに古い年代の対象容量に昇進した平均サイズ値を経験値として取るしかない.旧世代の余剰空間と比較し,Full GCを行って旧世代により多くの空間を空けるかどうかを決定する.
本編では、JVMモニタリングに関するツールについて説明します.