/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
This package provides a mechanism for defining and
inserting tracepoints into Java-technology based applications, which
can then be monitored by the tracing tools available on the system.
To add tracepoints to a program, you must first decide where to place the
tracepoints, what the logical names are for these points, what information
will be available to the tracing mechanisms at each point, and decide upon
any logical grouping.
You add instrumentation to a program in three steps:
- First, declare tracepoints by creating interfaces to define
them, and include these interfaces in the program definition.
The declared interfaces are standard Java technology-based
interfaces and are compiled with the program.
- Second, add code in the application to create an instance of the
interface at some point during the initialization of the application,
using a factory class provided by the system. The reference to the
instance can be stored as a global static, or passed as context to all
the places where it is needed.
- Finally, add the actual tracepoints to the desired locations in the
application by inserting a call to one of the methods defined in the
interface, via the factory-created reference.
The method calls representing the tracepoints have no logical
impact on the program. The side effect of the call is that any
activated tracing mechanisms will be notified that the tracepoint has
been hit, and will take whatever actions are appropriate (for example,
logging the tracepoint, or triggering a DTrace probe, etc.). In most
cases, the impact on performance of adding tracepoints to the application
will be minimal.
Each logical grouping of tracepoints should be defined in a common
interface, called a provider. An application can have one or many
providers. Each provider is independent and can be created whenever
it is appropriate for that provider, for example, when a subsytem is
initialized. Providers should be disposed of when they are no longer
needed, to free up any associated system resources. Each tracepoint
in a provider is represented by a method in that interface. These methods
are referred to as probes. The method signature determines the probe
parameters. A call to the method with the specified parameters triggers
the probe and makes its parameter values visible to any associated tracing
mechanism.
User-defined interfaces which represent providers must extend the Provider
interface. To activate the system-defined tracing mechanisms, you must obtain an instance of the ProviderFactory
class, and pass the class of the provider to the createProvider()
method. The returned instance is then used to trigger the probes later in the application.
In addition to triggering the probes, the provider instance can be used to obtain direct references to the Probe
objects, which can be used directly for triggering, or can be queried to determine whether the probe is currently being traced. The Provider
interface also defines a Provider.dispose()
method which is used to free up any resources that might be associated with that provider.
When a probe is triggered, any activated tracing system will be given the provider name, the probe name, and the values of the probe arguments. The tracing system is free to consume this data is whatever way is appropriate. By default, the provider name is the same as the class name of the interface that defines the provider. Similarly, the probe name is the name of the method that defines the probe. These default values can be over-ridden by annotations. The provider definition can be annotated with the @ProviderName
annotation, whose value will indicate the provider name that the tracing system will use. Similarly, the @ProbeName
annotation annotates a declared method and indicates the probe name that should be used in the place of the method name. These annotations can be used to define providers and probes with the same name, in cases where the semantics of the Java language may prevent this.
Here is a very small and simple usage example:
import com.sun.tracing.Provider;
import com.sun.tracing.ProviderFactory;
interface MyProvider extends Provider {
void startProbe();
void finishProbe(int value);
}
public class MyApplication {
public static void main(String argv[]) {
ProviderFactory factory = ProviderFactory.getDefaultFactory();
MyProvider trace = factory.createProvider(MyProvider.class);
trace.startProbe();
int result = foo();
trace.finishProbe(result);
trace.dispose();
}
}
The Java Development Kit (JDK) currently only includes one system-defined
tracing framework: DTrace. DTrace is enabled automatically whenever an
application is run on a system and a JDK release that supports it. When
DTrace is enabled, probes are made available for listing and matching by
DTrace scripts as soon as the provider is created. At the tracepoint, an
associated DTrace script is informed of the creation of the provider, and
it takes whatever action it is designed to take. Tracepoints in the
program have the following DTrace probe names:
<provider><pid>:<module>:<function>:<probe>
Where:
<provider>
the provider name as specified by the application
<pid>
the operating system process ID
<module>
undefined, unless specified by the application
<function>
undefined, unless specified by the application
<probe>
the probe name as specified by the application
The com.sun.tracing.dtrace
package contains additional annotations that can be used to control the names used for the module
and function
fields, as well as annotations
that can be added to the provider to control probe stability and dependency
attributes.
Integer, float and string probe parameters are made available to DTrace using the built-in argument variables, arg0 ... arg_n
. Integer-types are passed by value (boxed values are unboxed), floating-point types are passed as encoded integer arguments, and java.lang.String
objects are converted to UTF8 strings, so they can be read into the DTrace script using the copyinstr()
intrinsic. Non-string and non-boxed primitive reference arguments are only placeholders and have no value.
Using the example above, with a theoretical process ID of 123, these are
the probes that can be traced from DTrace:
MyProvider123:::startProbe
MyProvider123:::finishProbe
When finishProbe
executes, arg0
will contain the value of result
.
The DTrace tracing mechanism is enabled for all providers, apart from in the
following circumstances:
- DTrace is not supported on the underlying system.
- The property
com.sun.tracing.dtrace
is set to "disable".
- The RuntimePermission
com.sun.tracing.dtrace.createProvider
is denied to the process.
/**
* This package provides a mechanism for defining and
* inserting tracepoints into Java-technology based applications, which
* can then be monitored by the tracing tools available on the system.
* <p>
* To add tracepoints to a program, you must first decide where to place the
* tracepoints, what the logical names are for these points, what information
* will be available to the tracing mechanisms at each point, and decide upon
* any logical grouping.
* <p>
* You add instrumentation to a program in three steps:
* <ul>
* <li>First, declare tracepoints by creating interfaces to define
* them, and include these interfaces in the program definition.
* The declared interfaces are standard Java technology-based
* interfaces and are compiled with the program.</li>
* <li>Second, add code in the application to create an instance of the
* interface at some point during the initialization of the application,
* using a factory class provided by the system. The reference to the
* instance can be stored as a global static, or passed as context to all
* the places where it is needed.</li>
* <li>Finally, add the actual tracepoints to the desired locations in the
* application by inserting a call to one of the methods defined in the
* interface, via the factory-created reference.</li>
* </ul>
* <p>
* The method calls representing the tracepoints have no logical
* impact on the program. The side effect of the call is that any
* activated tracing mechanisms will be notified that the tracepoint has
* been hit, and will take whatever actions are appropriate (for example,
* logging the tracepoint, or triggering a DTrace probe, etc.). In most
* cases, the impact on performance of adding tracepoints to the application
* will be minimal.
* <p>
* Each logical grouping of tracepoints should be defined in a common
* interface, called a <i>provider</i>. An application can have one or many
* providers. Each provider is independent and can be created whenever
* it is appropriate for that provider, for example, when a subsytem is
* initialized. Providers should be disposed of when they are no longer
* needed, to free up any associated system resources. Each tracepoint
* in a provider is represented by a method in that interface. These methods
* are referred to as <i>probes</i>. The method signature determines the probe
* parameters. A call to the method with the specified parameters triggers
* the probe and makes its parameter values visible to any associated tracing
* mechanism.
* <p>
* User-defined interfaces which represent providers must extend the
* {@code Provider} interface. To activate the system-defined
* tracing mechanisms, you must obtain an instance of the
* {@code ProviderFactory} class, and pass the class of the provider to
* the {@code createProvider()} method. The returned instance is then used to
* trigger the probes later in the application.
* <p>
* In addition to triggering the probes, the provider instance can be used
* to obtain direct references to the {@code Probe} objects, which can be used
* directly for triggering, or can be queried to determine whether the probe is
* currently being traced. The {@code Provider} interface also defines a
* {@code Provider.dispose()} method which is used to free up any resources
* that might be associated with that provider.
* <p>
* When a probe is triggered, any activated tracing system will be given
* the provider name, the probe name, and the values of the probe arguments.
* The tracing system is free to consume this data is whatever way is
* appropriate.
* By default, the provider name is the same as the class name of the interface
* that defines the provider. Similarly, the probe name is
* the name of the method that defines the probe. These default values
* can be over-ridden by annotations. The provider definition can be
* annotated with the {@code @ProviderName} annotation, whose value will
* indicate the provider name that the tracing system will use. Similarly,
* the {@code @ProbeName} annotation annotates a declared method and
* indicates the probe name that should be used in the place of the
* method name. These annotations can be used to define providers and
* probes with the same name, in cases where the semantics of the Java language
* may prevent this.
* <p>
* Here is a very small and simple usage example:
* <p>
*
<PRE>
import com.sun.tracing.Provider;
import com.sun.tracing.ProviderFactory;
interface MyProvider extends Provider {
void startProbe();
void finishProbe(int value);
}
public class MyApplication {
public static void main(String argv[]) {
ProviderFactory factory = ProviderFactory.getDefaultFactory();
MyProvider trace = factory.createProvider(MyProvider.class);
trace.startProbe();
int result = foo();
trace.finishProbe(result);
trace.dispose();
}
}
</PRE>
* <p>
* The Java Development Kit (JDK) currently only includes one system-defined
* tracing framework: DTrace. DTrace is enabled automatically whenever an
* application is run on a system and a JDK release that supports it. When
* DTrace is enabled, probes are made available for listing and matching by
* DTrace scripts as soon as the provider is created. At the tracepoint, an
* associated DTrace script is informed of the creation of the provider, and
* it takes whatever action it is designed to take. Tracepoints in the
* program have the following DTrace probe names:<br>
* {@code <provider><pid>:<module>:<function>:<probe>}
* Where:
* <ul>
* <li>{@code <provider>} the provider name as specified by the application</li>
* <li>{@code <pid>} the operating system process ID</li>
* <li>{@code <module>} undefined, unless specified by the application</li>
* <li>{@code <function>} undefined, unless specified by the application</li>
* <li>{@code <probe>} the probe name as specified by the application</li>
* </ul>
* <p>
* The {@code com.sun.tracing.dtrace} package contains additional
* annotations that can be used to control the names used for the
* <code>module</code> and <code>function</code> fields, as well as annotations
* that can be added to the provider to control probe stability and dependency
* attributes.
* <p>
* Integer, float and string probe parameters are made available to DTrace
* using
* the built-in argument variables, {@code arg0 ... arg_n}. Integer-types
* are passed by value (boxed values are unboxed), floating-point types are
* passed as encoded integer
* arguments, and {@code java.lang.String} objects are converted
* to UTF8 strings, so they can be read into the DTrace script using the
* {@code copyinstr()} intrinsic. Non-string and non-boxed primitive
* reference arguments are only
* placeholders and have no value.
* <p>
* Using the example above, with a theoretical process ID of 123, these are
* the probes that can be traced from DTrace:
<PRE>
MyProvider123:::startProbe
MyProvider123:::finishProbe
</PRE>
* When {@code finishProbe} executes, {@code arg0} will contain the
* value of {@code result}.
* <p>
* The DTrace tracing mechanism is enabled for all providers, apart from in the
* following circumstances:
* <ul>
* <li>DTrace is not supported on the underlying system.</li>
* <li>The property {@code com.sun.tracing.dtrace} is set to "disable".</li>
* <li>The RuntimePermission {@code com.sun.tracing.dtrace.createProvider}
* is denied to the process.</li>
* </ul>
* <p>
*/
package com.sun.tracing;