JVMソース分析のjstatツールの原理は完全に解読します。
6881 ワード
概要
jstatはhotspotが持っている道具です。javaと同じ
jstat皆さんがたくさん使っていますが、よく使われているのはjstat-gcutilです。出力は以下の通りです。
jstatはどのようにこれらの変数の値を取得しますか?
変数値は明らかにターゲットプロセスから取得されましたが、どうやって来ましたか?local socketですか?それともmemory shareですか?実は共有ファイルから来ました。このファイルはPerfDataといいます。主にtmp/hsperfdata_/このファイル
PerfDataファイル
ファイルの作成
このファイルが存在するかどうかは二つのパラメータ、一つはUsePerfData、もう一つはPerf DisplaleShardMem、もし設定されたら-XX:+Perf DisplaleShardMemまたは-XX:-UsePerfData、このファイルは存在しません。デフォルトではPerfDiscleShardMemはクローズされています。UsePerfDataとPerfDispable SharedMemの二つのパラメータについてここで説明します。 UsePerfData:UsePerfDataというパラメータをオフにしたら、jvm起動中にperf memoryは作成されません。jvm運転中にこれらの性能データは保存されません。デフォルトはオープン です。 PerfDiscable ShardMem:このパラメータはPerfDataを記憶するメモリが共有できるかどうかを決定しています。つまり、このパラメータ設定が設定されていないにもかかわらず、jvmは起動時には一つのメモリを割り当ててPerfDataを保存します。このPerfDataは他のプロセスで見られる問題ではないです。このパラメータを設定したら、共有できないと説明します。この時、他のプロセスはこのメモリにアクセスできなくなります。例えば、jps、jstatなどは仕事ができません。デフォルトでは、このパラメータは閉じられています。すなわち、デフォルトサポート共有方式 具体的なコードはPerfメモリにあります。memoryレギオンに
このファイルはいつ削除されますか?通常、プロセスが終了すると自動的に削除されますが、いくつかの極端な状況では、例えば、Kill-9は、この信号jvmをキャプチャすることはできませんので、直接にプロセスを終了し、いくつかの終わりの作業をしていない場合、プロセスはなくなっていますが、このファイルはまだ存在します。このファイルはずっと残していますか?人為的な削除を待つしかないです。jvmではこのような状況を考慮して、現在のユーザーの次のいずれかのjavaプロセス(例えば、jpsを実行します)が起きた時に判断します。下のプロセスファイルは、プロセスがまだ存在するかどうかを確認し、存在しない場合は直接にファイルを削除し、存在するかどうかを判断する具体的な操作は、実際には、キル-0の信号を送信します。異常があるかどうかを確認します。
ファイルの更新
このファイルはmmapによってメモリにマッピングされていますが、jstatは直接DirectByteBufferによってPerfDataから読み込まれていますので、メモリの値が変わったら、jstatから見た値が変化します。メモリの値はいつ変化しますか?つまり、50 msに一度の値を更新すると、ほぼリアルタイムと考えられます。
PerfDataその他の関連VMパラメータ-XX:PerfData MemorySize:指定/tmp/hsperfdata_下のperfDataファイルのサイズは、デフォルトでは32 KBです。ユーザーがこの値を設定すると、jvmで自動的にOSのpage sizeと整列します。例えば、linuxでpagesizeがデフォルトでは4 KBです。31 KBを設定すると、自動的に32 KB が割り当てられます。-XX:+PerfData SaveToFile:プロセスが終了した時にPerfDataの中のデータを特定のファイルに保存するかどうか、ファイルパスは下記のパラメータで指定されます。そうでなければ、現在のディレクトリの下に -XX:PerfData SaveFile:PerfDataファイルを保存するパス を指定します。
jstatの穴
私がしばらく考えていた二つの大きな穴:回正常なBackground CMS GCを発見した後、FGCの値を2回追加しました。CMSにはinit markとremarkがあり、両方のアプリケーションを一時停止する段階があります。また、oldにgcを行うので、 を2回も計算しました。 JDK 8におけるメタスペースの使用状況は正確ではありません。例えば、CCSCの値はCommpresed Class Space Capacityを表しています。しかし、この値の計算はreerveの値ではないことが分かりました。だから、metaspaceは実用的で少ないことが分かります。したがって、この場合は、それらの値をjmxで取って計算したほうがいいです。
おすすめの読書:
ビッグデータの中台のKafkaは、いったいどこがいいですか?
JVMパラメータによる頻繁なCMS GC
jstatはhotspotが持っている道具です。javaと同じ
JAVA_HOME/bin
の下にもあります。このツールを通じて、現在のプロセスのgc、compler、class、memoryなどの関連状況をリアルタイムで知ることができます。具体的にはjstat -options
を通して、どのタイプのデータをサポートしているのか、例えばJDK 8の下の結果を見てみます。-class-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation
jstatの出力jstat皆さんがたくさん使っていますが、よく使われているのはjstat-gcutilです。出力は以下の通りです。
~ ᐅ jstat -gcutil 692 1000
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 41.49 59.79 83.66 89.92 78.74 295 5.436 10 3.855 9.291
0.00 41.49 59.80 83.66 89.92 78.74 295 5.436 10 3.855 9.291
0.00 41.49 59.80 83.66 89.92 78.74 295 5.436 10 3.855 9.291
0.00 41.49 59.80 83.66 89.92 78.74 295 5.436 10 3.855 9.291
0.00 41.49 59.80 83.66 89.92 78.74 295 5.436 10 3.855 9.291
各列はどのように定義されていますか?どのように計算されていますか?実はtools.jarにjstat_というファイルがあります。optionsでは、このファイルには上の各タイプの出力結果が定義されています。例えば、gcutilです。option gcutil {
column {
header "^S0^" /* Survivor 0 Space - Percent Used */
data (1-((sun.gc.generation.0.space.1.capacity - sun.gc.generation.0.space.1.used)/sun.gc.generation.0.space.1.capacity)) * 100
scale raw
align right
width 6
format "0.00"
}
column {
header "^S1^" /* Survivor 1 Space - Percent Used */
data (1-((sun.gc.generation.0.space.2.capacity - sun.gc.generation.0.space.2.used)/sun.gc.generation.0.space.2.capacity)) * 100
scale raw
align right
width 6
format "0.00"
}
column {
header "^E^" /* Eden Space - Percent Used */
data (1-((sun.gc.generation.0.space.0.capacity - sun.gc.generation.0.space.0.used)/sun.gc.generation.0.space.0.capacity)) * 100
align right
scale raw
width 6
format "0.00"
}
column {
header "^O^" /* Old Space - Percent Used */
data (1-((sun.gc.generation.1.space.0.capacity - sun.gc.generation.1.space.0.used)/sun.gc.generation.1.space.0.capacity)) * 100
align right
scale raw
width 6
format "0.00"
}
column {
header "^M^" /* Metaspace Space - Percent Used */
data (1-((sun.gc.metaspace.capacity - sun.gc.metaspace.used)/sun.gc.metaspace.capacity)) * 100
align right
width 6
scale raw
format "0.00"
}
column {
header "^CCS^" /* Compressed Class Space Space - Percent Used */
data (1-((sun.gc.compressedclassspace.capacity - sun.gc.compressedclassspace.used)/sun.gc.compressedclassspace.capacity)) * 100
align right
width 6
scale raw
format "0.00"
}
column {
header "^YGC^" /* Young Generation Collections */
data sun.gc.collector.0.invocations
align right
width 6
format "0"
}
column {
header "^YGCT^" /* Young Generation Collection Time */
data sun.gc.collector.0.time/sun.os.hrt.frequency
align right
scale sec
width 8
format "0.000"
}
column {
header "^FGC^" /* Full Collections */
data sun.gc.collector.1.invocations
align right
width 5
scale raw
format "0"
}
column {
header "^FGCT^" /* Full Collection Time */
data sun.gc.collector.1.time/sun.os.hrt.frequency
align right
scale sec
width 8
format "0.000"
}
column {
header "^GCT^" /* Total Garbage Collection Time */
data (sun.gc.collector.0.time + sun.gc.collector.1.time)/sun.os.hrt.frequency
align right
width 8
scale sec
format "0.000"
}
}
上記の定義から私達はgcutilの各列がどういう意味であるかを知っています。sun.gc.generation.0.space.0.capacity
のようないくつかの変数はjvmで作成され、リアルタイムで更新された値です。jstatはどのようにこれらの変数の値を取得しますか?
変数値は明らかにターゲットプロセスから取得されましたが、どうやって来ましたか?local socketですか?それともmemory shareですか?実は共有ファイルから来ました。このファイルはPerfDataといいます。主にtmp/hsperfdata_/このファイル
PerfDataファイル
ファイルの作成
このファイルが存在するかどうかは二つのパラメータ、一つはUsePerfData、もう一つはPerf DisplaleShardMem、もし設定されたら-XX:+Perf DisplaleShardMemまたは-XX:-UsePerfData、このファイルは存在しません。デフォルトではPerfDiscleShardMemはクローズされています。UsePerfDataとPerfDispable SharedMemの二つのパラメータについてここで説明します。
if (PerfDisableSharedMem) { // do not share the memory for the performance data.
_start = create_standard_memory(size);
} else {
_start = create_shared_memory(size); if (_start == NULL) { // creation of the shared memory region failed, attempt
// to create a contiguous, non-shared memory region instead.
//
if (PrintMiscellaneous && Verbose) {
warning("Reverting to non-shared PerfMemory region.
");
}
PerfDisableSharedMem = true;
_start = create_standard_memory(size);
}
}
ファイルの削除このファイルはいつ削除されますか?通常、プロセスが終了すると自動的に削除されますが、いくつかの極端な状況では、例えば、Kill-9は、この信号jvmをキャプチャすることはできませんので、直接にプロセスを終了し、いくつかの終わりの作業をしていない場合、プロセスはなくなっていますが、このファイルはまだ存在します。このファイルはずっと残していますか?人為的な削除を待つしかないです。jvmではこのような状況を考慮して、現在のユーザーの次のいずれかのjavaプロセス(例えば、jpsを実行します)が起きた時に判断します。下のプロセスファイルは、プロセスがまだ存在するかどうかを確認し、存在しない場合は直接にファイルを削除し、存在するかどうかを判断する具体的な操作は、実際には、キル-0の信号を送信します。異常があるかどうかを確認します。
ファイルの更新
このファイルはmmapによってメモリにマッピングされていますが、jstatは直接DirectByteBufferによってPerfDataから読み込まれていますので、メモリの値が変わったら、jstatから見た値が変化します。メモリの値はいつ変化しますか?つまり、50 msに一度の値を更新すると、ほぼリアルタイムと考えられます。
PerfDataその他の関連VMパラメータ
jstatの穴
私がしばらく考えていた二つの大きな穴:
size_t CompressedClassSpaceCounters::capacity() { return MetaspaceAux::committed_bytes(Metaspace::ClassType);
}
おすすめの読書:
ビッグデータの中台のKafkaは、いったいどこがいいですか?
JVMパラメータによる頻繁なCMS GC