OpenJDK / amber / amber
changeset 406:bde3a21bcab0
6690122: Provide a mechanism for specifying Java-level USDT-like dtrace probes
Summary: Initial checkin of JSDT code
Reviewed-by: sspitsyn, sbohne
line wrap: on
line diff
--- a/jdk/make/com/sun/Makefile Tue Apr 15 17:46:47 2008 -0700 +++ b/jdk/make/com/sun/Makefile Thu Apr 17 22:00:16 2008 -0400 @@ -41,7 +41,7 @@ # Omit mirror since it's built with the apt tool. SUBDIRS = $(SCRIPT_SUBDIR) image security crypto/provider jndi jmx \ java inputmethods org xml rowset net/httpserver net/ssl demo \ - tools jarsigner + tools jarsigner tracing all build clean clobber:: $(SUBDIRS-loop)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/com/sun/tracing/Makefile Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,26 @@ +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. +# + +# +# Makefile for building tracing classes +# + +BUILDDIR = ../../.. +PACKAGE = com.sun.tracing +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +SUBDIRS = dtrace +all build: + $(SUBDIRS-loop) +clean clobber:: + $(SUBDIRS-loop) + +AUTO_FILES_JAVA_DIRS = com/sun/tracing + +# +# Rules. +# +include $(BUILDDIR)/common/Classes.gmk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/com/sun/tracing/dtrace/Makefile Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,19 @@ +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. +# + +# +# Makefile for building dtrace extension +# +BUILDDIR = ../../../.. +PACKAGE = com.sun.tracing.dtrace +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +AUTO_FILES_JAVA_DIRS = com/sun/tracing/dtrace + +# +# Rules. +# +include $(BUILDDIR)/common/Classes.gmk
--- a/jdk/make/docs/Makefile Tue Apr 15 17:46:47 2008 -0700 +++ b/jdk/make/docs/Makefile Thu Apr 17 22:00:16 2008 -0400 @@ -273,6 +273,28 @@ # SMARTCARDIO_PKGS is located in NON_CORE_PKGS.gmk # +# Variables used by TRACING target +# + +TRACING_SOURCEPATH = $(TOPDIR)/src/share/classes +TRACING_DOCDIR = $(DOCSDIR)/jre/api/tracing + +TRACING_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ + -encoding ascii \ + -nodeprecatedlist \ + -d $(TRACING_DOCDIR) \ + -sourcepath $(TRACING_SOURCEPATH) \ + -windowtitle $(TRACING_WINDOWTITLE) \ + -doctitle $(TRACING_DOCTITLE) \ + -header $(TRACING_JAVADOCHEADER) \ + -linkoffline ../../../../../api $(DOCSDIR)/api/ + +TRACING_WINDOWTITLE = "Tracing" +TRACING_DOCTITLE = "Java$(TRADEMARK) Platform Tracing" +TRACING_JAVADOCHEADER = "Platform Tracing" +# TRACING_PKGS is located in NON_CORE_PKGS.gmk + +# # Variables used by HTTPSERVER target # @@ -420,6 +442,7 @@ jaasdocs \ jgssdocs \ smartcardiodocs \ + tracingdocs \ httpserverdocs \ mgmtdocs \ attachdocs \ @@ -585,6 +608,14 @@ $(JAVADOC_CMD) $(SMARTCARDIO_JAVADOCFLAGS) \ $(SMARTCARDIO_PKGS) +.PHONY: tracingdocs +tracingdocs: + @# ######## api-tracing ############################ + $(RM) -r $(DTRACE_DOCDIR) + $(MKDIR) -p $(DTRACE_DOCDIR) + $(JAVADOC) $(DTRACE_JAVADOCFLAGS) \ + $(DTRACE_PKGS) + .PHONY: httpserverdocs httpserverdocs: @# ######## api-httpserver #######################
--- a/jdk/make/docs/NON_CORE_PKGS.gmk Tue Apr 15 17:46:47 2008 -0700 +++ b/jdk/make/docs/NON_CORE_PKGS.gmk Thu Apr 17 22:00:16 2008 -0400 @@ -84,6 +84,9 @@ SMARTCARDIO_PKGS = javax.smartcardio +TRACING_PKGS = com.sun.tracing \ + com.sun.tracing.dtrace + # non-core packages in rt.jar NON_CORE_PKGS = $(DOMAPI_PKGS) \ $(MGMT_PKGS) \ @@ -91,4 +94,5 @@ $(JGSS_PKGS) \ $(OLD_JSSE_PKGS) \ $(HTTPSERVER_PKGS) \ - $(SMARTCARDIO_PKGS) + $(SMARTCARDIO_PKGS) \ + $(TRACING_PKGS)
--- a/jdk/make/sun/Makefile Tue Apr 15 17:46:47 2008 -0700 +++ b/jdk/make/sun/Makefile Thu Apr 17 22:00:16 2008 -0400 @@ -63,7 +63,7 @@ $(HEADLESS_SUBDIR) $(DGA_SUBDIR) \ font jpeg cmm applet rmi beans $(JDBC_SUBDIR) \ jawt text nio launcher management $(ORG_SUBDIR) \ - native2ascii serialver tools jconsole + native2ascii serialver tools jconsole tracing all build clean clobber:: $(SUBDIRS-loop)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/sun/tracing/Makefile Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,26 @@ +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. +# + +# +# Makefile for building tracing package implementation classes +# + +BUILDDIR = ../.. +PACKAGE = sun.tracing +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +SUBDIRS = dtrace +all build: + $(SUBDIRS-loop) +clean clobber:: + $(SUBDIRS-loop) + +AUTO_FILES_JAVA_DIRS = sun/tracing + +# +# Rules. +# +include $(BUILDDIR)/common/Classes.gmk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/sun/tracing/dtrace/Makefile Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,59 @@ +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. +# + +# +# Makefile for building dtrace extension +# +BUILDDIR = ../../.. +PACKAGE = sun.tracing.dtrace +LIBRARY = jsdt +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +# +# Use mapfile +# +FILES_m = mapfile-vers +include $(BUILDDIR)/common/Mapfile-vers.gmk + +NATIVE_DTRACE_DIR=native/sun/tracing/dtrace + +SRCDIR=$(SHARE_SRC)/$(NATIVE_DTRACE_DIR) +PSRCDIR=$(PLATFORM_SRC)/$(NATIVE_DTRACE_DIR) + +FILES_c = JVM.c jvm_symbols_md.c + +FILES_java = \ + sun/tracing/dtrace/Activation.java \ + sun/tracing/dtrace/DTraceProvider.java \ + sun/tracing/dtrace/DTraceProbe.java \ + sun/tracing/dtrace/DTraceProviderFactory.java \ + sun/tracing/dtrace/JVM.java + +FILES_export = $(FILES_java) + +ifeq ($(PLATFORM), linux) +OTHER_LDLIBS += -ldl +endif + +# +# Use JNI for generating header files +# +JAVAHFLAGS += -jni + +# +# Don't need to link against -ljava +# +JAVALIB= + +# +# Rules. +# +include $(BUILDDIR)/common/Library.gmk + +# +# Add to ambient vpath so we pick up the library files +# +vpath %.c $(SRCDIR):$(PSRCDIR)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/sun/tracing/dtrace/mapfile-vers Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,19 @@ +# +#ident "@(#)mapfile-vers 1.1 07/08/14" +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + Java_sun_tracing_dtrace_JVM_isSupported0; + Java_sun_tracing_dtrace_JVM_activate0; + Java_sun_tracing_dtrace_JVM_dispose0; + Java_sun_tracing_dtrace_JVM_isEnabled0; + Java_sun_tracing_dtrace_JVM_defineClass0; + local: + *; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/Probe.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,51 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing; + +/** + * The {@code Probe} interface represents a tracepoint. + * + * A {@code Probe} instance is obtained by calling the + * {@code Provider.getProbe()} method of a provider instance created by + * {@code ProviderFactory.createProvider()}. A {@code Probe} can be used to + * trigger a probe manually (provided the correct arguments are passed to + * it), or to check a probe to see if anything is currently tracing it. + * <p> + * A tracing check can be used to avoid lengthy work that might be + * needed to set up the probe's arguments. However, checking + * whether the probe is enabled generally takes the same amount of time + * as actually triggering the probe. So, you should only check a probe's status + * without triggering it if setting up the arguments is very expensive. + * <p> + * Users do not need to implement this interface: instances are + * created automatically by the system when a {@code Provider)} instance is + * created. + * <p> + * @since 1.7 + */ + +public interface Probe { + /** + * Checks whether there is an active trace of this probe. + * + * @return true if an active trace is detected. + */ + boolean isEnabled(); + + /** + * Determines whether a tracepoint is enabled. + * + * Typically, users do not need to use this method. It is called + * automatically when a Provider's instance method is called. Calls to + * this method expect the arguments to match the declared parameters for + * the method associated with the probe. + * + * @param args the parameters to pass to the method. + * @throws IllegalArgumentException if the provided parameters do not + * match the method declaration for this probe. + */ + void trigger(Object ... args); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/ProbeName.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,28 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * An annotation used to override the name of a probe. + * <p> + * This annotation can be added to a method in a user-defined {@code Provider} + * interface, to set the name that will be used for the generated probe + * associated with that method. Without this annotation, the name will be the + * name of the method. + * <p> + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ProbeName { + String value(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/Provider.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,56 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing; + +/** + * {@code Provider} is a superinterface for user-defined tracing providers. + * <p> + * To define tracepoints, users must extend this interface + * and then use a {@code ProviderFactory} to create an instance of the + * newly-defined interface. Each method in the defined interface represents a + * tracepoint (or probe), which can be triggered by calling the associated + * method on the returned instance. + * <p> + * This interface also contains a {@code getProbe()} method, which can be + * used to get direct handles to the {@code Probe} objects themselves. + * {@code Probe} objects can be triggered manually, or they can be queried to + * check their state. + * <p> + * When an application has finished triggering probes, it should call + * {@code dispose()} to free up any system resources associated with the + * Provider. + * <p> + * All methods declared in a subclass of this interface should have a + * {@code void} return type. Methods can have parameters, and when called the + * values of the arguments will be passed to the tracing implementation. + * If any methods do not have a {@code void} return type, an + * {@code java.lang.IllegalArgumentException} will be thrown when the + * provider is registered. + * @since 1.7 + */ + +public interface Provider { + /** + * Retrieves a reference to a Probe object, which is used to check status + * or to trigger the probe manually. + * + * If the provided method parameter is not a method of the provider + * interface, or if the provider interface has been disposed, then + * this returns null + * + * @param method a method declared in the provider. + * @return the specified probe represented by that method, or null. + */ + Probe getProbe(java.lang.reflect.Method method); + + /** + * Disposes system resources associated with this provider. + * + * After calling this method, triggering the probes will have no effect. + * Additional calls to this method after the first call are ignored. + */ + void dispose(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/ProviderFactory.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,110 @@ + +package com.sun.tracing; + +import java.util.HashSet; +import java.io.PrintStream; +import java.lang.reflect.Field; +import java.util.logging.Logger; + +import sun.tracing.NullProviderFactory; +import sun.tracing.PrintStreamProviderFactory; +import sun.tracing.MultiplexProviderFactory; +import sun.tracing.dtrace.DTraceProviderFactory; + +/** + * {@code ProviderFactory} is a factory class used to create instances of + * providers. + * + * To enable tracing in an application, this class must be used to create + * instances of the provider interfaces defined by users. + * The system-defined factory is obtained by using the + * {@code getDefaultFactory()} static method. The resulting instance can be + * used to create any number of providers. + * + * @since 1.7 + */ +public abstract class ProviderFactory { + + protected ProviderFactory() {} + + /** + * Creates an implementation of a Provider interface. + * + * @param cls the provider interface to be defined. + * @return an implementation of {@code cls}, whose methods, when called, + * will trigger tracepoints in the application. + * @throws NullPointerException if cls is null + * @throws IllegalArgumentException if the class definition contains + * non-void methods + */ + public abstract <T extends Provider> T createProvider(Class<T> cls); + + /** + * Returns an implementation of a {@code ProviderFactory} which + * creates instances of Providers. + * + * The created Provider instances will be linked to all appropriate + * and enabled system-defined tracing mechanisms in the JDK. + * + * @return a {@code ProviderFactory} that is used to create Providers. + */ + public static ProviderFactory getDefaultFactory() { + HashSet<ProviderFactory> factories = new HashSet<ProviderFactory>(); + + // Try to instantiate a DTraceProviderFactory + String prop = null; + try { prop = System.getProperty("com.sun.tracing.dtrace"); } + catch (java.security.AccessControlException e) { + Logger.getAnonymousLogger().fine( + "Cannot access property com.sun.tracing.dtrace"); + } + if ( (prop == null || !prop.equals("disable")) && + DTraceProviderFactory.isSupported() ) { + factories.add(new DTraceProviderFactory()); + } + + // Try to instantiate an output stream factory + try { prop = System.getProperty("sun.tracing.stream"); } + catch (java.security.AccessControlException e) { + Logger.getAnonymousLogger().fine( + "Cannot access property sun.tracing.stream"); + } + if (prop != null) { + for (String spec : prop.split(",")) { + PrintStream ps = getPrintStreamFromSpec(spec); + if (ps != null) { + factories.add(new PrintStreamProviderFactory(ps)); + } + } + } + + // See how many factories we instantiated, and return an appropriate + // factory that encapsulates that. + if (factories.size() == 0) { + return new NullProviderFactory(); + } else if (factories.size() == 1) { + return factories.toArray(new ProviderFactory[1])[0]; + } else { + return new MultiplexProviderFactory(factories); + } + } + + private static PrintStream getPrintStreamFromSpec(String spec) { + try { + // spec is in the form of <class>.<field>, where <class> is + // a fully specified class name, and <field> is a static member + // in that class. The <field> must be a 'PrintStream' or subtype + // in order to be used. + int fieldpos = spec.lastIndexOf('.'); + Class<?> cls = Class.forName(spec.substring(0, fieldpos)); + Field f = cls.getField(spec.substring(fieldpos + 1)); + Class<?> fieldType = f.getType(); + return (PrintStream)f.get(null); + } catch (Exception e) { + Logger.getAnonymousLogger().warning( + "Could not parse sun.tracing.stream property: " + e); + } + return null; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/ProviderName.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,28 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * An annotation used to specify the name of a provider. + * <p> + * This annotation can be added to a user-defined {@code Provider} + * interface, to set the name that will be used + * for the provider in the generated probes. Without this annotation, + * the simple class name of the provider interface is used. + * <p> + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ProviderName { + String value(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/ArgsAttributes.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,33 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + + +/** + * This annotation describes the interface attributes of the probe arguments in + * a single provider. + * + * This annotation can be added to a user-defined {@code Provider} specification + * interface to set the stability attributes of the probe arguments, for + * all the probes specified in that provider. + * <p> + * If this annotation is not present, the interface attributes for the + * arguments are Private/Private/Unknown. + * <p> + * @see <a href="http://docs.sun.com/app/docs/doc/817-6223/6mlkidlnp?a=view">Solaris Dynamic Tracing Guide, Chapter 39: Stability</a> + * @since 1.7 + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface ArgsAttributes { + Attributes value(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/Attributes.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + + +/** + * This annotation describes the interface's field attributes + * for the probes in a provider. + * + * This annotation provides the contents of field-specific annotations + * that specify the stability attributes and dependency class of a + * particular field, for the probes in a provider. + * <p> + * The default interface attributes for unspecified fields is + * Private/Private/Unknown. + * <p> + * @see <a href="http://docs.sun.com/app/docs/doc/817-6223/6mlkidlnp?a=view">Solaris Dynamic Tracing Guide, Chapter 39: Stability</a> + * @since 1.7 + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target({}) +public @interface Attributes { + /** + * The stability level of the name. + */ + StabilityLevel name() default StabilityLevel.PRIVATE; + + /** + * The stability level of the data. + */ + StabilityLevel data() default StabilityLevel.PRIVATE; + + /** + * The interface attribute's dependency class. + */ + DependencyClass dependency() default DependencyClass.UNKNOWN; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/DependencyClass.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,57 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing.dtrace; + +/** + * Enumeration for the DTrace dependency classes. + * + * @see <a href="http://docs.sun.com/app/docs/doc/817-6223/6mlkidlnp?a=view">Solaris Dynamic Tracing Guide for details, Chapter 39: Stability</a> + * @since 1.7 + */ +public enum DependencyClass { + /** + * The interface has an unknown set of architectural dependencies. + */ + UNKNOWN (0), + /** + * The interface is specific to the CPU model of the current system. + */ + CPU (1), + /** + * The interface is specific to the hardware platform of the current + * system. + */ + PLATFORM (2), + /** + * The interface is specific to the hardware platform group of the + * current system. + */ + GROUP (3), + /** + * The interface is specific to the instruction set architecture (ISA) + * supported by the microprocessors on this system. + */ + ISA (4), + /** + * The interface is common to all Solaris systems regardless of the + * underlying hardware. + */ + COMMON (5); + + public String toDisplayString() { + return toString().substring(0,1) + + toString().substring(1).toLowerCase(); + } + + public int getEncoding() { return encoding; } + + private int encoding; + + private DependencyClass(int encoding) { + this.encoding = encoding; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/FunctionAttributes.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * This annotation describes the interface attributes of the + * {@code function} field for a single provider. + * + * This annotation can be added to a user-defined {@code Provider} specification + * interface to set the stability attributes of the {@code function} field for + * all probes specified in that provider. + * <p> + * If this annotation is not present, the interface attributes for the + * {@code function} field are Private/Private/Unknown. + * <p> + * @see <a href="http://docs.sun.com/app/docs/doc/817-6223/6mlkidlnp?a=view">Solaris Dynamic Tracing Guide, Chapter 39: Stability</a> + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface FunctionAttributes { + Attributes value(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/FunctionName.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,27 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * An annotation used to specify the {@code function} field for a DTrace probe. + * + * This annotation can be added to a method in a user-defined Provider + * specification interface to set the {@code function} field that is used + * for the generated DTrace probe associated with that method. + * <p> + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface FunctionName { + String value(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/ModuleAttributes.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * This annotation is used to describe the interface attributes of the + * {@code module} field for a single provider. + * + * This annotation can be added to a user-defined Provider specification + * interface to set the stability attributes of the {@code module} field for + * all probes specified in that provider. + * <p> + * If this annotation is not present, the interface attributes for the + * {@code module} field is Private/Private/Unknown. + * <p> + * @see <a href="http://docs.sun.com/app/docs/doc/817-6223/6mlkidlnp?a=view">Solaris Dynamic Tracing Guide, Chapter 39: Stability</a> + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface ModuleAttributes { + Attributes value(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/ModuleName.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,27 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * An annotation used to specify the {@code module} field for a DTrace probe. + * + * This annotation can be added to a method in a user-defined Provider + * specification interface to set the {@code module} field that will be used + * for the generated DTrace probe associated with that method. + * <p> + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ModuleName { + String value(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/NameAttributes.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * This annotation describes the interface attributes of the + * {@code name} field for a single provider. + * + * This annotation can be added to a user-defined Provider specification + * interface to set the stability attributes of the {@code name} field for + * all probes specified in that provider. + * <p> + * If this annotation is not present, the interface attributes for the + * {@code name} field will be Private/Private/Unknown. + * <p> + * @see <a href="http://docs.sun.com/app/docs/doc/817-6223/6mlkidlnp?a=view">Solaris Dynamic Tracing Guide, Chapter 39: Stability</a> + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface NameAttributes { + Attributes value(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/ProviderAttributes.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * This annotation is used to describe the interface attributes of the + * {@code provider} field for a single provider. + * + * This annotation can be added to a user-defined Provider specification + * interface to set the stability attributes of the {@code provider} field for + * all probes specified in that provider. + * <p> + * If this annotation is not present, the interface attributes for the + * {@code provider} field will be Private/Private/Unknown. + * <p> + * @see <a href="http://docs.sun.com/app/docs/doc/817-6223/6mlkidlnp?a=view">Solaris Dynamic Tracing Guide, Chapter 39: Stability</a> + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface ProviderAttributes { + Attributes value(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/StabilityLevel.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,68 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package com.sun.tracing.dtrace; + +/** + * Enumeration for the DTrace stability levels. + * + * @see <a href="http://docs.sun.com/app/docs/doc/817-6223/6mlkidlnp?a=view">Solaris Dynamic Tracing Guide, Chapter 39: Stability</a> + * @since 1.7 + */ +public enum StabilityLevel { + /** + * The interface is private to DTrace and represents an implementation + * detail of DTrace. + */ + INTERNAL (0), + /** + * The interface is private to Sun for use by other Sun products. It is + * not yet publicly documented for use by customers and ISVs. + */ + PRIVATE (1), + /** + * The interface is supported in the current release but is scheduled + * to be removed, most likely in a future minor release. + */ + OBSOLETE (2), + /** + * The interface is controlled by an entity other than Sun. + */ + EXTERNAL (3), + /** + * The interface gives developers early access to new or + * rapidly changing technology or to an implementation artifact that is + * essential for observing or debugging system behavior. A more + * stable solution is anticipated in the future. + */ + UNSTABLE (4), + /** + * The interface might eventually become Standard or Stable but is + * still in transition. + */ + EVOLVING (5), + /** + * The interface is a mature interface under Sun's control. + */ + STABLE (6), + /** + * The interface complies with an industry standard. + */ + STANDARD (7); + + String toDisplayString() { + return toString().substring(0,1) + + toString().substring(1).toLowerCase(); + } + + public int getEncoding() { return encoding; } + + private int encoding; + + private StabilityLevel(int encoding) { + this.encoding = encoding; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/package-info.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,62 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/** + * This package contains annotations and enumerations that are used to + * add DTrace-specific information to a tracing provider. + * <p> + * The DTrace-specific annotations modify the attributes of a DTrace provider + * implementation when it is used by the tracing subsystem. The annotations are + * added to a {@code com.sun.tracing} provider specification to control + * specific attributes of the provider as it relates to DTrace. + * <p> + * Any other tracing subsystems supported by the system will ignore these + * annotations. + * <p> + * DTrace probes have additional fields and stability attributes that are + * not accounted for in the generic tracing package. If unspecified, the + * default values are used for the stability and dependency attributes of + * probes, as well as for the module and field names of the generated probes. + * The values can be specified by adding the appropriate annotations to the + * provider specification. + * <p> + * The {@code FunctionName} annotation is used to annotate the tracepoint + * methods defined in the provider specification. The value of this annotation + * is used as the {@code function} field in the generated DTrace probes. It + * is typically set to the name of the enclosing function where the + * tracepoint is triggered. + * <p> + * The {@code ModuleName} annotation is used to annotate the provider + * specification itself and applies to all the probes in the provider. It + * sets the value of the {@code module} field in the generated DTrace probes. + * <p> + * The remaining annotations, are also applied to the provider itself, and + * are used to set the stability and dependency attributes of all probes in + * that provider. Each probe field and the probe arguments can be + * independently assigned interface attributes to control the stability + * ratings of the probes. + * <p> + * Here is an example of how to declare a provider, specifying additional DTrace + * data: +<PRE> + @ProviderName("my_app_provider") + @ModuleName("app.jar") + @ProviderAttributes(@Attributes={ + name=StabilityLevel.STABLE,data=StabilityLevel.STABLE, + dependency=DependencyClass.COMMON}) + @ProbeAttributes(@Attributes={ + name=StabilityLevel.STABLE,data=StabilityLevel.STABLE, + dependency=DependencyClass.COMMON}) + @ModuleAttributes(@Attributes={name=StabilityLevel.UNSTABLE}) + public class MyProvider { + @FunctionName("main") void startProbe(); + } +</PRE> + * <p> + * @see <a href="http://docs.sun.com/app/docs/doc/817-6223/6mlkidlms?a=view">Solaris Dynamic Tracing Guide, Chapter 34: Statically Defined Tracing for User Applications</a> + * @see <a href="http://docs.sun.com/app/docs/doc/817-6223/6mlkidlnp?a=view">Solaris Dynamic Tracing Guide, Chapter 39: Stability</a> + */ + +package com.sun.tracing.dtrace;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tracing/package-info.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,163 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/** + * 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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/MultiplexProviderFactory.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,124 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package sun.tracing; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Logger; + +import com.sun.tracing.ProviderFactory; +import com.sun.tracing.Provider; +import com.sun.tracing.Probe; + +/** + * Factory class to create tracing Providers. + * + * This factory creates a "multiplex provider", which is a provider that + * encapsulates a list of providers and whose probes trigger a corresponding + * trigger in each of the encapsulated providers' probes. + * + * This is used when there are multiple tracing frameworks activated at once. + * A user-defined provider gets implementation for each of the activated + * frameworks and this multiplex framework is what is ultimately passed + * back to the user. All probe triggers are multiplexed to each + * active framework. + * + * @since 1.7 + */ +public class MultiplexProviderFactory extends ProviderFactory { + + private Set<ProviderFactory> factories; + + public MultiplexProviderFactory(Set<ProviderFactory> factories) { + this.factories = factories; + } + + public <T extends Provider> T createProvider(Class<T> cls) { + HashSet<Provider> providers = new HashSet<Provider>(); + for (ProviderFactory factory : factories) { + providers.add(factory.createProvider(cls)); + } + MultiplexProvider provider = new MultiplexProvider(cls, providers); + try { + provider.init(); + } catch (Exception e) { + // Probably a permission problem (can't get declared members) + Logger.getAnonymousLogger().warning( + "Could not initialize tracing provider: " + e.getMessage()); + } + return provider.newProxyInstance(); + } +} + +class MultiplexProvider extends ProviderSkeleton { + + private Set<Provider> providers; + + protected ProbeSkeleton createProbe(Method m) { + return new MultiplexProbe(m, providers); + } + + MultiplexProvider(Class<? extends Provider> type, Set<Provider> providers) { + super(type); + this.providers = providers; + } + + public void dispose() { + for (Provider p : providers) { + p.dispose(); + } + super.dispose(); + } +} + +class MultiplexProbe extends ProbeSkeleton { + + private Set<Probe> probes; + + MultiplexProbe(Method m, Set<Provider> providers) { + super(m.getParameterTypes()); + probes = new HashSet<Probe>(); + for (Provider p : providers) { + Probe probe = p.getProbe(m); + if (probe != null) { + probes.add(probe); + } + } + } + + public boolean isEnabled() { + for (Probe p : probes) { + if (p.isEnabled()) { + return true; + } + } + return false; + } + + public void uncheckedTrigger(Object[] args) { + for (Probe p : probes) { + try { + // try the fast path + ProbeSkeleton ps = (ProbeSkeleton)p; + ps.uncheckedTrigger(args); + } catch (ClassCastException e) { + // Probe.trigger takes an "Object ..." varargs parameter, + // so we can't call it directly. + try { + Method m = Probe.class.getMethod( + "trigger", Class.forName("[java.lang.Object")); + m.invoke(p, args); + } catch (Exception e1) { + assert false; // This shouldn't happen + } + } + } + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/NullProviderFactory.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,71 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package sun.tracing; + +import java.lang.reflect.Method; +import java.util.logging.Logger; + +import com.sun.tracing.ProviderFactory; +import com.sun.tracing.Provider; + +/** + * Factory class to create tracing Providers. + * + * This factory will create tracing instances that do nothing. + * It is used when no tracing is desired, but Provider instances still + * must be generated so that tracing calls in the application continue to + * run. + * + * @since 1.7 + */ +public class NullProviderFactory extends ProviderFactory { + + /** + * Creates and returns a Null provider. + * + * See comments at {@code ProviderSkeleton.createProvider()} for more + * details. + * + * @return a provider whose probe trigger are no-ops. + */ + public <T extends Provider> T createProvider(Class<T> cls) { + NullProvider provider = new NullProvider(cls); + try { + provider.init(); + } catch (Exception e) { + // Probably a permission problem (can't get declared members) + Logger.getAnonymousLogger().warning( + "Could not initialize tracing provider: " + e.getMessage()); + } + return provider.newProxyInstance(); + } +} + +class NullProvider extends ProviderSkeleton { + + NullProvider(Class<? extends Provider> type) { + super(type); + } + + protected ProbeSkeleton createProbe(Method m) { + return new NullProbe(m.getParameterTypes()); + } +} + +class NullProbe extends ProbeSkeleton { + + public NullProbe(Class<?>[] parameters) { + super(parameters); + } + + public boolean isEnabled() { + return false; + } + + public void uncheckedTrigger(Object[] args) { + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/PrintStreamProviderFactory.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,107 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package sun.tracing; + +import java.lang.reflect.Method; +import java.io.PrintStream; +import java.util.HashMap; +import java.util.logging.Logger; + +import com.sun.tracing.ProviderFactory; +import com.sun.tracing.Provider; +import com.sun.tracing.ProviderName; +import com.sun.tracing.Probe; +import com.sun.tracing.ProbeName; + +/** + * Factory class to create tracing Providers. + * + * This factory will create tracing instances that print to a PrintStream + * when activated. + * + * @since 1.7 + */ +public class PrintStreamProviderFactory extends ProviderFactory { + + private PrintStream stream; + + public PrintStreamProviderFactory(PrintStream stream) { + this.stream = stream; + } + + public <T extends Provider> T createProvider(Class<T> cls) { + PrintStreamProvider provider = new PrintStreamProvider(cls, stream); + try { + provider.init(); + } catch (Exception e) { + // Probably a permission problem (can't get declared members) + Logger.getAnonymousLogger().warning( + "Could not initialize tracing provider: " + e.getMessage()); + } + return provider.newProxyInstance(); + } +} + +class PrintStreamProvider extends ProviderSkeleton { + + private PrintStream stream; + private String providerName; + + protected ProbeSkeleton createProbe(Method m) { + String probeName = getAnnotationString(m, ProbeName.class, m.getName()); + return new PrintStreamProbe(this, probeName, m.getParameterTypes()); + } + + PrintStreamProvider(Class<? extends Provider> type, PrintStream stream) { + super(type); + this.stream = stream; + this.providerName = getProviderName(); + } + + PrintStream getStream() { + return stream; + } + + String getName() { + return providerName; + } +} + +class PrintStreamProbe extends ProbeSkeleton { + + private PrintStreamProvider provider; + private String name; + + PrintStreamProbe(PrintStreamProvider p, String name, Class<?>[] params) { + super(params); + this.provider = p; + this.name = name; + } + + public boolean isEnabled() { + return true; + } + + public void uncheckedTrigger(Object[] args) { + StringBuffer sb = new StringBuffer(); + sb.append(provider.getName()); + sb.append("."); + sb.append(name); + sb.append("("); + boolean first = true; + for (Object o : args) { + if (first == false) { + sb.append(","); + } else { + first = false; + } + sb.append(o.toString()); + } + sb.append(")"); + provider.getStream().println(sb.toString()); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/ProbeSkeleton.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,70 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package sun.tracing; + +import java.lang.reflect.Method; +import java.lang.reflect.Field; +import com.sun.tracing.Probe; + +/** + * Provides common code for implementation of {@code Probe} classes. + * + * @since 1.7 + */ +public abstract class ProbeSkeleton implements Probe { + + protected Class<?>[] parameters; + + protected ProbeSkeleton(Class<?>[] parameters) { + this.parameters = parameters; + } + + public abstract boolean isEnabled(); // framework-dependent + + /** + * Triggers the probe with verified arguments. + * + * The caller of this method must have already determined that the + * arity and types of the arguments match what the probe was + * declared with. + */ + public abstract void uncheckedTrigger(Object[] args); // framework-dependent + + private static boolean isAssignable(Object o, Class<?> formal) { + if (o != null) { + if ( !formal.isInstance(o) ) { + if ( formal.isPrimitive() ) { // o might be a boxed primitive + try { + // Yuck. There must be a better way of doing this + Field f = o.getClass().getField("TYPE"); + return formal.isAssignableFrom((Class<?>)f.get(null)); + } catch (Exception e) { + /* fall-through. */ + } + } + return false; + } + } + return true; + } + + /** + * Performs a type-check of the parameters before triggering the probe. + */ + public void trigger(Object ... args) { + if (args.length != parameters.length) { + throw new IllegalArgumentException("Wrong number of arguments"); + } else { + for (int i = 0; i < parameters.length; ++i) { + if ( !isAssignable(args[i], parameters[i]) ) { + throw new IllegalArgumentException( + "Wrong type of argument at position " + i); + } + } + uncheckedTrigger(args); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/ProviderSkeleton.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,223 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package sun.tracing; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.AnnotatedElement; +import java.lang.annotation.Annotation; +import java.util.HashMap; + +import com.sun.tracing.Provider; +import com.sun.tracing.Probe; +import com.sun.tracing.ProviderName; + +/** + * Provides a common code for implementation of {@code Provider} classes. + * + * Each tracing subsystem needs to provide three classes, a factory + * (derived from {@code ProviderFactory}, a provider (a subclass of + * {@code Provider}, and a probe type (subclass of {@code ProbeSkeleton}). + * + * The factory object takes a user-defined interface and provides an + * implementation of it whose method calls will trigger probes in the + * tracing framework. + * + * The framework's provider class, and its instances, are not seen by the + * user at all -- they usually sit in the background and receive and dispatch + * the calls to the user's provider interface. The {@code ProviderSkeleton} + * class provides almost all of the implementation needed by a framework + * provider. Framework providers must only provide a constructor and + * disposal method, and implement the {@code createProbe} method to create + * an appropriate {@code ProbeSkeleton} subclass. + * + * The framework's probe class provides the implementation of the two + * probe methods, {@code isEnabled()} and {@code uncheckedTrigger()}. Both are + * framework-dependent implementations. + * + * @since 1.7 + */ + +public abstract class ProviderSkeleton implements InvocationHandler, Provider { + + protected boolean active; // set to false after dispose() is called + protected Class<? extends Provider> providerType; // user's interface + protected HashMap<Method, ProbeSkeleton> probes; // methods to probes + + + /** + * Creates a framework-specific probe subtype. + * + * This method is implemented by the framework's provider and returns + * framework-specific probes for a method. + * + * @param method A method in the user's interface + * @return a subclass of ProbeSkeleton for the particular framework. + */ + protected abstract ProbeSkeleton createProbe(Method method); + + /** + * Initializes the provider. + * + * @param type the user's interface + */ + protected ProviderSkeleton(Class<? extends Provider> type) { + this.active = false; // in case of some error during initialization + this.providerType = type; + this.probes = new HashMap<Method,ProbeSkeleton>(); + } + + /** + * Post-constructor initialization routine. + * + * Subclass instances must be initialized before they can create probes. + * It is up to the factory implementations to call this after construction. + */ + public void init() { + for (Method m : providerType.getDeclaredMethods()) { + if ( m.getReturnType() != Void.TYPE ) { + throw new IllegalArgumentException( + "Return value of method is not void"); + } else { + probes.put(m, createProbe(m)); + } + } + this.active = true; + } + + /** + * Magic routine which creates an implementation of the user's interface. + * + * This method creates the instance of the user's interface which is + * passed back to the user. Every call upon that interface will be + * redirected to the {@code invoke()} method of this class (until + * overridden by the VM). + * + * @return an implementation of the user's interface + */ + @SuppressWarnings("unchecked") + public <T extends Provider> T newProxyInstance() { + return (T)Proxy.newProxyInstance(providerType.getClassLoader(), + new Class<?>[] { providerType }, this); + } + + /** + * Triggers a framework probe when a user interface method is called. + * + * This method dispatches a user interface method call to the appropriate + * probe associated with this framework. + * + * If the invoked method is not a user-defined member of the interface, + * then it is a member of {@code Provider} or {@code Object} and we + * invoke the method directly. + * + * @param proxy the instance whose method was invoked + * @param method the method that was called + * @param args the arguments passed in the call. + * @return always null, if the method is a user-defined probe + */ + public Object invoke(Object proxy, Method method, Object[] args) { + if (method.getDeclaringClass() != providerType) { + try { + return method.invoke(this, args); + } catch (IllegalAccessException e) { + assert false; + } catch (InvocationTargetException e) { + assert false; + } + } else if (active) { + ProbeSkeleton p = probes.get(method); + if (p != null) { + // Skips argument check -- already done by javac + p.uncheckedTrigger(args); + } + } + return null; + } + + /** + * Direct accessor for {@code Probe} objects. + * + * @param m the method corresponding to a probe + * @return the method associated probe object, or null + */ + public Probe getProbe(Method m) { + return active ? probes.get(m) : null; + } + + /** + * Default provider disposal method. + * + * This is overridden in subclasses as needed. + */ + public void dispose() { + active = false; + probes.clear(); + } + + /** + * Gets the user-specified provider name for the user's interface. + * + * If the user's interface has a {@ProviderName} annotation, that value + * is used. Otherwise we use the simple name of the user interface's class. + * @return the provider name + */ + protected String getProviderName() { + return getAnnotationString( + providerType, ProviderName.class, providerType.getSimpleName()); + } + + /** + * Utility method for getting a string value from an annotation. + * + * Used for getting a string value from an annotation with a 'value' method. + * + * @param element the element that was annotated, either a class or method + * @param annotation the class of the annotation we're interested in + * @param defaultValue the value to return if the annotation doesn't + * exist, doesn't have a "value", or the value is empty. + */ + protected static String getAnnotationString( + AnnotatedElement element, Class<? extends Annotation> annotation, + String defaultValue) { + String ret = (String)getAnnotationValue( + element, annotation, "value", defaultValue); + return ret.isEmpty() ? defaultValue : ret; + } + + /** + * Utility method for calling an arbitrary method in an annotation. + * + * @param element the element that was annotated, either a class or method + * @param annotation the class of the annotation we're interested in + * @param methodName the name of the method in the annotation we wish + * to call. + * @param defaultValue the value to return if the annotation doesn't + * exist, or we couldn't invoke the method for some reason. + * @return the result of calling the annotation method, or the default. + */ + protected static Object getAnnotationValue( + AnnotatedElement element, Class<? extends Annotation> annotation, + String methodName, Object defaultValue) { + Object ret = defaultValue; + try { + Method m = annotation.getMethod(methodName); + Annotation a = element.getAnnotation(annotation); + ret = m.invoke(a); + } catch (NoSuchMethodException e) { + assert false; + } catch (IllegalAccessException e) { + assert false; + } catch (InvocationTargetException e) { + assert false; + } catch (NullPointerException e) { + assert false; + } + return ret; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/dtrace/Activation.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,87 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package sun.tracing.dtrace; + +import java.lang.ref.WeakReference; +import java.lang.ref.ReferenceQueue; +import java.security.Permission; +import java.util.HashSet; + +class Activation { + private SystemResource resource; + private int referenceCount; + + Activation(String moduleName, DTraceProvider[] providers) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + Permission perm = + new RuntimePermission("com.sun.tracing.dtrace.createProvider"); + security.checkPermission(perm); + } + referenceCount = providers.length; + for (DTraceProvider p : providers) { + p.setActivation(this); + } + resource = new SystemResource( + this, JVM.activate(moduleName, providers)); + } + + void disposeProvider(DTraceProvider p) { + if (--referenceCount == 0) { + resource.dispose(); + } + } +} + +/** + * The native resource part of an Activation. + * + * This holds the native handle. + * + * If the user loses a reference to a set of Providers without disposing them, + * and GC determines the Activation is unreachable, then the next + * activation or flush call will automatically dispose the unreachable objects + * + * The SystemResource instances are creating during activation, and + * unattached during disposal. When created, they always have a + * strong reference to them via the {@code resources} static member. Explicit + * {@code dispose} calls will unregister the native resource and remove + * references to the SystemResource object. Absent an explicit dispose, + * when their associated Activation object becomes garbage, the SystemResource + * object will be enqueued on the reference queue and disposed at the + * next call to {@code flush}. + */ +class SystemResource extends WeakReference<Activation> { + + private long handle; + + private static ReferenceQueue<Activation> referenceQueue = + referenceQueue = new ReferenceQueue<Activation>(); + static HashSet<SystemResource> resources = new HashSet<SystemResource>(); + + SystemResource(Activation activation, long handle) { + super(activation, referenceQueue); + this.handle = handle; + flush(); + resources.add(this); + } + + void dispose() { + JVM.dispose(handle); + resources.remove(this); + handle = 0; + } + + static void flush() { + SystemResource resource = null; + while ((resource = (SystemResource)referenceQueue.poll()) != null) { + if (resource.handle != 0) { + resource.dispose(); + } + } + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/dtrace/DTraceProbe.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,62 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package sun.tracing.dtrace; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +import sun.tracing.ProbeSkeleton; + +class DTraceProbe extends ProbeSkeleton { + private Object proxy; + private Method declared_method; + private Method implementing_method; + + DTraceProbe(Object proxy, Method m) { + super(m.getParameterTypes()); + this.proxy = proxy; + this.declared_method = m; + try { + // The JVM will override the proxy method's implementation with + // a version that will invoke the probe. + this.implementing_method = proxy.getClass().getMethod( + m.getName(), m.getParameterTypes()); + } catch (NoSuchMethodException e) { + throw new RuntimeException("Internal error, wrong proxy class"); + } + } + + public boolean isEnabled() { + return JVM.isEnabled(implementing_method); + } + + public void uncheckedTrigger(Object[] args) { + try { + implementing_method.invoke(proxy, args); + } catch (IllegalAccessException e) { + assert false; + } catch (InvocationTargetException e) { + assert false; + } + } + + String getProbeName() { + return DTraceProvider.getProbeName(declared_method); + } + + String getFunctionName() { + return DTraceProvider.getFunctionName(declared_method); + } + + Method getMethod() { + return implementing_method; + } + + Class<?>[] getParameterTypes() { + return this.parameters; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/dtrace/DTraceProvider.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,210 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package sun.tracing.dtrace; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.annotation.Annotation; +import java.util.HashMap; + +import sun.tracing.ProviderSkeleton; +import sun.tracing.ProbeSkeleton; +import com.sun.tracing.Provider; +import com.sun.tracing.ProviderName; +import com.sun.tracing.ProbeName; +import com.sun.tracing.dtrace.Attributes; +import com.sun.tracing.dtrace.ModuleName; +import com.sun.tracing.dtrace.FunctionName; +import com.sun.tracing.dtrace.StabilityLevel; +import com.sun.tracing.dtrace.DependencyClass; + +import sun.misc.ProxyGenerator; + +class DTraceProvider extends ProviderSkeleton { + + private Activation activation; + private Object proxy; + + // For proxy generation + private final static Class[] constructorParams = { InvocationHandler.class }; + private final String proxyClassNamePrefix = "$DTraceTracingProxy"; + + static final String DEFAULT_MODULE = "java_tracing"; + static final String DEFAULT_FUNCTION = "unspecified"; + + private static long nextUniqueNumber = 0; + private static synchronized long getUniqueNumber() { + return nextUniqueNumber++; + } + + protected ProbeSkeleton createProbe(Method m) { + return new DTraceProbe(proxy, m); + } + + DTraceProvider(Class<? extends Provider> type) { + super(type); + } + + void setProxy(Object p) { + proxy = p; + } + + void setActivation(Activation a) { + this.activation = a; + } + + public void dispose() { + if (activation != null) { + activation.disposeProvider(this); + activation = null; + } + super.dispose(); + } + + /** + * Magic routine which creates an implementation of the user's interface. + * + * This method uses the ProxyGenerator directly to bypass the + * java.lang.reflect.proxy cache so that we get a unique class each + * time it's called and can't accidently reuse a $Proxy class. + * + * @return an implementation of the user's interface + */ + @SuppressWarnings("unchecked") + public <T extends Provider> T newProxyInstance() { + /* + * Choose a name for the proxy class to generate. + */ + long num = getUniqueNumber(); + + String proxyPkg = ""; + if (!Modifier.isPublic(providerType.getModifiers())) { + String name = providerType.getName(); + int n = name.lastIndexOf('.'); + proxyPkg = ((n == -1) ? "" : name.substring(0, n + 1)); + } + + String proxyName = proxyPkg + proxyClassNamePrefix + num; + + /* + * Generate the specified proxy class. + */ + Class<?> proxyClass = null; + byte[] proxyClassFile = ProxyGenerator.generateProxyClass( + proxyName, new Class<?>[] { providerType }); + try { + proxyClass = JVM.defineClass( + providerType.getClassLoader(), proxyName, + proxyClassFile, 0, proxyClassFile.length); + } catch (ClassFormatError e) { + /* + * A ClassFormatError here means that (barring bugs in the + * proxy class generation code) there was some other + * invalid aspect of the arguments supplied to the proxy + * class creation (such as virtual machine limitations + * exceeded). + */ + throw new IllegalArgumentException(e.toString()); + } + + /* + * Invoke its constructor with the designated invocation handler. + */ + try { + Constructor cons = proxyClass.getConstructor(constructorParams); + return (T)cons.newInstance(new Object[] { this }); + } catch (NoSuchMethodException e) { + throw new InternalError(e.toString()); + } catch (IllegalAccessException e) { + throw new InternalError(e.toString()); + } catch (InstantiationException e) { + throw new InternalError(e.toString()); + } catch (InvocationTargetException e) { + throw new InternalError(e.toString()); + } + } + + // In the normal case, the proxy object's method implementations will call + // this method (it usually calls the ProviderSkeleton's version). That + // method uses the passed 'method' object to lookup the associated + // 'ProbeSkeleton' and calls uncheckedTrigger() on that probe to cause the + // probe to fire. DTrace probes are different in that the proxy class's + // methods are immediately overridden with native code to fire the probe + // directly. So this method should never get invoked. We also wire up the + // DTraceProbe.uncheckedTrigger() method to call the proxy method instead + // of doing the work itself. + public Object invoke(Object proxy, Method method, Object[] args) { + if (method.getDeclaringClass() != providerType) { + try { + return method.invoke(this, args); + } catch (IllegalAccessException e) { + assert false; + } catch (InvocationTargetException e) { + assert false; + } + } else if (active) { + assert false : "This method should have been overridden by the JVM"; + } + return null; + } + + public String getProviderName() { + return super.getProviderName(); + } + + String getModuleName() { + return getAnnotationString( + providerType, ModuleName.class, DEFAULT_MODULE); + } + + static String getProbeName(Method method) { + return getAnnotationString( + method, ProbeName.class, method.getName()); + } + + static String getFunctionName(Method method) { + return getAnnotationString( + method, FunctionName.class, DEFAULT_FUNCTION); + } + + DTraceProbe[] getProbes() { + return probes.values().toArray(new DTraceProbe[0]); + } + + StabilityLevel getNameStabilityFor(Class<? extends Annotation> type) { + Attributes attrs = (Attributes)getAnnotationValue( + providerType, type, "value", null); + if (attrs == null) { + return StabilityLevel.PRIVATE; + } else { + return attrs.name(); + } + } + + StabilityLevel getDataStabilityFor(Class<? extends Annotation> type) { + Attributes attrs = (Attributes)getAnnotationValue( + providerType, type, "value", null); + if (attrs == null) { + return StabilityLevel.PRIVATE; + } else { + return attrs.data(); + } + } + + DependencyClass getDependencyClassFor(Class<? extends Annotation> type) { + Attributes attrs = (Attributes)getAnnotationValue( + providerType, type, "value", null); + if (attrs == null) { + return DependencyClass.UNKNOWN; + } else { + return attrs.dependency(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/dtrace/DTraceProviderFactory.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,144 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package sun.tracing.dtrace; + +import java.util.Map; +import java.util.Set; +import java.util.HashMap; +import java.util.HashSet; +import java.util.logging.Logger; +import java.security.Permission; + +import com.sun.tracing.ProviderFactory; +import com.sun.tracing.Provider; + +/** + * Factory class to create JSDT Providers. + * + * This class contains methods to create an instance of a Provider + * interface which can be used to place tracepoints in an application. + * Method calls upon that instance trigger DTrace probes that + * are visible from DTrace scripts. Such calls have no other + * side effects in the application. + * <p> + * The DTrace script mechanisms for listing and matching probes will not see + * nor match any probes until the provider they reside in is created by a + * call to {@code createProvider()} (or {@code createProviders()}). + * <p> + * Providers that are created should be disposed of when they are no longer + * needed to free up system resources, at which point the associated + * DTrace probes will no longer be available to DTrace. One disposes a + * provider by calling + * {@link com.sun.tracing.Provider#dispose Provider.dispose()} on a + * created provider instance. + * + * @since 1.7 + */ +public final class DTraceProviderFactory extends ProviderFactory { + /** + * Creates an instance of a provider which can then be used to trigger + * DTrace probes. + * + * The provider specification, provided as an argument, should only + * contain methods which have a 'void' return type and String or + * integer-based typed arguments (long, int, short, char, byte, or boolean). + * + * @param cls A user-defined interface which extends {@code Provider}. + * @return An instance of the interface which is used to trigger + * the DTrace probes. + * @throws java.lang.SecurityException if a security manager has been + * installed and it denies + * RuntimePermission("com.sun.dtrace.jsdt.createProvider") + * @throws java.lang.IllegalArgumentException if the interface contains + * methods that do not return null, or that contain arguments that are + * not String or integer types. + */ + public <T extends Provider> T createProvider(Class<T> cls) { + DTraceProvider jsdt = new DTraceProvider(cls); + T proxy = jsdt.newProxyInstance(); + jsdt.setProxy(proxy); + try { + jsdt.init(); + new Activation(jsdt.getModuleName(), new DTraceProvider[] { jsdt }); + } catch (Exception e) { + // Probably a permission problem (can't get declared members) + Logger.getAnonymousLogger().warning( + "Could not initialize tracing provider: " + e.getMessage()); + jsdt.dispose(); + } + return proxy; + } + + /** + * Creates multiple providers at once. + * + * This method batches together a number of provider instantiations. + * It works similarly + * to {@code createProvider}, but operates on a set of providers instead + * of one at a time. This method is in place since some DTrace + * implementations limit the number of times that providers can be + * created. When numerous providers can be created at once with this + * method, it will count only as a single creation point to DTrace, thus + * it uses less system resources. + * <p> + * All of the probes in the providers will be visible to DTrace after + * this call and all will remain visible until all of the providers + * are disposed. + * <p> + * The {@code moduleName} parameter will override any {@code ModuleName} + * annotation associated with any of the providers in the set. + * All of the probes created by this call will share the same + * module name. + * <p> + * @param providers a set of provider specification interfaces + * @param moduleName the module name to associate with all probes + * @return A map which maps the provider interface specification to an + * implementing instance. + * @throws java.lang.SecurityException if a security manager has been + * installed and it denies + * RuntimePermission("com.sun.dtrace.jsdt.createProvider") + * @throws java.lang.IllegalArgumentException if any of the interface + * contains methods that do not return null, or that contain arguments + * that are not String or integer types. + */ + public Map<Class<? extends Provider>,Provider> createProviders( + Set<Class<? extends Provider>> providers, String moduleName) { + HashMap<Class<? extends Provider>,Provider> map = + new HashMap<Class<? extends Provider>,Provider>(); + HashSet<DTraceProvider> jsdts = new HashSet<DTraceProvider>(); + for (Class<? extends Provider> cls : providers) { + DTraceProvider jsdt = new DTraceProvider(cls); + jsdts.add(jsdt); + map.put(cls, jsdt.newProxyInstance()); + } + new Activation(moduleName, jsdts.toArray(new DTraceProvider[0])); + return map; + } + + /** + * Used to check the status of DTrace support in the underlying JVM and + * operating system. + * + * This is an informative method only - the Java-level effects of + * creating providers and triggering probes will not change whether or + * not DTrace is supported by the underlying systems. + * + * @return true if DTrace is supported + */ + public static boolean isSupported() { + try { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + Permission perm = new RuntimePermission( + "com.sun.tracing.dtrace.createProvider"); + security.checkPermission(perm); + } + return JVM.isSupported(); + } catch (SecurityException e) { + return false; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/dtrace/JVM.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,50 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package sun.tracing.dtrace; + +import java.lang.reflect.Method; + +/** + * Container class for JVM interface native methods + * + * @since 1.7 + */ +class JVM { + + static { + java.security.AccessController.doPrivileged( + new sun.security.action.LoadLibraryAction("jsdt")); + } + + static long activate(String moduleName, DTraceProvider[] providers) { + return activate0(moduleName, providers); + } + + static void dispose(long handle) { + dispose0(handle); + } + + static boolean isEnabled(Method m) { + return isEnabled0(m); + } + + static boolean isSupported() { + return isSupported0(); + } + + static Class<?> defineClass( + ClassLoader loader, String name, byte[] b, int off, int len) { + return defineClass0(loader, name, b, off, len); + } + + private static native long activate0( + String moduleName, DTraceProvider[] providers); + private static native void dispose0(long activation_handle); + private static native boolean isEnabled0(Method m); + private static native boolean isSupported0(); + private static native Class<?> defineClass0( + ClassLoader loader, String name, byte[] b, int off, int len); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/tracing/package-info.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,37 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/** + * This package contains internal common code for implementing tracing + * frameworks, and defined a number of existing frameworks. + * <p> + * There are four tracing frameworks currently defined. The "Null" and + * "Multiplex" frameworks are used internally as part of the implementation. + * The "DTrace" framework is the prime consumer framework at the moment, + * while the "PrintStream" framework is a functional, but hidden, framework + * which can be used to track probe firings. All but the "DTrace" framework + * are defined in this package. The "DTrace" framework is implemented in the + * {@code sun.tracing.dtrace} package. + * <p> + * This package also contains the {@code ProviderSkeleton} class, which + * holds most of the common code needed for implementing frameworks. + * <p> + * The "Null" framework is used when there are no other active frameworks. + * It accomplishes absolutely nothing and is merely a placeholder so that + * the application can call the tracing routines without error. + * <p> + * The "Multiplex" framework is used when there are multiple active frameworks. + * It is initialized with the framework factories and create providers and + * probes that dispatch to each active framework in turn. + * <p> + * The "PrintStream" framework is currently a debugging framework which + * dispatches trace calls to a user-defined PrintStream class, defined by + * a property. It may some day be opened up to general use. + * <p> + * See the {@code sun.tracing.dtrace} and {@code com.sun.tracing.dtrace} + * packages for information on the "DTrace" framework. + */ + +package sun.tracing;
--- a/jdk/src/share/javavm/export/jvm.h Tue Apr 15 17:46:47 2008 -0700 +++ b/jdk/src/share/javavm/export/jvm.h Thu Apr 17 22:00:16 2008 -0400 @@ -591,6 +591,80 @@ JNIEXPORT jboolean JNICALL JVM_SupportsCX8(void); +/* + * com.sun.dtrace.jsdt support + */ + +#define JVM_TRACING_DTRACE_VERSION 1 + +/* + * Structure to pass one probe description to JVM + */ +typedef struct { + jmethodID method; + jstring function; + jstring name; + void* reserved[4]; // for future use +} JVM_DTraceProbe; + +/** + * Encapsulates the stability ratings for a DTrace provider field + */ +typedef struct { + jint nameStability; + jint dataStability; + jint dependencyClass; +} JVM_DTraceInterfaceAttributes; + +/* + * Structure to pass one provider description to JVM + */ +typedef struct { + jstring name; + JVM_DTraceProbe* probes; + jint probe_count; + JVM_DTraceInterfaceAttributes providerAttributes; + JVM_DTraceInterfaceAttributes moduleAttributes; + JVM_DTraceInterfaceAttributes functionAttributes; + JVM_DTraceInterfaceAttributes nameAttributes; + JVM_DTraceInterfaceAttributes argsAttributes; + void* reserved[4]; // for future use +} JVM_DTraceProvider; + +/* + * Get the version number the JVM was built with + */ +JNIEXPORT jint JNICALL +JVM_DTraceGetVersion(JNIEnv* env); + +/* + * Register new probe with given signature, return global handle + * + * The version passed in is the version that the library code was + * built with. + */ +JNIEXPORT jlong JNICALL +JVM_DTraceActivate(JNIEnv* env, jint version, jstring module_name, + jint providers_count, JVM_DTraceProvider* providers); + +/* + * Check JSDT probe + */ +JNIEXPORT jboolean JNICALL +JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method); + +/* + * Destroy custom DOF + */ +JNIEXPORT void JNICALL +JVM_DTraceDispose(JNIEnv* env, jlong activation_handle); + +/* + * Check to see if DTrace is supported by OS + */ +JNIEXPORT jboolean JNICALL +JVM_DTraceIsSupported(JNIEnv* env); + /************************************************************************* PART 2: Support for the Verifier and Class File Format Checker ************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/native/sun/tracing/dtrace/JVM.c Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,304 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include <stdlib.h> + +#include "jvm.h" +#include "jni.h" +#include "jni_util.h" + +#include "jvm_symbols.h" +#include "sun_tracing_dtrace_JVM.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static JvmSymbols* jvm_symbols = NULL; + +static void initialize() { + static int initialized = 0; + if (initialized == 0) { + jvm_symbols = lookupJvmSymbols(); + initialized = 1; + } +} + +/* + * Class: sun_tracing_dtrace_JVM + * Method: isSupported0 + * Signature: ()I + */ +JNIEXPORT jboolean JNICALL Java_sun_tracing_dtrace_JVM_isSupported0( + JNIEnv* env, jclass cls) { + initialize(); + if (jvm_symbols != NULL) { + return jvm_symbols->IsSupported(env) ? JNI_TRUE : JNI_FALSE; + } else { + return JNI_FALSE; + } +} + +// Macros that cause an immediate return if we detect an exception +#define CHECK if ((*env)->ExceptionOccurred(env)) { return; } +#define CHECK_(x) if ((*env)->ExceptionOccurred(env)) { return x; } + +static void readProbeData ( + JNIEnv* env, jobject probe, JVM_DTraceProbe* jvm_probe) { + jclass clazz; + jmethodID mid; + jobject method; + + if (jvm_probe == NULL) { + return; // just in case + } + + clazz = (*env)->GetObjectClass(env, probe); CHECK + + mid = (*env)->GetMethodID( + env, clazz, "getFunctionName", "()Ljava/lang/String;"); CHECK + jvm_probe->function = (jstring)(*env)->CallObjectMethod( + env, probe, mid); CHECK + + mid = (*env)->GetMethodID( + env, clazz, "getProbeName", "()Ljava/lang/String;"); CHECK + jvm_probe->name = (jstring)(*env)->CallObjectMethod(env, probe, mid); CHECK + + mid = (*env)->GetMethodID( + env, clazz, "getMethod", "()Ljava/lang/reflect/Method;"); CHECK + method = (*env)->CallObjectMethod(env, probe, mid); CHECK + jvm_probe->method = (*env)->FromReflectedMethod(env, method); CHECK +} + +static void readFieldInterfaceAttributes( + char* annotationName, JNIEnv* env, jobject provider, + JVM_DTraceInterfaceAttributes* attrs) { + jobject result; + jobject result_clazz; + jclass provider_clazz; + jclass annotation_clazz; + jmethodID get; + jmethodID enc; + + provider_clazz = (*env)->GetObjectClass(env, provider); CHECK + annotation_clazz = (*env)->FindClass(env, annotationName); CHECK + + get = (*env)->GetMethodID(env, provider_clazz, "getNameStabilityFor", + "(Ljava/lang/Class;)Lcom/sun/tracing/dtrace/StabilityLevel;"); CHECK + result = (*env)->CallObjectMethod( + env, provider, get, annotation_clazz); CHECK + result_clazz = (*env)->GetObjectClass(env, result); CHECK + enc = (*env)->GetMethodID(env, result_clazz, "getEncoding", "()I"); CHECK + attrs->nameStability = (*env)->CallIntMethod(env, result, enc); CHECK + + get = (*env)->GetMethodID(env, provider_clazz, "getDataStabilityFor", + "(Ljava/lang/Class;)Lcom/sun/tracing/dtrace/StabilityLevel;"); CHECK + result = (*env)->CallObjectMethod( + env, provider, get, annotation_clazz); CHECK + result_clazz = (*env)->GetObjectClass(env, result); CHECK + enc = (*env)->GetMethodID(env, result_clazz, "getEncoding", "()I"); CHECK + attrs->dataStability = (*env)->CallIntMethod(env, result, enc); CHECK + + get = (*env)->GetMethodID(env, provider_clazz, "getDependencyClassFor", + "(Ljava/lang/Class;)Lcom/sun/tracing/dtrace/DependencyClass;"); CHECK + result = (*env)->CallObjectMethod( + env, provider, get, annotation_clazz); CHECK + result_clazz = (*env)->GetObjectClass(env, result); CHECK + enc = (*env)->GetMethodID(env, result_clazz, "getEncoding", "()I"); CHECK + attrs->dependencyClass = (*env)->CallIntMethod(env, result, enc); CHECK +} + +static void readInterfaceAttributes( + JNIEnv* env, jobject provider, JVM_DTraceProvider* jvm_provider) { + readFieldInterfaceAttributes("com/sun/tracing/dtrace/ProviderAttributes", + env, provider, &(jvm_provider->providerAttributes)); + readFieldInterfaceAttributes("com/sun/tracing/dtrace/ModuleAttributes", + env, provider, &(jvm_provider->moduleAttributes)); + readFieldInterfaceAttributes("com/sun/tracing/dtrace/FunctionAttributes", + env, provider, &(jvm_provider->functionAttributes)); + readFieldInterfaceAttributes("com/sun/tracing/dtrace/NameAttributes", + env, provider, &(jvm_provider->nameAttributes)); + readFieldInterfaceAttributes("com/sun/tracing/dtrace/ArgsAttributes", + env, provider, &(jvm_provider->argsAttributes)); +} + +static void readProviderData( + JNIEnv* env, jobject provider, JVM_DTraceProvider* jvm_provider) { + jmethodID mid; + jobjectArray probes; + jsize i; + jclass clazz = (*env)->GetObjectClass(env, provider); CHECK + mid = (*env)->GetMethodID( + env, clazz, "getProbes", "()[Lsun/tracing/dtrace/DTraceProbe;"); CHECK + probes = (jobjectArray)(*env)->CallObjectMethod( + env, provider, mid); CHECK + + // Fill JVM structure, describing provider + jvm_provider->probe_count = (*env)->GetArrayLength(env, probes); CHECK + jvm_provider->probes = (JVM_DTraceProbe*)calloc( + jvm_provider->probe_count, sizeof(*jvm_provider->probes)); + mid = (*env)->GetMethodID( + env, clazz, "getProviderName", "()Ljava/lang/String;"); CHECK + jvm_provider->name = (jstring)(*env)->CallObjectMethod( + env, provider, mid); CHECK + + readInterfaceAttributes(env, provider, jvm_provider); CHECK + + for (i = 0; i < jvm_provider->probe_count; ++i) { + jobject probe = (*env)->GetObjectArrayElement(env, probes, i); CHECK + readProbeData(env, probe, &jvm_provider->probes[i]); CHECK + } +} + +/* + * Class: sun_tracing_dtrace_JVM + * Method: activate0 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_sun_tracing_dtrace_JVM_activate0( + JNIEnv* env, jclass cls, jstring moduleName, jobjectArray providers) { + jlong handle = 0; + jsize num_providers; + jsize i; + JVM_DTraceProvider* jvm_providers; + + initialize(); + + if (jvm_symbols == NULL) { + return 0; + } + + num_providers = (*env)->GetArrayLength(env, providers); CHECK_(0L) + + jvm_providers = (JVM_DTraceProvider*)calloc( + num_providers, sizeof(*jvm_providers)); + + for (i = 0; i < num_providers; ++i) { + JVM_DTraceProvider* p = &(jvm_providers[i]); + jobject provider = (*env)->GetObjectArrayElement( + env, providers, i); + readProviderData(env, provider, p); + } + + handle = jvm_symbols->Activate( + env, JVM_TRACING_DTRACE_VERSION, moduleName, + num_providers, jvm_providers); + + for (i = 0; i < num_providers; ++i) { + JVM_DTraceProvider* p = &(jvm_providers[i]); + free(p->probes); + } + free(jvm_providers); + + return handle; +} + +/* + * Class: sun_tracing_dtrace_JVM + * Method: dispose0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_tracing_dtrace_JVM_dispose0( + JNIEnv* env, jclass cls, jlong handle) { + if (jvm_symbols != NULL && handle != 0) { + jvm_symbols->Dispose(env, handle); + } +} + +/* + * Class: sun_tracing_dtrace_JVM + * Method: isEnabled0 + * Signature: (Ljava/lang/String;Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_sun_tracing_dtrace_JVM_isEnabled0( + JNIEnv* env, jclass cls, jobject method) { + jmethodID mid; + if (jvm_symbols != NULL && method != NULL) { + mid = (*env)->FromReflectedMethod(env, method); + return jvm_symbols->IsProbeEnabled(env, mid); + } + return JNI_FALSE; +} + +/* + * Class: sun_tracing_dtrace_JVM + * Method: defineClass0 + * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BII)Ljava/lang/Class; + * + * The implementation of this native static method is a copy of that of + * the native instance method Java_java_lang_ClassLoader_defineClass0() + * with the implicit "this" parameter becoming the "loader" parameter. + * + * This code was cloned and modified from java_lang_reflect_Proxy + */ +JNIEXPORT jclass JNICALL +Java_sun_tracing_dtrace_JVM_defineClass0( + JNIEnv *env, jclass ignore, jobject loader, jstring name, jbyteArray data, + jint offset, jint length) +{ + jbyte *body; + char *utfName; + jclass result = 0; + char buf[128]; + + if (data == NULL) { + return 0; + } + + /* Work around 4153825. malloc crashes on Solaris when passed a + * negative size. + */ + if (length < 0) { + return 0; + } + + body = (jbyte *)malloc(length); + + if (body == 0) { + return 0; + } + + (*env)->GetByteArrayRegion(env, data, offset, length, body); + + if ((*env)->ExceptionOccurred(env)) + goto free_body; + + if (name != NULL) { + int i; + int len = (*env)->GetStringUTFLength(env, name); + int unicode_len = (*env)->GetStringLength(env, name); + if (len >= sizeof(buf)) { + utfName = malloc(len + 1); + if (utfName == NULL) { + goto free_body; + } + } else { + utfName = buf; + } + (*env)->GetStringUTFRegion(env, name, 0, unicode_len, utfName); + + // Convert '.' to '/' in the package name + for (i = 0; i < unicode_len; ++i) { + if (utfName[i] == '.') { + utfName[i] = '/'; + } + } + } else { + utfName = NULL; + } + + result = (*env)->DefineClass(env, utfName, loader, body, length); + + if (utfName && utfName != buf) + free(utfName); + + free_body: + free(body); + return result; +} + +#ifdef __cplusplus +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/native/sun/tracing/dtrace/jvm_symbols.h Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,30 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#ifndef _JVM_SYMBOLS_H +#define _JVM_SYMBOLS_H + +#include "jvm.h" + +typedef jint (JNICALL* GetVersion_t)(JNIEnv*); +typedef jboolean (JNICALL *IsSupported_t)(JNIEnv*); +typedef jlong (JNICALL* Activate_t)( + JNIEnv*, jint, jstring, jint, JVM_DTraceProvider*); +typedef void (JNICALL *Dispose_t)(JNIEnv*, jlong); +typedef jboolean (JNICALL *IsProbeEnabled_t)(JNIEnv*, jmethodID); + +typedef struct { + GetVersion_t GetVersion; + IsSupported_t IsSupported; + Activate_t Activate; + Dispose_t Dispose; + IsProbeEnabled_t IsProbeEnabled; +} JvmSymbols; + +// Platform-dependent implementation. +// Returns NULL if the symbols are not found +extern JvmSymbols* lookupJvmSymbols(); + +#endif // def _JVM_SYMBOLS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/solaris/native/sun/tracing/dtrace/jvm_symbols_md.c Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,35 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include <dlfcn.h> +#include <stdlib.h> + +#include <jvm.h> + +#include "jvm_symbols.h" + +JvmSymbols* lookupJvmSymbols() { + JvmSymbols* syms = (JvmSymbols*)malloc(sizeof(JvmSymbols)); + if (syms != NULL) { + syms->GetVersion = (GetVersion_t) + dlsym(RTLD_DEFAULT, "JVM_DTraceGetVersion"); + syms->IsSupported = (IsSupported_t) + dlsym(RTLD_DEFAULT, "JVM_DTraceIsSupported"); + syms->Activate = (Activate_t) + dlsym(RTLD_DEFAULT, "JVM_DTraceActivate"); + syms->Dispose = (Dispose_t) + dlsym(RTLD_DEFAULT, "JVM_DTraceDispose"); + syms->IsProbeEnabled = (IsProbeEnabled_t) + dlsym(RTLD_DEFAULT, "JVM_DTraceIsProbeEnabled"); + + if ( syms->GetVersion == NULL || syms->Activate == NULL || + syms->IsProbeEnabled == NULL || syms->Dispose == NULL || + syms->IsSupported == NULL) { + free(syms); + syms = NULL; + } + } + return syms; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/windows/native/sun/tracing/dtrace/jvm_symbols_md.c Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,44 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include <windows.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <jvm.h> + +#include "jvm_symbols.h" + +JvmSymbols* lookupJvmSymbols() { + JvmSymbols* syms = (JvmSymbols*)malloc(sizeof(JvmSymbols)); + if (syms != NULL) { + HINSTANCE jvm = LoadLibrary("jvm.dll"); + if (jvm == NULL) { + free(syms); + return NULL; + } + syms->GetVersion = (GetVersion_t) + GetProcAddress(jvm, "JVM_DTraceGetVersion"); + syms->IsSupported = (IsSupported_t) + GetProcAddress(jvm, "JVM_DTraceIsSupported"); + syms->Activate = (Activate_t) + GetProcAddress(jvm, "JVM_DTraceActivate"); + syms->Dispose = (Dispose_t) + GetProcAddress(jvm, "JVM_DTraceDispose"); + syms->IsProbeEnabled = (IsProbeEnabled_t) + GetProcAddress(jvm, "JVM_DTraceIsProbeEnabled"); + + (void)FreeLibrary(jvm); + if ( syms->GetVersion == NULL || syms->IsSupported == NULL || + syms->Activate == NULL || syms->Dispose == NULL || + syms->IsProbeEnabled == NULL) { + free(syms); + syms = NULL; + } + + } + return syms; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/tracing/BasicFunctionality.java Thu Apr 17 22:00:16 2008 -0400 @@ -0,0 +1,146 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6537506 + * @summary Basic unit test for tracing framework + */ + +import com.sun.tracing.*; +import java.lang.reflect.Method; + +@ProviderName("NamedProvider") +interface BasicProvider extends Provider { + void plainProbe(); + void probeWithArgs(int a, float f, String s, Long l); + @ProbeName("namedProbe") void probeWithName(); + void overloadedProbe(); + void overloadedProbe(int i); +} + +interface InvalidProvider extends Provider { + int nonVoidProbe(); +} + +public class BasicFunctionality { + + public static ProviderFactory factory; + public static BasicProvider bp; + + public static void main(String[] args) throws Exception { + + factory = ProviderFactory.getDefaultFactory(); + if (factory != null) { + bp = factory.createProvider(BasicProvider.class); + } + + testProviderFactory(); + testProbe(); + testProvider(); + } + + static void fail(String s) throws Exception { + throw new Exception(s); + } + + static void testProviderFactory() throws Exception { + if (factory == null) { + fail("ProviderFactory.getDefaultFactory: Did not create factory"); + } + if (bp == null) { + fail("ProviderFactory.createProvider: Did not create provider"); + } + try { + factory.createProvider(null); + fail("ProviderFactory.createProvider: Did not throw NPE for null"); + } catch (NullPointerException e) {} + + try { + factory.createProvider(InvalidProvider.class); + fail("Factory.createProvider: Should error with non-void probes"); + } catch (IllegalArgumentException e) {} + } + + public static void testProvider() throws Exception { + + // These just shouldn't throw any exeptions: + bp.plainProbe(); + bp.probeWithArgs(42, (float)3.14, "spam", new Long(2L)); + bp.probeWithArgs(42, (float)3.14, null, null); + bp.probeWithName(); + bp.overloadedProbe(); + bp.overloadedProbe(42); + + Method m = BasicProvider.class.getMethod("plainProbe"); + Probe p = bp.getProbe(m); + if (p == null) { + fail("Provider.getProbe: Did not return probe"); + } + + Method m2 = BasicFunctionality.class.getMethod("testProvider"); + p = bp.getProbe(m2); + if (p != null) { + fail("Provider.getProbe: Got probe with invalid spec"); + } + + bp.dispose(); + // These just shouldn't throw any exeptions: + bp.plainProbe(); + bp.probeWithArgs(42, (float)3.14, "spam", new Long(2L)); + bp.probeWithArgs(42, (float)3.14, null, null); + bp.probeWithName(); + bp.overloadedProbe(); + bp.overloadedProbe(42); + + if (bp.getProbe(m) != null) { + fail("Provider.getProbe: Should return null after dispose()"); + } + + bp.dispose(); // just to make sure nothing bad happens + } + + static void testProbe() throws Exception { + Method m = BasicProvider.class.getMethod("plainProbe"); + Probe p = bp.getProbe(m); + p.isEnabled(); // just make sure it doesn't do anything bad + p.trigger(); + + try { + p.trigger(0); + fail("Probe.trigger: too many arguments not caught"); + } catch (IllegalArgumentException e) {} + + p = bp.getProbe(BasicProvider.class.getMethod( + "probeWithArgs", int.class, float.class, String.class, Long.class)); + try { + p.trigger(); + fail("Probe.trigger: too few arguments not caught"); + } catch (IllegalArgumentException e) {} + + try { + p.trigger((float)3.14, (float)3.14, "", new Long(0L)); + fail("Probe.trigger: wrong type primitive arguments not caught"); + } catch (IllegalArgumentException e) {} + } +}