1fb3fb4f3Stomee<!-- 291cfa10aStomee Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3fb3fb4f3Stomee Use is subject to license terms. 4fb3fb4f3Stomee 5fb3fb4f3Stomee CDDL HEADER START 6fb3fb4f3Stomee 7fb3fb4f3Stomee The contents of this file are subject to the terms of the 8fb3fb4f3Stomee Common Development and Distribution License (the "License"). 9fb3fb4f3Stomee You may not use this file except in compliance with the License. 10fb3fb4f3Stomee 11fb3fb4f3Stomee You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 12fb3fb4f3Stomee or http://www.opensolaris.org/os/licensing. 13fb3fb4f3Stomee See the License for the specific language governing permissions 14fb3fb4f3Stomee and limitations under the License. 15fb3fb4f3Stomee 16fb3fb4f3Stomee When distributing Covered Code, include this CDDL HEADER in each 17fb3fb4f3Stomee file and include the License file at usr/src/OPENSOLARIS.LICENSE. 18fb3fb4f3Stomee If applicable, add the following below this CDDL HEADER, with the 19fb3fb4f3Stomee fields enclosed by brackets "[]" replaced with your own identifying 20fb3fb4f3Stomee information: Portions Copyright [yyyy] [name of copyright owner] 21fb3fb4f3Stomee 22fb3fb4f3Stomee CDDL HEADER END 23fb3fb4f3Stomee--> 24fb3fb4f3Stomee<html> 25fb3fb4f3Stomee<head> 26fb3fb4f3Stomee <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type"> 27fb3fb4f3Stomee <title>Quick Start Guide to the Java DTrace API</title> 28fb3fb4f3Stomee</head> 29fb3fb4f3Stomee<body> 30fb3fb4f3Stomee<h1><a name="Quick_Start_Guide_to_the_Java_DTrace_API_"></a>Quick Start 31fb3fb4f3StomeeGuide</h1> 32fb3fb4f3Stomee<h1><small><small>to the</small> Java DTrace API</small></h1> 33fb3fb4f3Stomee<hr style="width: 100%; height: 2px;"> 34fb3fb4f3Stomee<h2>Contents</h2> 35fb3fb4f3Stomee<ul> 36fb3fb4f3Stomee <li><a href="#Hello_World">"hello, world" Example</a></li> 37fb3fb4f3Stomee <ul> 38fb3fb4f3Stomee <li><a href="#Writing_a_Simple_Consumer">Writing a Simple Consumer</a></li> 39fb3fb4f3Stomee <li><a href="#Running_hello.d_Script">Running the <tt>hello.d</tt> 40fb3fb4f3Stomee Script</a></li> 41fb3fb4f3Stomee </ul> 42fb3fb4f3Stomee <li><a href="#Aggregations">Aggregations</a></li> 43fb3fb4f3Stomee <li><a href="#Target_Process">Target Process ID</a></li> 44fb3fb4f3Stomee <li><a href="#Closing_Consumers">Closing Consumers</a></li> 45fb3fb4f3Stomee <li><a href="#Learning_DTrace">Learning More</a><br> 46fb3fb4f3Stomee </li> 47fb3fb4f3Stomee</ul> 48fb3fb4f3Stomee<h2><a name="Hello_World"></a>"hello, world" Example</h2> 49fb3fb4f3StomeeTo demonstrate how to use the Java DTrace API, let's write a simple Java 50fb3fb4f3Stomeeprogram that runs a D script, in this case <tt>hello.d</tt> (prints 51fb3fb4f3Stomee"hello, world" and exits). You will need root permission to use the 52*bbf21555SRichard LoweJava DTrace API (just as you do to use the <tt>dtrace(8)</tt> command). 53fb3fb4f3StomeeYou may want to eliminate this inconvenience by adding the following 54fb3fb4f3Stomeeline to <tt>/etc/user_attr</tt>: 55fb3fb4f3Stomee<br> 56fb3fb4f3Stomee<br> 57fb3fb4f3Stomee<tt><i>user-name</i>::::defaultpriv=basic,dtrace_kernel,dtrace_proc</tt> 58fb3fb4f3Stomee<br> 59fb3fb4f3Stomee<br> 60fb3fb4f3Stomee<i>(Substitute your user name.)</i> See the <a 613a931819SPeter Tribblehref=http://dtrace.org/guide/chp-sec.html> 623a931819SPeter Tribble<b>Security</b></a> chapter of the <i>Dynamic Tracing Guide</i> 63fb3fb4f3Stomeefor more information. 64fb3fb4f3Stomee<br> 65fb3fb4f3Stomee<h4><a name="Writing_a_Simple_Consumer"></a>Writing a Simple Consumer</h4> 66fb3fb4f3StomeeCreating a DTrace <a 67fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/Consumer.html">consumer</a> 68fb3fb4f3Stomeeis easy: 69fb3fb4f3Stomee<pre><tt> 70fb3fb4f3Stomee Consumer consumer = new LocalConsumer(); 71fb3fb4f3Stomee</tt></pre> 72fb3fb4f3Stomee<br> 73fb3fb4f3StomeeBefore you can do anything with the consumer, you must first open it. 74fb3fb4f3StomeeThen you simply compile and enable one or more D programs and run it: 75fb3fb4f3Stomee<pre><tt> 76fb3fb4f3Stomee consumer.open(); 77fb3fb4f3Stomee consumer.compile(program); 78fb3fb4f3Stomee consumer.enable(); 79fb3fb4f3Stomee consumer.go(); // runs in a background thread 80fb3fb4f3Stomee</tt></pre> 81fb3fb4f3Stomee<br> 82fb3fb4f3StomeeTo get the data generated by DTrace, you also need to add a <a 83fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/ConsumerListener.html">listener</a>: 84fb3fb4f3Stomee<pre><tt> 85fb3fb4f3Stomee consumer.addConsumerListener(new ConsumerAdapter() { 86fb3fb4f3Stomee public void dataReceived(DataEvent e) { 87fb3fb4f3Stomee System.out.println(e.getProbeData()); 88fb3fb4f3Stomee } 89fb3fb4f3Stomee }); 90fb3fb4f3Stomee</tt></pre> 91fb3fb4f3Stomee<br> 92fb3fb4f3StomeeHere is a simple example that runs a given D script:<br> 93fb3fb4f3Stomee<br> 94fb3fb4f3Stomee<b>Java program (<a href="../examples/TestAPI.java">TestAPI.java</a>)</b> 95fb3fb4f3Stomee<pre><tt><font color=#aaaaaa> 96fb3fb4f3Stomee import org.opensolaris.os.dtrace.*; 97fb3fb4f3Stomee import java.io.File; 98fb3fb4f3Stomee 99fb3fb4f3Stomee public class TestAPI { 100fb3fb4f3Stomee public static void 101fb3fb4f3Stomee main(String[] args) 102fb3fb4f3Stomee { 103fb3fb4f3Stomee if (args.length < 1) { 104fb3fb4f3Stomee System.err.println("Usage: java TestAPI <script> [ macroargs... ]"); 105fb3fb4f3Stomee System.exit(2); 106fb3fb4f3Stomee } 107fb3fb4f3Stomee 108fb3fb4f3Stomee File file = new File(args[0]); 109fb3fb4f3Stomee String[] macroArgs = new String[args.length - 1]; 110fb3fb4f3Stomee System.arraycopy(args, 1, macroArgs, 0, (args.length - 1));</font> 111fb3fb4f3Stomee 112fb3fb4f3Stomee Consumer consumer = new LocalConsumer(); 113fb3fb4f3Stomee consumer.addConsumerListener(new ConsumerAdapter() { 114fb3fb4f3Stomee public void dataReceived(DataEvent e) { 115fb3fb4f3Stomee System.out.println(e.getProbeData()); 116fb3fb4f3Stomee } 117fb3fb4f3Stomee }); 118fb3fb4f3Stomee<font color=#aaaaaa> 119fb3fb4f3Stomee try {</font> 120fb3fb4f3Stomee consumer.open(); 121fb3fb4f3Stomee consumer.compile(file, macroArgs); 122fb3fb4f3Stomee consumer.enable(); 123fb3fb4f3Stomee consumer.go();<font color=#aaaaaa> 124fb3fb4f3Stomee } catch (Exception e) { 125fb3fb4f3Stomee e.printStackTrace(); 126fb3fb4f3Stomee System.exit(1); 127fb3fb4f3Stomee } 128fb3fb4f3Stomee } 129fb3fb4f3Stomee }</font> 130fb3fb4f3Stomee</tt></pre> 131fb3fb4f3Stomee<br> 132fb3fb4f3StomeeCompile the test program as follows: 133fb3fb4f3Stomee<pre><tt> 13491cfa10aStomee javac -cp /usr/share/lib/java/dtrace.jar TestAPI.java 135fb3fb4f3Stomee</tt></pre> 136fb3fb4f3Stomee<br> 137fb3fb4f3Stomee<h4><a name="Running_hello.d_Script"></a>Running the <tt>hello.d</tt> Script</h4> 138fb3fb4f3StomeeNow we need a D script for the program to run. The following is a 139fb3fb4f3Stomeesimple example that prints "hello, world" and exits:<br> 140fb3fb4f3Stomee<b>D script (<a href="../examples/hello.d">hello.d</a>)</b> 141fb3fb4f3Stomee<pre><tt> 142fb3fb4f3Stomee dtrace:::BEGIN 143fb3fb4f3Stomee { 144fb3fb4f3Stomee trace("hello, world"); 145fb3fb4f3Stomee exit(0); 146fb3fb4f3Stomee } 147fb3fb4f3Stomee</tt></pre> 148fb3fb4f3Stomee<br> 149fb3fb4f3StomeeRun as follows:<br> 150fb3fb4f3Stomee<pre><tt> 15191cfa10aStomee java -cp .:/usr/share/lib/java/dtrace.jar TestAPI hello.d 152fb3fb4f3Stomee</tt></pre> 153fb3fb4f3Stomee<br> 15491cfa10aStomeeThe output should look like this: 155fb3fb4f3Stomee<pre><tt> 156fb3fb4f3Stomee org.opensolaris.os.dtrace.ProbeData[epid = 1, cpu = 1, 157fb3fb4f3Stomee enabledProbeDescription = dtrace:::BEGIN, flow = null, records = 158fb3fb4f3Stomee ["hello, world", 0]] 159fb3fb4f3Stomee</tt></pre> 160fb3fb4f3Stomee<br> 161fb3fb4f3StomeeThere is one record in the <a 162fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/ProbeData.html"><tt>ProbeData</tt></a> 163fb3fb4f3Stomeefor each action in the D script. The first record is generated by the 164fb3fb4f3Stomee<tt>trace()</tt> action. The second is generated by the <tt>exit()</tt> 165fb3fb4f3Stomeeaction. For prettier output, you could change the <tt>ConsumerAdapter <a 166fb3fb4f3Stomee href="../api/org/opensolaris/os/dtrace/ConsumerAdapter.html#dataReceived%28org.opensolaris.os.dtrace.DataEvent%29">dataReceived()</a></tt> 167fb3fb4f3Stomeeimplementation as follows: 168fb3fb4f3Stomee<pre><tt><font color=#aaaaaa> 169fb3fb4f3Stomee consumer.addConsumerListener(new ConsumerAdapter() { 170fb3fb4f3Stomee public void dataReceived(DataEvent e) { 171fb3fb4f3Stomee // System.out.println(e.getProbeData());</font> 172fb3fb4f3Stomee ProbeData data = e.getProbeData(); 173fb3fb4f3Stomee java.util.List < Record > records = data.getRecords(); 174fb3fb4f3Stomee for (Record r : records) { 175fb3fb4f3Stomee if (r instanceof ExitRecord) { 176fb3fb4f3Stomee } else { 177fb3fb4f3Stomee System.out.println(r); 178fb3fb4f3Stomee } 179fb3fb4f3Stomee }<font color=#aaaaaa> 180fb3fb4f3Stomee } 181fb3fb4f3Stomee });</font> 182fb3fb4f3Stomee</tt></pre> 183fb3fb4f3Stomee<br> 184fb3fb4f3Stomee<h2><a name="Aggregations"></a>Aggregations</h2> 185fb3fb4f3StomeeThe example Java program can just as easily run a more complex script, 186fb3fb4f3Stomeesuch as an aggregation:<br> 187fb3fb4f3Stomee<b>D script (<a href="../examples/syscall.d">syscall.d</a>)</b> 188fb3fb4f3Stomee<pre><tt> 189fb3fb4f3Stomee syscall:::entry 190fb3fb4f3Stomee / execname == $$1 / 191fb3fb4f3Stomee { 192fb3fb4f3Stomee @[probefunc] = count(); 193fb3fb4f3Stomee } 194fb3fb4f3Stomee 195fb3fb4f3Stomee profile:::tick-1sec 196fb3fb4f3Stomee { 197fb3fb4f3Stomee printa(@); 198fb3fb4f3Stomee clear(@); 199fb3fb4f3Stomee } 200fb3fb4f3Stomee</tt></pre> 201fb3fb4f3Stomee<br> 202fb3fb4f3StomeeThe above script uses the <tt>$$1</tt> macro variable as a placeholder 203fb3fb4f3Stomeefor whatever executable you'd like to trace. See the <a 2043a931819SPeter Tribblehref=http://dtrace.org/guide/chp-script.html#chp-script-3><b> 205fb3fb4f3StomeeMacro Arguments</b></a> section of the <b>Scripting</b> chapter of the 2063a931819SPeter Tribble<i>Dynamic Tracing Guide</i>. Using two dollar signs (<tt>$$1</tt>) 207fb3fb4f3Stomeeinstead of one (<tt>$1</tt>) forces expansion of the macro variable to 208fb3fb4f3Stomeetype string.<br> 209fb3fb4f3Stomee<br> 210fb3fb4f3StomeeTo run the example Java program using the above D script, you need to 21191cfa10aStomeespecify an argument to the <tt>execname</tt> placeholder, such as 21291cfa10aStomee"java":<br> 213fb3fb4f3Stomee<pre><tt> 21491cfa10aStomee java -cp .:/usr/share/lib/java/dtrace.jar TestAPI syscall.d java 215fb3fb4f3Stomee</tt></pre> 216fb3fb4f3Stomee<br> 217fb3fb4f3StomeeA data record generated by the <tt>printa()</tt> action is printed to 218fb3fb4f3Stomeethe console once every second. It contains counts of system calls by 219fb3fb4f3Stomeefunction name made by java. No record is generated by the 220fb3fb4f3Stomee<tt>clear()</tt> action.<br> 221fb3fb4f3Stomee<br> 222fb3fb4f3StomeeIf you omit the argument to the <tt>execname</tt> placeholder, the 223fb3fb4f3Stomeeprogram fails to compile and the API throws the following exception: 224fb3fb4f3Stomee<pre><tt> 225fb3fb4f3Stomee org.opensolaris.os.dtrace.DTraceException: failed to compile script 226fb3fb4f3Stomee syscall.d: line 2: macro argument $$1 is not defined 227fb3fb4f3Stomee at org.opensolaris.os.dtrace.LocalConsumer._compileFile(Native Method) 228fb3fb4f3Stomee at org.opensolaris.os.dtrace.LocalConsumer.compile(LocalConsumer.java:342) 229fb3fb4f3Stomee at TestAPI.main(TestAPI.java:26) 230fb3fb4f3Stomee</tt></pre> 231fb3fb4f3Stomee<br> 232fb3fb4f3StomeeA DTrace script may have more than one aggregation. In that case, each 233fb3fb4f3Stomeeaggregation needs a distinct name:<br> 234fb3fb4f3Stomee<b>D script (<a href="../examples/intrstat.d">intrstat.d</a>)</b> 235fb3fb4f3Stomee<pre><tt> 236fb3fb4f3Stomee sdt:::interrupt-start 237fb3fb4f3Stomee { 238fb3fb4f3Stomee self->ts = vtimestamp; 239fb3fb4f3Stomee } 240fb3fb4f3Stomee 241fb3fb4f3Stomee sdt:::interrupt-complete 242fb3fb4f3Stomee / self->ts && arg0 / 243fb3fb4f3Stomee { 244fb3fb4f3Stomee this->devi = (struct dev_info *)arg0; 245fb3fb4f3Stomee @counts[stringof(`devnamesp[this->devi->devi_major].dn_name), 246fb3fb4f3Stomee this->devi->devi_instance, cpu] = count(); 247fb3fb4f3Stomee @times[stringof(`devnamesp[this->devi->devi_major].dn_name), 248fb3fb4f3Stomee this->devi->devi_instance, cpu] = sum(vtimestamp - self->ts); 249fb3fb4f3Stomee self->ts = 0; 250fb3fb4f3Stomee } 251fb3fb4f3Stomee</tt></pre> 252fb3fb4f3Stomee<br> 253fb3fb4f3StomeeThe <tt>@counts</tt> and <tt>@times</tt> aggregations both accumulate 254fb3fb4f3Stomeevalues for each unique combination of device name, device instance, and 255fb3fb4f3StomeeCPU (a three-element tuple). In this example we drop the <tt>tick</tt> 256fb3fb4f3Stomeeprobe to demonstrate a more convenient way to get aggregation data 257fb3fb4f3Stomeewithout the use of the <tt>printa()</tt> action. The <a 258fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/Consumer.html#getAggregate%28%29"> 25991cfa10aStomee<tt>getAggregate()</tt></a> method allows us to get a read-consistent 26091cfa10aStomeesnapshot of all aggregations at once on a programmatic interval.<br> 261fb3fb4f3Stomee<b>Java program (<a href="../examples/TestAPI2.java">TestAPI2.java</a>)</b> 262fb3fb4f3Stomee<pre><tt><font color=#aaaaaa> 263fb3fb4f3Stomee ... 264fb3fb4f3Stomee 265fb3fb4f3Stomee try { 266fb3fb4f3Stomee consumer.open(); 267fb3fb4f3Stomee consumer.compile(file, macroArgs); 268fb3fb4f3Stomee consumer.enable(); 269fb3fb4f3Stomee consumer.go();</font> 270fb3fb4f3Stomee 271fb3fb4f3Stomee Aggregate a; 272fb3fb4f3Stomee do { 273fb3fb4f3Stomee Thread.sleep(1000); // 1 second 274fb3fb4f3Stomee a = consumer.getAggregate(); 275fb3fb4f3Stomee if (!a.asMap().isEmpty()) { 276fb3fb4f3Stomee System.out.println(a); 277fb3fb4f3Stomee } 278fb3fb4f3Stomee } while (consumer.isRunning());<font color=#aaaaaa> 279fb3fb4f3Stomee } catch (Exception e) { 280fb3fb4f3Stomee e.printStackTrace(); 281fb3fb4f3Stomee System.exit(1); 282fb3fb4f3Stomee } 283fb3fb4f3Stomee 284fb3fb4f3Stomee ...</font> 285fb3fb4f3Stomee</tt></pre> 286fb3fb4f3Stomee<br> 287fb3fb4f3StomeeCompile and run: 288fb3fb4f3Stomee<pre><tt> 28991cfa10aStomee javac -cp /usr/share/lib/java/dtrace.jar TestAPI2.java 290fb3fb4f3Stomee</tt></pre> 291fb3fb4f3Stomee<pre><tt> 29291cfa10aStomee java -cp .:/usr/share/lib/java/dtrace.jar TestAPI2 intrstat.d 293fb3fb4f3Stomee</tt></pre> 294fb3fb4f3Stomee<br> 295fb3fb4f3StomeeTry removing the <tt>tick</tt> probe from the <tt>syscall.d</tt> example 296fb3fb4f3Stomeeand running it again with the above modification (<tt>TestAPI2</tt>).<br> 297fb3fb4f3Stomee<br> 298fb3fb4f3StomeeBy default, the requested aggregate includes every aggregation and 299fb3fb4f3Stomeeaccumulates running totals. To display values per time interval 300fb3fb4f3Stomee(instead of running totals), clear the aggregations each time you call 301fb3fb4f3Stomee<tt>getAggregate()</tt>. Clearing an aggregation resets all counts to 30291cfa10aStomeezero without removing any elements. The following modification to the 303fb3fb4f3Stomeeexample above clears all aggregations: 304fb3fb4f3Stomee<pre><tt><font color=#aaaaaa> 305fb3fb4f3Stomee // a = consumer.getAggregate();</font> 306fb3fb4f3Stomee a = consumer.getAggregate(null, null); // included, cleared 307fb3fb4f3Stomee</tt></pre> 308fb3fb4f3Stomee<br> 309fb3fb4f3StomeeEach <tt>Set</tt> of aggregation names, <tt>included</tt> and 310fb3fb4f3Stomee<tt>cleared</tt>, specifies <i>all</i> aggregations if <tt>null</tt> and 311fb3fb4f3Stomeeno aggregations if empty. Any subset is possible. However, if an 312fb3fb4f3Stomeeaggregation has ever been used in the <tt>printa()</tt> action, it is no 313fb3fb4f3Stomeelonger available to the <tt>getAggregate()</tt> method.<br> 314fb3fb4f3Stomee<br> 315fb3fb4f3StomeeBe aware that you cannot call <tt>getAggregate()</tt> on an interval 316fb3fb4f3Stomeefaster that the <tt>aggrate</tt> setting. See the <a 3173a931819SPeter Tribblehref=http://dtrace.org/guide/chp-opt.html> 3183a931819SPeter Tribble<b>Options and Tunables</b></a> chapter of the <i>Dynamic 319fb3fb4f3StomeeTracing Guide</i>. See also the <a 3203a931819SPeter Tribblehref=http://dtrace.org/guide/chp-aggs.html#chp-aggs-4> 321fb3fb4f3Stomee<b>Minimizing Drops</b></a> section of the <b>Aggregations</b> chapter 322fb3fb4f3Stomeefor specific information about the <tt>aggrate</tt> option. The default 323fb3fb4f3Stomee<tt>aggrate</tt> is once per second. Here's an example of how you might 324fb3fb4f3Stomeedouble the <tt>aggrate</tt> to minimize drops: 325fb3fb4f3Stomee<pre><tt> 326fb3fb4f3Stomee consumer.setOption(Option.aggrate, Option.millis(500)); // every half second 327fb3fb4f3Stomee</tt></pre> 328fb3fb4f3Stomee<br> 329fb3fb4f3StomeeEven a single drop terminates the consumer unless you override the <a 330fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/ConsumerAdapter.html#dataDropped%28org.opensolaris.os.dtrace.DropEvent%29"> 331fb3fb4f3Stomee<tt>dataDropped()</tt></a> method of <tt>ConsumerAdapter</tt> to handle 332fb3fb4f3Stomeedrops differently. To avoid drops, it is probably better to increase 333fb3fb4f3Stomeethe <tt>aggsize</tt> option, since increasing the <tt>aggrate</tt> makes 334fb3fb4f3Stomeethe consumer work harder. In most cases, the <tt>aggrate</tt> should 335fb3fb4f3Stomeeonly be increased when you need to update a display of aggregation data 336fb3fb4f3Stomeemore frequently than once per second. Many runtime options, including 337fb3fb4f3Stomee<tt>aggrate</tt>, can be changed dynamically while the consumer is 338fb3fb4f3Stomeerunning.<br> 339fb3fb4f3Stomee<br> 340fb3fb4f3StomeeIt's also worth mentioning that a D aggregation may omit square 341fb3fb4f3Stomeebrackets and aggregate only a single value: 342fb3fb4f3Stomee<pre><tt> 343fb3fb4f3Stomee @total = count(); 344fb3fb4f3Stomee</tt></pre> 345fb3fb4f3Stomee<br> 346fb3fb4f3StomeeThe resulting singleton <a 347fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/Aggregation.html"> 34891cfa10aStomee<tt>Aggregation</tt></a> has one record that may be obtained as follows: 349fb3fb4f3Stomee<pre><tt> 350fb3fb4f3Stomee Aggregate a = consumer.getAggregate(); 351fb3fb4f3Stomee Aggregation total = a.getAggregation("total"); 352fb3fb4f3Stomee AggregationRecord totalRecord = total.getRecord(Tuple.EMPTY); 353fb3fb4f3Stomee</tt></pre> 354fb3fb4f3Stomee<br> 355fb3fb4f3Stomee<h2><a name="Target_Process"></a>Target Process ID</h2> 356fb3fb4f3StomeeIn addition to supporting macro arguments (see the <tt>syscall.d</tt> 357fb3fb4f3Stomeeaggregation example above), the Java DTrace API also supports the 358fb3fb4f3Stomee<tt>$target</tt> macro variable. (See the <a 3593a931819SPeter Tribblehref=http://dtrace.org/guide/chp-script.html#chp-script-4> 360fb3fb4f3Stomee<b>Target Process ID</b></a> section of the <b>Scripting</b> chapter of 3613a931819SPeter Tribblethe <i>Dynamic Tracing Guide</i>.) This allows you to trace a 362fb3fb4f3Stomeeprocess from the very beginning of its execution, rather than sometime 363fb3fb4f3Stomeeafter you manually obtain its process ID. The API does this by creating 364fb3fb4f3Stomeea process that is initially suspended and allowed to start only after <a 365fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/Consumer.html#go%28%29"> 36691cfa10aStomee<tt>go()</tt></a> has initiated tracing. For example, you can aggregate 36791cfa10aStomeeall the system calls from start to finish made by the <tt>date</tt> 36891cfa10aStomeecommand:<br> 369fb3fb4f3Stomee<b>D script (<a href="../examples/target.d">target.d</a>)</b> 370fb3fb4f3Stomee<pre><tt> 371fb3fb4f3Stomee syscall:::entry 372fb3fb4f3Stomee / pid == $target / 373fb3fb4f3Stomee { 374fb3fb4f3Stomee @[probefunc] = count(); 375fb3fb4f3Stomee } 376fb3fb4f3Stomee</tt></pre> 377fb3fb4f3Stomee<br> 378fb3fb4f3StomeeA modified version of the <tt>TestAPI.java</tt> program adds the <a 379fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/Consumer.html#createProcess%28java.lang.String%29"> 380fb3fb4f3Stomee<tt>createProcess()</tt></a> call to execute the given command but 381fb3fb4f3Stomeeprevent it from starting until the consumer is running:<br> 382fb3fb4f3Stomee<b>Java program (<a href="../examples/TestTarget.java">TestTarget.java</a>)</b> 383fb3fb4f3Stomee<pre><tt><font color=#aaaaaa> 384fb3fb4f3Stomee ... 385fb3fb4f3Stomee consumer.open();</font> 386fb3fb4f3Stomee consumer.createProcess(command);<font color=#aaaaaa> 387fb3fb4f3Stomee consumer.compile(file); 388fb3fb4f3Stomee consumer.enable(); 389fb3fb4f3Stomee consumer.go(); 390fb3fb4f3Stomee ...</font> 391fb3fb4f3Stomee</tt></pre> 392fb3fb4f3Stomee<br> 393fb3fb4f3StomeeIt also overrides the <a 394fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/ConsumerAdapter.html#processStateChanged%28org.opensolaris.os.dtrace.ProcessEvent%29"> 395fb3fb4f3Stomee<tt>processStateChanged()</tt></a> method of the 396fb3fb4f3Stomee<tt>ConsumerAdapter</tt> to print a notification when the process has 397fb3fb4f3Stomeeended: 398fb3fb4f3Stomee<pre><tt><font color=#aaaaaa> 399fb3fb4f3Stomee ... 400fb3fb4f3Stomee consumer.addConsumerListener(new ConsumerAdapter() { 401fb3fb4f3Stomee public void dataReceived(DataEvent e) { 402fb3fb4f3Stomee System.out.println(e.getProbeData()); 403fb3fb4f3Stomee } 404fb3fb4f3Stomee public void consumerStopped(ConsumerEvent e) { 405fb3fb4f3Stomee try { 406fb3fb4f3Stomee Aggregate a = consumer.getAggregate(); 407fb3fb4f3Stomee for (Aggregation agg : a.asMap().values()) { 408fb3fb4f3Stomee for (AggregationRecord rec : agg.asMap().values()) { 409fb3fb4f3Stomee System.out.println(rec.getTuple() + " " + 410fb3fb4f3Stomee rec.getValue()); 411fb3fb4f3Stomee } 412fb3fb4f3Stomee } 413fb3fb4f3Stomee } catch (Exception x) { 414fb3fb4f3Stomee x.printStackTrace(); 415fb3fb4f3Stomee System.exit(1); 416fb3fb4f3Stomee } 417fb3fb4f3Stomee consumer.close(); 418fb3fb4f3Stomee }</font> 419fb3fb4f3Stomee public void processStateChanged(ProcessEvent e) { 420fb3fb4f3Stomee System.out.println(e.getProcessState()); 421fb3fb4f3Stomee }<font color=#aaaaaa> 422fb3fb4f3Stomee }); 423fb3fb4f3Stomee ...</font> 424fb3fb4f3Stomee</tt></pre> 425fb3fb4f3Stomee<br> 426fb3fb4f3StomeeCompile and run: 427fb3fb4f3Stomee<pre><tt> 42891cfa10aStomee javac -cp /usr/share/lib/java/dtrace.jar TestTarget.java 429fb3fb4f3Stomee</tt></pre> 430fb3fb4f3Stomee<pre><tt> 43191cfa10aStomee java -cp .:/usr/share/lib/java/dtrace.jar TestTarget target.d date 432fb3fb4f3Stomee</tt></pre> 433fb3fb4f3Stomee<br> 434fb3fb4f3StomeeThe consumer exits automatically when the target <tt>date</tt> process 435fb3fb4f3Stomeecompletes.<br> 436fb3fb4f3Stomee<h2><a name="Closing_Consumers"></a>Closing Consumers</h2> 437fb3fb4f3StomeeAn application using the Java DTrace API may run multiple consumers 438fb3fb4f3Stomeesimultaneously. When a consumer stops running, the programmer is 439fb3fb4f3Stomeeresponsible for closing it in order to release the system resources it 440fb3fb4f3Stomeeholds. A consumer may stop running for any of the following reasons: 441fb3fb4f3Stomee<ul> 442fb3fb4f3Stomee <li>It was stopped explicitly by a call to its <a 443fb3fb4f3Stomeehref=../api/org/opensolaris/os/dtrace/Consumer.html#stop()> 444fb3fb4f3Stomee<tt>stop()</tt></a> method</li> 445fb3fb4f3Stomee <li>It encountered the <tt>exit()</tt> action</li> 446fb3fb4f3Stomee <li>Its <tt>$target</tt> process or processes (if any) all completed</li> 447fb3fb4f3Stomee <li>It encountered an exception</li> 448fb3fb4f3Stomee</ul> 449fb3fb4f3StomeeBy default, an exception prints a stack trace to <tt>stderr</tt> before 450fb3fb4f3Stomeenotifying listeners that the consumer has stopped. You can define 451fb3fb4f3Stomeedifferent behavior by setting an <a 452fb3fb4f3Stomeehref=../api/org/opensolaris/os/dtrace/ExceptionHandler.html> 453fb3fb4f3Stomee<tt>ExceptionHandler</tt></a>, but the consumer is still stopped.<br> 454fb3fb4f3Stomee<br> 455fb3fb4f3StomeeThe same listener that receives probe data generated by DTrace is also 456fb3fb4f3Stomeenotified when the consumer stops. This is a good place to close the 457fb3fb4f3Stomeeconsumer: 458fb3fb4f3Stomee<pre><tt><font color=#aaaaaa> 459fb3fb4f3Stomee consumer.addConsumerListener(new ConsumerAdapter() { 460fb3fb4f3Stomee public void dataReceived(DataEvent e) { 461fb3fb4f3Stomee System.out.println(e.getProbeData()); 462fb3fb4f3Stomee }</font> 463fb3fb4f3Stomee public void consumerStopped(ConsumerEvent e) { 464fb3fb4f3Stomee Consumer consumer = (Consumer)e.getSource(); 465fb3fb4f3Stomee consumer.close(); 466fb3fb4f3Stomee } 467fb3fb4f3Stomee }<font color=#aaaaaa> 468fb3fb4f3Stomee });</font> 469fb3fb4f3Stomee</tt></pre> 470fb3fb4f3Stomee<br> 471fb3fb4f3StomeeThis releases the resources held by the consumer in all cases, i.e. 472fb3fb4f3Stomeeafter it exits for <i>any</i> of the reasons listed above.<br> 473fb3fb4f3Stomee<br> 474fb3fb4f3StomeeYou can request the last aggregate snapshot made by a stopped consumer, 475fb3fb4f3Stomeeas long as it has not yet been closed: 476fb3fb4f3Stomee<pre><tt> 477fb3fb4f3Stomee Aggregate a = consumer.getAggregate(); 478fb3fb4f3Stomee</tt></pre> 479fb3fb4f3Stomee<br> 480fb3fb4f3StomeeNote however that any aggregation that has already appeared in a <a 481fb3fb4f3Stomeehref=../api/org/opensolaris/os/dtrace/PrintaRecord.html> 482fb3fb4f3Stomee<tt>PrintaRecord</tt></a> as a result of the <tt>printa()</tt> action 483fb3fb4f3Stomeeaction will not be included in the requested aggregate. 484fb3fb4f3Stomee<h2><a name="Learning_DTrace"></a>Learning More</h2> 485fb3fb4f3Stomee<br> 4863a931819SPeter TribbleThe <a href="http://dtrace.org/"> 4873a931819SPeter TribbleDTrace page</a> has links to resources to help you learn 488fb3fb4f3StomeeDTrace. In particular, you should read the <a 4893a931819SPeter Tribblehref="http://dtrace.org/guide/"><i>Dynamic Tracing 490fb3fb4f3Stomee Guide</i></a>.<br> 491fb3fb4f3Stomee<br> 492fb3fb4f3StomeeTry the example Java programs on this page with other D scripts. You 493fb3fb4f3Stomeeneed not remove <tt>#!/usr/sbin/dtrace -s</tt> from the top of an 494fb3fb4f3Stomeeexecutable script. You may want to remove <tt>profile:::tick*</tt> 495fb3fb4f3Stomeeclauses if you plan to use the <tt>Consumer</tt> <a 496fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/Consumer.html#getAggregate%28%29"> 49791cfa10aStomee<tt>getAggregate()</tt></a> method and control the data interval 498fb3fb4f3Stomeeprogrammatically. If the script uses the pre-compiler, you will need to 499fb3fb4f3Stomeecall the <tt>Consumer</tt> <a 500fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/Consumer.html#setOption%28java.lang.String%29"> 501fb3fb4f3Stomee<tt>setOption()</tt></a> method with the <a 502fb3fb4f3Stomeehref="../api/org/opensolaris/os/dtrace/Option.html#cpp"> 503fb3fb4f3Stomee<tt>Option.cpp</tt></a> argument.<br> 504fb3fb4f3Stomee<br> 505fb3fb4f3StomeeTo quickly familiarize yourself with the Java DTrace API, take a look at 506fb3fb4f3Stomeethe overview <a href="JavaDTraceAPI.html">diagram</a>.<br> 507fb3fb4f3Stomee<br> 508fb3fb4f3Stomee<a href="#Quick_Start_Guide_to_the_Java_DTrace_API_">Back to top</a><br> 509fb3fb4f3Stomee<br> 510fb3fb4f3Stomee</body> 511fb3fb4f3Stomee</html> 512