Friday May 23, 2008

Announcing statically-defined DTrace probes in Java!

It's taken a while (too long, perhaps), but the latest JDK7 snapshot build (b27) now has the capability of allowing you to define tracepoints in your Java application and then trace those tracepoints using DTrace. It's come a long way since our initial prototypes, and features a flexible, easy-to-use interface and somewhere around 95% reduction in disabled probe overhead. I hope the wait has been worth it.

To try it out, download the latest JDK binaries. The interface to the tracing system is defined in the com.sun.tracing package, and additional DTrace-specific attributes are defined in the com.sun.tracing.dtrace package. As you can see by the package naming convention, these interfaces are specific to the Sun JVM, and are not technically part of Java, so the usual warnings apply. Also, since it's not an official part of the JDK, you won't find any Javadoc describing the interfaces. But, you can download them here.

The interfaces are present and functional on all platforms, even though you'll only get the DTrace-probe side effects on platforms which support DTrace (for Hotspot, that's only Solaris). On other platforms, the tracing calls will result in no-ops, so it should be safe to apply tracepoints to any Java program. Also, as you may notice, the tracing APIs are written to be generic and not specific to DTrace. It was done this way so that one could add tracepoints to their programs now, and if a different tracing mechanism becomes available and implemented in the JDK, that tracing mechanism may work without any changes to the running Java application.

For those that are interested in the technical details of how this is implemented, feel free to peruse the initial Java/native sources and Hotspot sources. The openjdk repositories will, of course, always contain the latest and greatest.

The package descriptions in the Javadoc provide all the details about how to add probes to your program, and previous blog entries cover the proposal as well, but here's a quick summary of how to do it:

Define your provider

To define your provider, create a Java interface that extends com.sun.tracing.Provider. Each method you add to your interface defines a different probe. You can add parameters to the methods, these will be passed as arguments to your probe.
interface HelloWorldProvider extends com.sun.tracing.Provider {
    void program_init();
    void friendly_greeting(String greeting);
    void program_terminate();
}

Create an instance of your provider

At some point in your application, you need to create an instance of your provider in order to trigger your probes. You'll want to do this early on in your application life cycle since your probes won't even be declared until the provider is created (i.e., dtrace -l won't display your probes until your interface has been intantiated). Use the ProviderFactory to create your provider.
import com.sun.tracing.\*;

class Main {
    public static void main(String argv[]) {
        ProviderFactory factory = ProviderFactory.getDefaultFactory();
        HelloWorldProvider p = factory.createProvider(HelloWorldProvider.class);
        ...
    }
}

Insert probe points into your application

A probe point in the application is a method call of one of the methods your defined in your provider interface. When that method is called, a DTrace probe will be triggered. Any arguments you pass will be provided to an attached DTrace script.
class Main {
    public static void main(String argv[]) {
        ...
        p.program_init();
        String greeting = "Hello, DTracer";
        System.out.println(greeting);
        p.friendly_greeting(greeting);
        ... 
        p.program_terminate();
    }
}

Use DTrace to observe your program

The probes you defined are now traceable via DTrace. They are available as USDT-like probes, where the provider name is the name of your interface concatenated with the program PID, and the probe names are the names you gave the methods. You can control many more aspects of the probe/provider naming, refer to the Javadoc for details.
> dtrace -n 'HelloWorldProvider$target:::friendly_greeting { printf("%s\\n", copyinstr(arg0)); }' -c "java Hello"
About

kamg

Search

Top Tags
Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today