• Home
    • View
    • Login
    This page
    • Normal
    • Export PDF
    • Export Word
    • Attachments
    • Page Information

    Loading...
  1. Dashboard
  2. Port: MacOSX
  3. Main
  4. Installing & Using the Mac OS X Port
  5. Mac OS X Port Using HotSpot DTrace Probes

Mac OS X Port Using HotSpot DTrace Probes

  • Created by Mike Swingler, last modified by Brian Beck on Jan 18, 2013

The OpenJDK Mac OS X Port now has dtrace probes. Many of these probes are enabled automatically, though some resource intensive probes must be
enabled with a JVM argument. Java code JSDT probes are not supported. (For dtrace implementation information, see Mac OS X Port Dtrace Probe Implementation.)

What Is It Good For?

DTrace and its probes allow the Java developer and plain old Java user to learn more about the execution of a given Java process without
modifying any of the code. For example, if you want to know when garbage collection starts in a running java program with pid 12345, you'd
type:

% sudo /usr/sbin/dtrace -n 'hotspot$1:::gc-end{printf("GC: %d\n", timestamp);}' 1213
dtrace: description 'hotspot$1:::gc-end' matched 2 probes
CPU     ID                    FUNCTION:NAME
  0  23653 _ZN15VM_GC_Operation13notify_gc_endEv:gc-end GC: 334679181

  1  23653 _ZN15VM_GC_Operation13notify_gc_endEv:gc-end GC: 1487377551

  0  23653 _ZN15VM_GC_Operation13notify_gc_endEv:gc-end GC: 3231453137

Of course, you'll also want to do more sophisticated things that don't fit on a command line, so you can put the
d program into a file, say gcEnd.d:

hotspot$1:::gc-end
{
  printf("GC: %d\n", timestamp);
}

and type:

% sudo /usr/sbin/dtrace -s gcEnd.d 1213

You can get a complete list of probes available in HotSpot by typing:

% sudo /usr/sbin/dtrace -l 1213 | grep hotspot
23638 hotspot1213      libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl] class-initialization-clinit
23639 hotspot1213      libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl] class-initialization-concurrent
23640 hotspot1213      libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl] class-initialization-end
23641 hotspot1213      libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl] class-initialization-erroneous
23642 hotspot1213      libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl] class-initialization-error
...

One can do much more with dtrace than simple probe entry/exit notification. There are examples and tutorials available
on the web, for example: http://dsc.sun.com/solaris/articles/dtrace_example.html. Let me give you some ideas with a
couple more examples.

First, lets extend the gcEnd.d program above to measure the time intervals occupied by garbage collecton. To compute
this, we need to record the time when gc begins, and then compute the difference in time when gc ends:

long startTime;
hotspot$1:::gc-begin
{
  startTime = timestamp;
}
hotspot$1:::gc-end
{
  printf("GC time interval: %d\n", timestamp-startTime);
}

My final example uses probes that are not enabled by default. These optional probes can be turned on with the
following JVM flags:

 -XX:+DTraceMethodProbes
 -XX:+DTraceAllocProbes
 -XX:+DTraceMonitorProbes

Or turn them all on with:

 -XX:+ExtendedDTraceProbes

Start a Java program with extended dtrace probes:

% java -XX:+ExtendedDTraceProbes -jar /Developer/Extras/Java/JFC/Java2D/Java2D.jar

Run dtrace with the following command (substituting the correct process id), wait a bit, and type control-c:

