HPROF 出力ファイルの説明
ファイルの先頭のセクションには、オプションの説明、著作権、特記事項などの一般ヘッダー情報が記述されています。 その後に、各スレッドの要約が続きます。
シンプルなプログラムで HPROF を使用した後に次のような出力を表示できます。 このテスト・プログラムでは、2 つのスレッドを作成して短時間だけ実行しています。 出力から、applesと呼ばれる2つのスレッドがあり、システム生成のmainスレッドの後に orangesが作成されたことがわかります。 どちらのスレッドも、mainスレッドの前に終了します。 各スレッドについて、そのアドレス、ID、名前、およびスレッド・グループ名が表示されています。 スレッドが開始および終了した順序を確認できます。
THREAD START (obj=11199050, id = 1, name="Signal dispatcher", group="system")
THREAD START (obj=111a2120, id = 2, name="Reference Handler", group="system")
THREAD START (obj=111ad910, id = 3, name="Finalizer", group="system")
THREAD START (obj=8b87a0, id = 4, name="main", group="main")
THREAD END (id = 4)
THREAD START (obj=11262d18, id = 5, name="Thread-0", group="main")
THREAD START (obj=112e9250, id = 6, name="apples", group="main")
THREAD START (obj=112e9998, id = 7, name="oranges", group="main")
THREAD END (id = 6)
THREAD END (id = 7)
THREAD END (id = 5)
トレース出力セクションには、通常のスタック・トレース情報が記述されています。 各トレースの深さを設定可能であり、各トレースには一意の ID が割り当てられています。
TRACE 5:
java/util/Locale.toLowerCase(Locale.java:1188)
java/util/Locale.convertOldISOCodes(Locale.java:1226)
java/util/Locale.<init>(Locale.java:273)
java/util/Locale.<clinit>(Locale.java:200)
トレースにはいくつかのフレームが含まれており、各フレームには、クラス名、メソッド名、ファイル名、および行番号が含まれています。 上記の例では、Locale.java (toLowerCase メソッド内) の行番号 1188 が同じクラス内の convertOldISOCodes() 関数から呼び出されたことがわかります。 これらのトレースは、お使いのプログラムの実行パスをたどるのに役立ちます。 モニター・オプションを設定した場合は、次の例のようなモニター・ダンプが生成されます。
MONITOR DUMP BEGIN
THREAD 8, trace 1, status: R
THREAD 4, trace 5, status: CW
THREAD 2, trace 6, status: CW
THREAD 1, trace 1, status: R
MONITOR java/lang/ref/Reference$Lock(811bd50) unowned
waiting to be notified: thread 2
MONITOR java/lang/ref/ReferenceQueue$Lock(8134710) unowned
waiting to be notified: thread 4
RAW MONITOR "_hprof_dump_lock"(0x806d7d0)
owner: thread 8, entry count: 1
RAW MONITOR "Monitor Cache lock"(0x8058c50)
owner: thread 8, entry count: 1
RAW MONITOR "Monitor Registry lock"(0x8058d10)
owner: thread 8, entry count: 1
RAW MONITOR "Thread queue lock"(0x8058bc8)
owner: thread 8, entry count: 1
MONITOR DUMP END
MONITOR TIME BEGIN (total = 0 ms) Thu Aug 29 16:41:59 2002
MONITOR TIME END
- R - 実行可能 (Runnable) (スレッドは必要に応じて実行可能)
- S - 中断状態 (Suspended) (スレッドは他のスレッドによって中断されています)
- CW - 待機状態 (Condition Wait) (スレッドは待機中)
- MW — 待機モニター (Monitor Wait) (モニターは待機中)
Heapdump はその次のセクションです。 この情報では、各種のメモリー領域がリストされており、これらの領域の割り振り状況が示されています。
CLS 1123edb0 (name=java/lang/StringBuffer, trace=1318)
super 111504e8
constant[25] 8abd48
constant[32] 1123edb0
constant[33] 111504e8
constant[34] 8aad38
constant[115] 1118cdc8
CLS 111ecff8 (name=java/util/Locale, trace=1130)
super 111504e8
constant[2] 1117a5b0
constant[17] 1124d600
constant[24] 111fc338
constant[26] 8abd48
constant[30] 111fc2d0
constant[34] 111fc3a0
constant[59] 111ecff8
constant[74] 111504e8
constant[102] 1124d668
...
CLS 111504e8 (name=java/lang/Object, trace=1)
constant[18] 111504e8
CLS は、メモリーがクラス用に割り振られていることを示しています。 それに続く 16 進数はそのメモリーの割り振り先のアドレスです。
それに続いて、クラス名とトレース参照が示されています。 この情報を使用して、トレース出力を相互参照して、そのクラスがいつ呼び出されたのかを確認できます。 そのトレースを参照すると、このオブジェクトが作成される原因となった命令の行番号を取得できます。 このクラス内の定数のアドレスも表示され、上記の例では、スーパークラスのクラス定義のアドレスが表示されています。 どちらのクラスも、同じスーパークラスの子(アドレス11504e8を持つ)です。 出力の後続部分を見ると、このクラスの定義と名前がわかります。 これは Object クラスです (すべてのクラスの継承元となるクラス)。 JVM は、サブクラスを使用する前に、スーパークラス階層全体を読み込む必要があります。 したがって、すべてのスーパークラスのクラス定義が常に存在しています。 オブジェクト(OBJ)および配列(ARR)のエントリもあります。
OBJ 111a9e78 (sz=60, trace=1, class=java/lang/Thread@8b0c38)
name 111afbf8
group 111af978
contextClassLoader 1128fa50
inheritedAccessControlContext 111aa2f0
threadLocals 111bea08
inheritableThreadLocals 111bea08
ARR 8bb978 (sz=4, trace=2, nelems=0, elem type=java/io/ObjectStreamField@8bac80)
heap オプションを sites または all に設定すると、お使いのコードによって割り振られた各ストレージ域のリストが得られます。 パラメーター all は、 ダンプ と サイトを結合します。 このリストでは、割り振ったメモリー量が多い順にサイトがリストされています。
SITES BEGIN (ordered by live bytes) Tue Feb 06 10:54:46 2007
percent live alloc'ed stack class
rank self accum bytes objs bytes objs trace name
1 20.36% 20.36% 190060 16 190060 16 300000 byte[]
2 14.92% 35.28% 139260 1059 139260 1059 300000 char[]
3 5.27% 40.56% 49192 15 49192 15 300055 byte[]
4 5.26% 45.82% 49112 14 49112 14 300066 byte[]
5 4.32% 50.14% 40308 1226 40308 1226 300000 java.lang.String
6 1.62% 51.75% 15092 438 15092 438 300000 java.util.HashMap$Entry
7 0.79% 52.55% 7392 14 7392 14 300065 byte[]
8 0.47% 53.01% 4360 16 4360 16 300016 char[]
9 0.47% 53.48% 4352 34 4352 34 300032 char[]
10 0.43% 53.90% 3968 32 3968 32 300028 char[]
11 0.40% 54.30% 3716 8 3716 8 300000 java.util.HashMap$Entry[]
12 0.40% 54.70% 3708 11 3708 11 300000 int[]
13 0.31% 55.01% 2860 16 2860 16 300000 java.lang.Object[]
14 0.28% 55.29% 2644 65 2644 65 300000 java.util.Hashtable$Entry
15 0.28% 55.57% 2640 15 2640 15 300069 char[]
16 0.27% 55.84% 2476 17 2476 17 300000 java.util.Hashtable$Entry[]
17 0.25% 56.08% 2312 16 2312 16 300013 char[]
18 0.25% 56.33% 2312 16 2312 16 300015 char[]
19 0.24% 56.57% 2224 10 2224 10 300000 java.lang.Class
この例では、トレース 300055 によって割り振られたメモリーは、割り振られた合計メモリーの 5.27% です。 この比率は 49192 バイトに相当します。
cpu オプションを使用すると、プロセッサーに関するプロファイル情報が得られます。 cpu を samples に設定すると、出力にはコード実行時に取得した定期的サンプルの結果が含まれます。 各サンプルでは、処理中のコード・パスが記録されて、以下のようなレポートが生成されます。
CPU SAMPLES BEGIN (total = 714) Fri Aug 30 15:37:16 2002
rank self accum count trace method
1 76.28% 76.28% 501 77 MyThread2.bigMethod
2 6.92% 83.20% 47 75 MyThread2.smallMethod
...
CPU SAMPLES END
この出力内容から、bigMethod() はプロセッサー実行時間の 76.28% を消費していたこと、および 714 回のサンプルのうち 501 回で実行されていたことがわかります。 トレース ID を使用すると、このメソッドの呼び出しにつながった正確なルートがわかります。