void ustack(int nframes, int strsize) void ustack(int nframes) void ustack(void)
ustack() アクションは、指定バッファーにユーザースタックトレースを記録します。ユーザースタックの深さは、nframes で指定します。nframes を省略した場合、ustackframes オプションで指定された数のスタックフレームが記録されます。ustack() では、プローブ起動時の呼び出しフレームのアドレスを特定できますが、DTrace コンシューマがユーザーレベルで ustack() アクションを処理しないかぎり、スタックフレームはシンボルに翻訳されません。strsize にゼロ以外の値が指定されている場合、ustack() は指定された量の文字列空間を割り当て、これを使ってカーネルから直接、アドレスからシンボルへの翻訳を行います。このユーザーシンボルの直接翻訳機能は、現在、Java 仮想マシンのバージョン 1.5 以降でしか提供されていません。Java のアドレスからシンボルへの翻訳が行われると、Java クラスとメソッド名を持つ Java フレームが含まれているユーザースタックに、注釈が付けられます。翻訳できなかったフレームは、16 進アドレスで表されます。
以下の例では、文字列空間を持たないスタックをトレースしているため、Java のアドレスからシンボルへの翻訳は行われません。
# dtrace -n syscall::write:entry'/pid == $target/{ustack(50, 0);
exit(0)}' -c "java -version"
dtrace: description 'syscall::write:entry' matched 1 probe
java version "1.5.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b58)
Java HotSpot(TM) Client VM (build 1.5.0-beta3-b58, mixed mode)
dtrace: pid 5312 has exited
CPU ID FUNCTION:NAME
0 35 write:entry
libc.so.1`_write+0x15
libjvm.so`__1cDhpiFwrite6FipkvI_I_+0xa8
libjvm.so`JVM_Write+0x2f
d0c5c946
libjava.so`Java_java_io_FileOutputStream_writeBytes+0x2c
cb007fcd
cb002a7b
cb002a7b
cb002a7b
cb002a7b
cb002a7b
cb002a7b
cb002a7b
cb002a7b
cb002a7b
cb002a7b
cb002a7b
cb002a7b
cb002a7b
cb000152
libjvm.so`__1cJJavaCallsLcall_helper6FpnJJavaValue_
pnMmethodHandle_pnRJavaCallArguments_
pnGThread__v_+0x187
libjvm.so`__1cCosUos_exception_wrapper6FpFpnJJavaValue_
pnMmethodHandle_pnRJavaCallArguments_
pnGThread__v2468_v_+0x14
libjvm.so`__1cJJavaCallsEcall6FpnJJavaValue_nMmethodHandle_
pnRJavaCallArguments_pnGThread __v_+0x28
libjvm.so`__1cRjni_invoke_static6FpnHJNIEnv__pnJJavaValue_
pnI_jobject_nLJNICallType_pnK_jmethodID_pnSJNI_
ArgumentPusher_pnGThread__v_+0x180
libjvm.so`jni_CallStaticVoidMethod+0x10f
java`main+0x53d
|
Java 仮想マシンの C と C++ のスタックフレームは、C++ 符号化シンボル名でシンボリックに表現されます。Java スタックフレームは、16 進アドレスで表現されます。以下は、ゼロでない文字列空間で ustack() を呼び出す例です。
# dtrace -n syscall::write:entry'/pid == $target/{ustack(50, 500); exit(0)}'
-c "java -version"
dtrace: description 'syscall::write:entry' matched 1 probe
java version "1.5.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b58)
Java HotSpot(TM) Client VM (build 1.5.0-beta3-b58, mixed mode)
dtrace: pid 5308 has exited
CPU ID FUNCTION:NAME
0 35 write:entry
libc.so.1`_write+0x15
libjvm.so`__1cDhpiFwrite6FipkvI_I_+0xa8
libjvm.so`JVM_Write+0x2f
d0c5c946
libjava.so`Java_java_io_FileOutputStream_writeBytes+0x2c
java/io/FileOutputStream.writeBytes
java/io/FileOutputStream.write
java/io/BufferedOutputStream.flushBuffer
java/io/BufferedOutputStream.flush
java/io/PrintStream.write
sun/nio/cs/StreamEncoder$CharsetSE.writeBytes
sun/nio/cs/StreamEncoder$CharsetSE.implFlushBuffer
sun/nio/cs/StreamEncoder.flushBuffer
java/io/OutputStreamWriter.flushBuffer
java/io/PrintStream.write
java/io/PrintStream.print
java/io/PrintStream.println
sun/misc/Version.print
sun/misc/Version.print
StubRoutines (1)
libjvm.so`__1cJJavaCallsLcall_helper6FpnJJavaValue_
pnMmethodHandle_pnRJavaCallArguments_pnGThread
__v_+0x187
libjvm.so`__1cCosUos_exception_wrapper6FpFpnJJavaValue_
pnMmethodHandle_pnRJavaCallArguments_pnGThread
__v2468_v_+0x14
libjvm.so`__1cJJavaCallsEcall6FpnJJavaValue_nMmethodHandle
_pnRJavaCallArguments_pnGThread__v_+0x28
libjvm.so`__1cRjni_invoke_static6FpnHJNIEnv__pnJJavaValue_pnI
_jobject_nLJNICallType_pnK_jmethodID_pnSJNI
_ArgumentPusher_pnGThread__v_+0x180
libjvm.so`jni_CallStaticVoidMethod+0x10f
java`main+0x53d
8051b9a
|
この出力例から、Java スタックフレームのシンボリックなスタックフレーム情報を確認できます。いくつかの関数が静的関数で、アプリケーションシンボルテーブルにエントリがないので、この出力にはまだ 16 進フレームが含まれています。これらのフレームを翻訳することはできません。
Java フレーム以外のフレームの ustack() シンボル翻訳は、スタックデータの記録後に行われます。このため、シンボル翻訳の実行前に対応するユーザープロセスが終了してしまい、スタックフレーム翻訳ができない可能性があります。シンボル翻訳の前にユーザープロセスが終了した場合、次の例のように、dtrace からの警告メッセージと、16 進スタックフレームのリストが表示されます。
dtrace: failed to grab process 100941: no such process
c7b834d4
c7bca85d
c7bca1a4
c7bd4374
c7bc2628
8047efc
|
この問題に対処するためのテクニックについては、第 33 章ユーザープロセスのトレースを参照してください。
最後に、事後 DTrace デバッガコマンドはフレーム翻訳を実行できないので、ring バッファーポリシーで ustack() を使用すると、常に生の ustack() データが返されることになります。
以下の D プログラムの例では、ustack() が使用されていますが、strsize の指定は省略されています。
syscall::brk:entry
/execname == $$1/
{
@[ustack(40)] = count();
}
デフォルトの Solaris インストールで、Netscape の Web ブラウザ .netscape.bin を指定してこのプログラムを実行するには、次のコマンドを使用します。
# dtrace -s brk.d .netscape.bin
dtrace: description 'syscall::brk:entry' matched 1 probe
^C
libc.so.1`_brk_unlocked+0xc
88143f6
88146cd
.netscape.bin`unlocked_malloc+0x3e
.netscape.bin`unlocked_calloc+0x22
.netscape.bin`calloc+0x26
.netscape.bin`_IMGCB_NewPixmap+0x149
.netscape.bin`il_size+0x2f7
.netscape.bin`il_jpeg_write+0xde
8440c19
.netscape.bin`il_first_write+0x16b
8394670
83928e5
.netscape.bin`NET_ProcessHTTP+0xa6
.netscape.bin`NET_ProcessNet+0x49a
827b323
libXt.so.4`XtAppProcessEvent+0x38f
.netscape.bin`fe_EventLoop+0x190
.netscape.bin`main+0x1875
1
libc.so.1`_brk_unlocked+0xc
libc.so.1`sbrk+0x29
88143df
88146cd
.netscape.bin`unlocked_malloc+0x3e
.netscape.bin`unlocked_calloc+0x22
.netscape.bin`calloc+0x26
.netscape.bin`_IMGCB_NewPixmap+0x149
.netscape.bin`il_size+0x2f7
.netscape.bin`il_jpeg_write+0xde
8440c19
.netscape.bin`il_first_write+0x16b
8394670
83928e5
.netscape.bin`NET_ProcessHTTP+0xa6
.netscape.bin`NET_ProcessNet+0x49a
827b323
libXt.so.4`XtAppProcessEvent+0x38f
.netscape.bin`fe_EventLoop+0x190
.netscape.bin`main+0x1875
1
...
|