# ./jflow.
d
<- java/lang/[Link]
-> [Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
<- java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
<- java/io/[Link]
-> java/io/[Link]
<- java/io/[Link]
DTrace Topics:
Java
-> java/lang/[Link]
-> java/lang/[Link]
<- java/lang/[Link]
<- java/lang/[Link]
<- java/io/[Link]
<- java/io/[Link]
-> java/io/[Link]
Brendan Gregg
Sun Microsystems
March 2007
-> java/io/[Link]
<- java/io/[Link]
-> java/io/[Link]
-> sun/nio/cs/[Link]
-> sun/nio/cs/[Link]
<- sun/nio/cs/[Link]
-> sun/nio/cs/[Link]
-> java/nio/[Link]
DTrace Topics: Java
This presentation is about DTrace and Java, and is
part of the DTrace Topics collection.
These slides cover:
>
>
>
>
>
DTrace Recap
Java and DTrace
The hotspot Provider
hotspot Examples
Resources
DTrace Recap
A general understanding of DTrace is assumed
knowledge for this presentation.
If you are new to DTrace, try starting with the
presentation called DTrace Topics: Intro.
The next two slides are a short summary of DTrace,
if needed.
What is DTrace
DTrace is a dynamic troubleshooting and analysis
tool first introduced in the Solaris 10 and
OpenSolaris operating systems.
DTrace is many things, in particular:
> A tool, /usr/sbin/dtrace
> A programming language interpreter, the D language
> An instrumentation framework
DTrace operates with low overhead when in use,
and zero overhead when not.
DTrace is designed to be safe for production use.
4
What is DTrace
DTrace can observe the entire software stack from
one tool. It is like a combination of,
> truss, sotruss, apptrace, mdb, lockstat, prex/tnf*, C, awk
root and users with DTrace privileges can use it.
DTrace traces events at dynamic instrumentation
points called probes. There are thousands of them.
providers are libraries of related probes.
When probes fire, arbitry actions can be performed,
> Eg: print functions and arguments, measure latencies,
process data, walk process and kernel memory, ...
Java and DTrace
In the first release of Solaris 10, DTrace provided a
jstack() action to read Java stack traces.
For JDK 1.4.2 and 5.0, prototype DTrace Java
providers were released as loadable VM agent
libraries, first named djvm then dvm.
The hotspot DTrace Java provider was integrated
in JDK 6.0, ready for immediate use.
jstack()
This can be used with:
> The profile provider, to sample frequent stack traces.
This can identify Java code hot spots.
> The pid provider, to show how Java interacts with user
libraries.
> The syscall provider, to determine what Java causes the
system to do.
jstack() example
The following shows why Java caused a read():
# dtrace -n 'syscall::read:entry /execname == "java"/ { jstack(); }'
[...]
syscall
0 75943
read:entry
[Link].1`_read+0x7
[Link].4`_X11TransSocketRead+0x25
[Link].4`_X11TransRead+0x17
user
[Link].4`_XRead+0x58
libraries [Link].4`_XReply+0xcd
[Link].4`XGetInputFocus+0x68
[Link]`Java_sun_awt_X11_XlibWrapper_XGetInputFocus+0x27
sun/awt/X11/[Link](J)J
sun/awt/X11/[Link]()J
Java sun/awt/X11/[Link](J)V
code sun/awt/X11/[Link](J)V
sun/awt/X11/[Link](J)V
sun/awt/X11/[Link](Lsun/awt/X11/IXAnyEve
sun/awt/X11/[Link](Lsun/awt/X11/IXAnyEvent;
8
djvm/dvm Provider
If possible, move the application to JDK 6.0 and use
the integrated hotspot provider.
If you are stuck on JDK 1.4.2 or 5.0, you can try the
djvm/dvm prototype provider.
They require command line configuration and the
application to be restarted.
The provider can be downloaded from,
> [Link]
Some examples of its usage are here,
> [Link]
9
hotspot Provider Probes
hotspot provides numerous probes, including:
> Class events,
class-loaded
class-unloaded
> Method invocation,
method-entry
method-return
> Object events,
object-alloc
> Garbage collect,
gc-begin
gc-end
A class loaded
A class unloaded
A method begins
A method completed
An object was allocated
System wide GC begins
System wide GC ended
10
hotspot Provider Probes
> Thread events,
thread-start
thread-stop
> Monitor events
> VM events
A thread has started
A thread completed
The method-* probes can degrade performance,
and are only enabled with the VM flag
ExtendedDTraceProbes.
The full reference for probes and their arguments is:
[Link]
11
hotspot Example #1
The hotspot provider will be demonstrated by
tracing a simple Java program.
The following [Link] code may look familiar,
many Java tutorials begin with something similar:
Greeting class
$ cat [Link]
public class Greeting {
public void greet() {
[Link]("Hello DTrace!");
}
}
12
hotspot Example #1
Now the test harness:
TestGreeting class
$ cat [Link]
public class TestGreeting {
public static void main(String[] args) {
Greeting hello = new Greeting();
while (true) {
[Link](); call greet method
try {
[Link]().sleep(1000);
} catch (InterruptedException e) {
every
}
second
}
}
}
13
hotspot Example #1
Compiling, executing:
$ javac [Link]
$ java TestGreeting
Hello DTrace!
Hello DTrace!
Hello DTrace!
slowly scrolling
Hello DTrace!
^C
output
This simple program produces some known events
that we can trace.
14
Example #1: jstack()
We will start with jstack() (not hotspot!). We know
that this program writes output, ie syscall::write
# dtrace -n 'syscall::write:entry /execname == "java"/ { jstack(); }'
0 75945
write:entry
[Link].1`_write+0x7
[Link]`__1cDhpiFwrite6FipkvI_I_+0xa0
[Link]`JVM_Write+0x36
[Link]`writeBytes+0x154
[Link]`Java_java_io_FileOutputStream_writeBytes+0x3f
java/io/[Link]([BII)V
java/io/[Link]([BII)V
java/io/[Link]()V
java/io/[Link]()V
java/io/[Link]([BII)V
sun/nio/cs/[Link]()V
sun/nio/cs/[Link]()V
[...continued...]
15
Example #1: jstack()
Ah-ha!
sun/nio/cs/[Link]()V
java/io/[Link]()V
java/io/[Link]()V
java/io/[Link](Ljava/lang/String;)V
[Link]()V
[Link]([Ljava/lang/String;)V
StubRout
[Link]`__1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHan
[Link]`__1cCosUos_exception_wrapper6FpFpnJJavaValue_pnMmetho
[Link]`__1cJJavaCallsEcall6FpnJJavaValue_nMmethodHandle_pnRJ
[Link]`__1cRjni_invoke_static6FpnHJNIEnv__pnJJavaValue_pnI_j
[Link]`jni_CallStaticVoidMethod+0x15d
java`JavaMain+0xd30
[Link].1`_thr_setup+0x52
[Link].1`_lwp_start
> Read the stack trace above [Link] carefully.
How many Java classes do you recognize?
16
Example #1: Listing Probes
Now to see what the hotspot provider can do:
# dtrace -ln 'hotspot*:::'
ID
PROVIDER
MODULE
FUNCTION NAME
52103 hotspot_jni278338
[Link]
jni_GetObjectRefType GetOb
52104 hotspot_jni278338
[Link]
jni_GetObjectRefType GetOb
52105 hotspot_jni278338
[Link]
jni_GetPrimitiveArrayCritical GetPr
52106 hotspot_jni278338
[Link]
jni_GetPrimitiveArrayCritical GetPr
52107 hotspot_jni278338
[Link]
jni_GetShortArrayElements GetSh
[...]
# dtrace -ln 'hotspot*:::' | wc -l
1015
# dtrace -ln 'hotspot*:::' | awk '{print $5}' | sort -u | wc -l
499
> 1014 probes, 498 unique probe names == deep visibility!
17
Example #1: Tracing Probes
Watching all enabled hotspot events:
# dtrace -n 'hotspot*:::'
dtrace: description 'hotspot*:::' matched 1014 probes
CPU
ID
FUNCTION:NAME
0 66465 jni_GetArrayLength:GetArrayLength-entry
0 66466 jni_GetArrayLength:GetArrayLength-return
0 66529 jni_GetObjectField:GetObjectField-entry
0 66530 jni_GetObjectField:GetObjectField-return
0 66529 jni_GetObjectField:GetObjectField-entry
0 66530 jni_GetObjectField:GetObjectField-return
0 66475 jni_GetByteArrayRegion:GetByteArrayRegion-entry
0 66476 jni_GetByteArrayRegion:GetByteArrayRegion-return
0 66456 jni_ExceptionOccurred:ExceptionOccurred-entry
0 66457 jni_ExceptionOccurred:ExceptionOccurred-return
[...]
Output scrolls rather fast...
18
Example #1: Aggregating Probes
# dtrace -n 'hotspot*::: { @[probename] = count(); }'
dtrace: description 'hotspot*::: ' matched 1014 probes
^C
ExceptionOccurred-entry
ExceptionOccurred-return
GetArrayLength-entry
GetArrayLength-return
GetByteArrayRegion-entry
GetByteArrayRegion-return
GetObjectField-entry
GetObjectField-return
8
8
8
8
8
8
16
16
> Interesting, but some expected probes are missing (eg,
method-entry). We can enable additional probes...
19
Example #1: Extended Probes
Extended probes are not activated by default as
they may degrade performance on busy apps.
They can be enabled using,
> An option to java: -XX:+ExtendedDTraceProbes
> An option to jinfo: -flag +ExtendedDTraceProbes
# java -XX:+ExtendedDTraceProbes TestGreeting
Hello DTrace!
Hello DTrace!
Hello DTrace!
[...]
20
Example #1: Extended Probes
# dtrace -n 'hotspot*::: { @[probename] = count(); }'
dtrace: description 'hotspot*::: ' matched 1014 probes
^C
ExceptionOccurred-entry
ExceptionOccurred-return
GetArrayLength-entry
GetArrayLength-return
GetByteArrayRegion-entry
GetByteArrayRegion-return
object-alloc
GetObjectField-entry
GetObjectField-return
method-entry
method-return
8
8
8
8
8
8
8
16
16
496
496
> Now we see method-entry and method-return, which
occurred 496 times while this was tracing (4 seconds).
21
Example #1: Tracing Methods
The class and method name can be fetched from
the probe arguments:
# dtrace -qn 'hotspot*:::method-entry { printf("-> %4s.%s\n",
stringof(copyin(arg1, arg2)), stringof(copyin(arg3, arg4))); }'
-> [Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
Live [Link] calls!
-> java/lang/[Link]
-> java/lang/[Link]
-> java/io/[Link]
[...]
22
Example #1: Aggregating Methods
# dtrace -qn 'hotspot*:::method-entry { @calls[stringof(copyin(arg1, arg2)),
stringof(copyin(arg3,arg4))] = count(); }
END { printa("%48s.%-24s %@4d\n", @calls); }'
^C
[Link]
2
java/io/[Link]
2
java/io/[Link]
2
java/io/[Link]
2
java/io/[Link]
2
java/io/[Link]
2
java/io/[Link]
2
java/io/[Link]
2
[...truncated...]
java/nio/CharBuffer$[Link]
20
java/nio/ByteBuffer$[Link]
30
> Identify most frequently called methods.
23
Example #1: Aggregating Methods
Wait a sec,
[...]
java/nio/CharBuffer$[Link]
java/nio/ByteBuffer$[Link]
20
30
These don't look right the strings have been corrupted.
If you see such output, the end of the copyin string
needs to be manually terminated.
24
Example #1: Aggregating Methods
Now a script is written to aggregate methods with
string termination:
# ./jagg.d
Tracing... Hit Ctrl-C to end.
^C
[Link]
java/io/[Link]
java/io/[Link]
java/io/[Link]
java/io/[Link]
java/lang/[Link]
3
3
3
3
3
3
[...]
java/nio/charset/[Link]
java/nio/[Link]
java/nio/[Link]
java/nio/[Link]
12
18
18
24
25
# cat jagg.d
#!/usr/sbin/dtrace -qs
dtrace:::BEGIN
{
printf("Tracing... Hit Ctrl-C to end.\n");
}
hotspot*:::method-entry
{
this->class = (char *) copyin(arg1, arg2 + 1);
this->class[arg2] = '\0';
this->method = (char *) copyin(arg3, arg4 + 1);
this->method[arg4] = '\0';
@calls[stringof(this->class), stringof(this->method)] = count();
}
dtrace:::END
{
printa("%48s.%-24s %@4d\n", @calls);
}
26
Example #1: Method Flow
With some more scripting, flow indented method
calls can be printed:
# ./jflow.d
<- java/lang/[Link]
-> [Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
<- java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
-> java/io/[Link]
<- java/io/[Link]
-> java/io/[Link]
<- java/io/[Link]
[...]
27
Example #1: jflow.d
# cat jflow.d
#!/usr/sbin/dtrace -s
#pragma D option quiet
hotspot*:::method-entry
{
self->indent++;
printf("%*s %s %s.%s\n", self->indent, "", "->",
stringof(copyin(arg1, arg2)), stringof(copyin(arg3,arg4)));
}
hotspot*:::method-return
{
printf("%*s %s %s.%s\n", self->indent, "", "<-",
stringof(copyin(arg1, arg2)), stringof(copyin(arg3,arg4)));
self->indent--;
}
28
Example #1: Stack Flow
DTrace can observe all layers of the software stack.
The following example demonstrates this capability,
and was actually from the prototype provider,
[Link]
-> java/io/InputStreamReader:read
Java
-> sun/nio/cs/StreamDecoder:read
-> sun/nio/cs/StreamDecoder:read0
-> [Link].1:malloc
-> [Link].1:_smalloc
libc
<- [Link].1:_smalloc
<- [Link].1:malloc
-> sun/nio/cs/StreamDecoder:read
-> sun/nio/cs/StreamDecoder:ensureOpen
<- sun/nio/cs/StreamDecoder:ensureOpen
[...]
Java
29
Example #1: Object Allocation
The creation of a new object can be traced with
object-alloc:
# dtrace -qn 'hotspot*:::object-alloc { printf("new %s\n",
stringof(copyin(arg1, arg2))); }'
new java/nio/HeapCharBuffer
new java/nio/HeapCharBuffer
new java/nio/HeapCharBuffer
new java/nio/HeapCharBuffer
[...]
30
Example #1: Method Times
With method-entry and method-return probes, and
DTrace's ability to measure nanosecond
timestamps, the time to execute methods can be
measured.
This can help identify bottlenecks in Java code.
Things start to get a little harder. Be aware of,
>
>
>
>
>
overlapping methods
multiple Java threads executing concurrently
Java threads context switching off the CPUs
DTrace overheads at nanosecond resolutions
recursive methods?
31
Example #1: What's next
Further analysis can be performed using:
> Other hotspot probes
> Other DTrace providers
> Scripting to identify events of interest
The possibilities for analysis are near-endless. This
is great if you are troubleshooting a known problem
as DTrace should have the power to find it.
32
Resources
To learn more about DTrace and Java,
[Link]
Search the Internet for DTrace Java, in particular
are articles written by:
> Adam Leventhal
> Kelly O'Hair
Find Examples of DTracing Java in
/usr/jdk/instances/jdk1.6.0/sample/dtrace/hotspot
Check my blog: [Link]
33
dtrace:::END
Brendan Gregg
brendan@[Link]
34