% sudo /usr/sbin/dtrace -s object_allocation_stat.d -p 1444
^C
 Top 100 allocations by size:
        40 java/lang/ref/SoftReference
       192 [C
       192 java/lang/String
      2016 sun/java2d/loops/GraphicsPrimitiveMgr$PrimitiveSpec

The object_allocation_stat.d example code:

Object Allocation Statistics (object_allocation_stat.d)
#!/usr/sbin/dtrace -Zs

#pragma D option quiet
#pragma D option destructive
#pragma D option defaultargs
#pragma D option bufsize=16m
#pragma D option aggrate=100ms

/*
 * Usage:
 *      object_allocation_stat.d -p JAVA_PID [PAUSE_AT_STARTUP_FILE]
 *
 * This script collects statistics about object allocations.
 *
 * Notes:
 *  - this probes are available only with '-XX:+ExtendedDtraceProbes' option,
 *      so pass this option too.
 *  - This script SLOW DOWN your java application. So, not be surprised :)
 *
 *
 * Note that Hotspot probes definitions are located in libjvm.so and
 * straightforward attempt to run d-script may fail, e.g.:
 *      ./dscript.d -c "java HelloWorld"
 *      "probe description hotspotPID:::probename does not match any probes"
 * This is because dtrace tries to enable probes before libjvm.so is loaded.
 *
 * To avoid this use one of following options to start java:
 * 1) -XX:+PauseAtStartup 
 * 2) -XX:+PauseAtStartup -XX:PauseAtStartupFile=FILENAME
 *
 * In first case the file named 'vm.paused.JAVA_PID' will be created and
 *  then java process will be paused till 'vm.paused.JAVA_PID' will be deleted.
 * In second case jvm will wait till 'FILENAME' will be deleted.
 * 
 * Then you can launch d-script you want to run by passing JAVA_PID as -p <JAVA_PID>
 * and delete PAUSE_AT_STARTUP_FILE manually or by passing it as first argument 
 * (PAUSE_AT_STARTUP_FILE) to d-script.
 * 
 * NB: -XX:+PauseAtStartup requires -XX:+UnlockDiagnosticVMOptions
 *
 */

self char *str_ptr;
self string class_name;

long long ALLOCATED_OBJECTS_CNT;

string PAUSE_AT_STARTUP_FILE;

:::BEGIN
/ $1 != "" /
{
    PAUSE_AT_STARTUP_FILE = $1;

    printf("rm %s\n\n", PAUSE_AT_STARTUP_FILE);
    system("rm %s", PAUSE_AT_STARTUP_FILE);
}

BEGIN
{
    TOP_N = 100;
    ALLOCATED_OBJECTS_CNT = 0;
}

/*
 * hotspot:::object-alloc probe arguments:
 *  arg0: uintptr_t,    Java thread id
 *  arg1: char*,        a pointer to mUTF-8 string containing the name of
 *                          the class of the object being allocated
 *  arg2: uintptr_t,    the length of the class name (in bytes)
 *  arg3: uintptr_t,    the size of the object being allocated
 */
hotspot$target:::object-alloc
{
    ALLOCATED_OBJECTS_CNT ++;

    self->str_ptr = (char*) copyin(arg1, args[2]+1);
    self->str_ptr[args[2]] = '\0';
    self->class_name = (string) self->str_ptr;


    @allocs_count[self->class_name] = count();
    @allocs_size[self->class_name] = sum(args[3]);

/*
    printf("%s:\t[%u] class_name=%s (len=%u), size=%u\n",
        probename, args[0], self->class_name, args[2], args[3]);
*/
}

:::END
{
    printf("Top %d allocations by size:\n", TOP_N);
    trunc(@allocs_size, TOP_N);
    printa("%10@d %s\n", @allocs_size);

    printf("\n");
    printf("Top %d allocations by count:\n", TOP_N);
    trunc(@allocs_count, TOP_N);
    printa("%10@d %s\n", @allocs_count);

    printf("\nTotal number of allocated objects: %d\n", ALLOCATED_OBJECTS_CNT);
}

More DTrace scripts

Overview
Content Tools
ThemeBuilder
  • No labels

Terms of Use
• License: GPLv2
• Privacy • Trademarks • Contact Us

Powered by a free Atlassian Confluence Open Source Project License granted to https://www.atlassian.com/software/views/opensource-community-additional-license-offer. Evaluate Confluence today.

  • Kolekti ThemeBuilder Powered by Atlassian Confluence 8.5.22
  • Kolekti ThemeBuilder printed.by.atlassian.confluence
  • Report a bug
  • Atlassian News
Atlassian
Kolekti ThemeBuilder EngineAtlassian Confluence
{"serverDuration": 187, "requestCorrelationId": "34bd061ea3d7e5da"}