is new.
public interface Instrumentation
This class provides services needed to instrument Java programming language code. Instrumentation is the addition of byte-codes to methods for the purpose of gathering data to be utilized by tools. Since the changes are purely additive, these tools do not modify application state or behavior. Examples of such benign tools include monitoring agents, profilers, coverage analyzers, and event loggers.
There are two ways to obtain an instance of the Instrumentation interface:
When a JVM is launched in a way that indicates an agent class. In that case the Instrumentation instance is passed to the premain method of the agent class.
When a JVM provides a mechanism to start agents sometime after the JVM is launched. In that case the Instrumentation instance is passed to the agentmain method of the agent code.
These mechanisms are described in the
package specification
The only way to access an instance of the Instrumentation interface is for the JVM to be launched in a way that indicates the agent class - see
the package specification
.
The Instrumentation instance is passed to the premain method of the agent class. Once an agent acquires the Instrumentation instance, the agent may call methods on the instance at any time.
Once an agent acquires the Instrumentation instance, the agent may call methods on the instance at any time.
| Method Summary | |
|---|---|
| void |
addTransformer
(
ClassFileTransformer
transformer) Registers the supplied transformer. |
void
|
addTransformer
(
ClassFileTransformer
Registers the supplied transformer.
|
void
|
appendToBootstrapClassLoaderSearch
(
JarFile
Specifies a JAR file with instrumentation classes to be defined by the bootstrap class loader.
|
void
|
appendToSystemClassLoaderSearch
(
JarFile
Specifies a JAR file with instrumentation classes to be defined by the system class loader.
|
| Class [] |
getAllLoadedClasses
() Returns an array of all classes currently loaded by the JVM. |
| Class [] |
getInitiatedClasses
(
ClassLoader
loader) Returns an array of all classes for which loader is an initiating loader. |
| long |
getObjectSize
(
Object
objectToSize) Returns an implementation-specific approximation of the amount of storage consumed by the specified object. |
boolean
|
isNativeMethodPrefixSupported
()
Returns whether the current JVM configuration supports
setting a native method prefix
|
| boolean |
isRedefineClassesSupported
() Returns whether or not the current JVM configuration supports redefinition of classes. |
boolean
|
isRetransformClassesSupported
()
Returns whether or not the current JVM configuration supports retransformation of classes.
|
|
|
void
|
redefineClasses
(
ClassDefinition
Redefine the supplied set of classes using the supplied class files.
|
| boolean |
removeTransformer
(
ClassFileTransformer
transformer) Unregisters the supplied transformer. |
void
|
retransformClasses
(
Class
Retransform the supplied set of classes.
|
void
|
setNativeMethodPrefix
(
ClassFileTransformer
transformer,
String
This method modifies the failure handling of native method resolution by allowing retry with a prefix applied to the name.
|
| Method Detail |
|---|
addTransformer
void
addTransformer
(
ClassFileTransformer
transformer, boolean canRetransform)
Registers the supplied transformer. All future class definitions will be seen by the transformer, except definitions of classes upon which any registered transformer is dependent. The transformer is called when classes are loaded, when they are
redefined
. and if canRetransform is true, when they are
retransformed
. See
ClassFileTransformer.transform
for the order of transform calls. If a transformer throws an exception during execution, the JVM will still call the other registered transformers in order. The same transformer may be added more than once, but it is strongly discouraged -- avoid this by creating a new instance of tranformer class.
This method is intended for use in instrumentation, as described in the
class specification
.
Parameters:
transformer - the transformer to register
canRetransform - can this transformer's transformations be retransformed
Throws:
NullPointerException
- if passed a null transformer
UnsupportedOperationException
- if canRetransform is true and the current configuration of the JVM does not allow retransformation (
isRetransformClassesSupported()
is false)
Since:
1.6
void addTransformer(ClassFileTransformer transformer)
Same as addTransformer(transformer, false).
This method is intended for use in instrumentation, as described in the
class specification
.
See Also:
addTransformer(ClassFileTransformer,boolean)
boolean removeTransformer(ClassFileTransformer transformer)
isRetransformClassesSupported
boolean
isRetransformClassesSupported
()
Returns whether or not the current JVM configuration supports retransformation of classes. The ability to retransform an already loaded class is an optional capability of a JVM. Retransformation will only be supported if the Can-Retransform-Classes manifest attribute is set to true in the agent JAR file (as described in the
package specification
) and the JVM supports this capability. During a single instantiation of a single JVM, multiple calls to this method will always return the same answer.
Returns:
true if the current JVM configuration supports retransformation of classes, false if not.
Since:
1.6
See Also:
retransformClasses(java.lang.Class>
...)
retransformClasses
void
retransformClasses
(
Class
<?>... classes) throws
ClassNotFoundException
,
UnmodifiableClassException
Retransform the supplied set of classes.
This function facilitates the instrumentation of already loaded classes. When classes are initially loaded or when they are
redefined
, the initial class file bytes can be transformed with the
ClassFileTransformer
. This function reruns the transformation process (whether or not a transformation has previously occurred). This retransformation follows these steps:
starting from the initial class file bytes
for each transformer that was added with canRetransform false, the bytes returned by
transform
during the last class load or redefine are reused as the output of the transformation; note that this is equivalent to reapplying the previous transformation, unaltered; except that
transform
for each transformer that was added with canRetransform true, the
transform
the transformed class file bytes are installed as the new definition of the class
The order of transformation is described in the (
transform
method. This same order is used in the automatic reapplication of retransformation incapable transforms.
The initial class file bytes represent the bytes passed to
ClassLoader.defineClass
or
redefineClasses
(before any transformations were applied), however they might not exactly match them. The constant pool might not have the same layout or contents. The constant pool may have more or fewer entries. Constant pool entries may be in a different order; however, constant pool indices in the bytecodes of methods will correspond. Some attributes may not be present. Where order is not meaningful, for example the order of methods, order might not be preserved.
This method operates on a set in order to allow interdependent changes to more than one class at the same time (a retransformation of class A can require a retransformation of class B).
If a retransformed method has active stack frames, those active frames continue to run the bytecodes of the original method. The retransformed method will be used on new invokes.
This method does not cause any initialization except that which would occur under the customary JVM semantics. In other words, redefining a class does not cause its initializers to be run. The values of static variables will remain as they were prior to the call.
Instances of the retransformed class are not affected.
The retransformation may change method bodies, the constant pool and attributes. The retransformation must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions. The class file bytes are not checked, verified and installed until after the transformations have been applied, if the resultant bytes are in error this method will throw an exception.
If this method throws an exception, no classes have been retransformed.
This method is intended for use in instrumentation, as described in the
class specification
.
Parameters:
classes - array of classes to retransform; a zero-length array is allowed, in this case, this method does nothing
Throws:
ClassNotFoundException
- if a specified class cannot be found
UnmodifiableClassException
- if a specified class cannot be modified
UnsupportedOperationException
- if the current configuration of the JVM does not allow retransformation (
isRetransformClassesSupported()
is false) or the retransformation attempted to make unsupported changes
ClassFormatError
- if the data did not contain a valid class
NoClassDefFoundError
- if the name in the class file is not equal to the name of the class
UnsupportedClassVersionError
- if the class file version numbers are not supported
ClassCircularityError
- if the new classes contain a circularity
LinkageError
- if a linkage error occurs
NullPointerException
- if the supplied classes array or any of its components is null.
Since:
1.6
See Also:
isRetransformClassesSupported()
,
addTransformer(java.lang.instrument.ClassFileTransformer, boolean)
,
ClassFileTransformer
boolean isRedefineClassesSupported()
Redefinition will only be supported if the Can-Redefine-Classes manifest attribute is set to true in the agent JAR file (as described in the
package specification
) and the JVM supports this capability.
During a single instantiation of a single JVM, multiple calls to this method will always return the same answer.
redefineClasses(java.lang.instrument.ClassDefinition...)
void redefineClasses(ClassDefinition... definitions)
[] definitions)throws ClassNotFoundException, UnmodifiableClassException
This method is used to replace the definition of a class without reference to the existing class file bytes, as one might do when recompiling from source for fix-and-continue debugging. Where the existing class file bytes are to be transformed (for example in bytecode instrumentation)
retransformClasses
should be used.
This method operates on a set in order to allow interdependent changes to more than one class at the same time (a redefinition of class A can require a redefinition of class B).
If a redefined method has active stack frames, those active frames continue to run the bytecodes of the original method. The redefined method will be used on new invokes.
This method does not cause any initialization except that which would occur under the customary JVM semantics. In other words, redefining a class does not cause its initializers to be run. The values of static variables will remain as they were prior to the call.
Instances of the redefined class are not affected.
Registered transformers will be called before the redefine operation is applied.
The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions.
The class file bytes are not checked, verified and installed until after the transformations have been applied, if the resultant bytes are in error this method will throw an exception.
A zero-length definitions array is allowed, in this case, this method does nothing.
If this method throws an exception, no classes have been redefined.
This method is intended for use in instrumentation, as described in the class specification .
definitions; a zero-length array is allowed, in this case, this method does nothing
attempted to make
addTransformer(java.lang.instrument.ClassFileTransformer, boolean)
Class[] getAllLoadedClasses()
Class[] getInitiatedClasses(ClassLoader loader)
long getObjectSize(Object objectToSize)
appendToBootstrapClassLoaderSearch
void
appendToBootstrapClassLoaderSearch
(
JarFile
jarfile) throws
ClassLoaderConfigurationError
Specifies a JAR file with instrumentation classes to be defined by the bootstrap class loader.
When the virtual machine's built-in class loader, known as the "bootstrap class loader", unsuccessfully searches for a class, the entries in the
JAR file
will be searched as well.
This method may be used multiple times to add multiple JAR files to be searched in the order that this method was invoked.
The JAR file must not contain an entry that corresponds to a class with the same name as a class that is already loaded, or in process of being loaded, by a class loader other than the bootstrap class loader. For example, if the JAR file contains the entry COM/foo/Quux.class then this method will not succeed if the class COM.foo.Quux is already loaded by some class loader that is not the bootstrap class loader. This restriction ensures the instrumentation classes provided by the agent are defined by the bootstrap class loader.
The
Java Virtual Machine Specification
specifies that a subsequent attempt to resolve a symbolic reference that the Java virtual machine has previously unsuccessfully attempted to resolve always fails with the same error that was thrown as a result of the initial resolution attempt. Consequently, if the JAR file contains an entry that corresponds to a class for which the Java virtual machine has unsuccessfully attempted to resolve a reference, then subsequent attempts to resolve that reference will fail with the same error as the initial attempt.
Parameters:
jarfile - The JAR file to be searched when the bootstrap class loader unsuccessfully searches for a class.
Throws:
ClassLoaderConfigurationError
- If the JAR file contains a class with the same name as a class already loaded by a class loader other than the bootstrap class loader.
NullPointerException
- If jarfile is null.
Since:
1.6
See Also:
ClassLoader
,
JarFile
appendToSystemClassLoaderSearch
void
appendToSystemClassLoaderSearch
(
JarFile
jarfile) throws
ClassLoaderConfigurationError
Specifies a JAR file with instrumentation classes to be defined by the system class loader. When the system class loader for delegation (see
getSystemClassLoader()
) unsuccessfully searches for a class, the entries in the
JarFile
will be searched as well.
This method may be used multiple times to add multiple JAR files to be searched in the order that this method was invoked.
The JAR file must not contain an entry that corresponds to a class with the same name as a class that is already loaded, or in process of being loaded, by a class loader that is a descendent of the system class loader. For example, if the JAR file contains the entry COM/foo/Quux.class, and there is a class loader L which returns the system class loader as its parent class loader for delegation, then the method will not succeed if loader L has loaded (or is in the process of loading) COM.foo.Quux. In addition the Class-Path attribute must not be present in the main section of the JAR manifest (see
JAR file specification
). These restrictions ensure that the instrumentation classes provided by the agent are defined by the system class loader (or its ascendents if the instrumentation classes can be defined by an ascendent class loader).
The system class loader supports adding a JAR file to be searched if it implements a method named appendToClassPathForInstrumentation which takes a single parameter of type java.lang.String. The method is not required to have public access. The appendToSystemClassLoaderSearch method synchronizes on the system class loader and invokes the appendToClassPathForInstrumentation method with the parameter set to the path name of the JAR file obtained by invoking the
getName()
method.
The
Java Virtual Machine Specification
specifies that a subsequent attempt to resolve a symbolic reference that the Java virtual machine has previously unsuccessfully attempted to resolve always fails with the same error that was thrown as a result of the initial resolution attempt. Consequently, if the JAR file contains an entry that corresponds to a class for which the Java virtual machine has unsuccessfully attempted to resolve a reference, then subsequent attempts to resolve that reference will fail with the same error as the initial attempt.
This method does not change the value of java.class.path
system property
.
Parameters:
jarfile - The JAR file to be searched when the system class loader unsuccessfully searches for a class.
Throws:
ClassLoaderConfigurationError
- If the JAR file contains a class with the same name as a class already loaded by a class loader that is a descendent of the system class loader, or the Class-Path attribute is present in the main section of the JAR manifest.
UnsupportedOperationException
- If the system class loader does not support appending a a JAR file to be searched.
NullPointerException
- If jarfile is null.
Since:
1.6
See Also:
ClassLoader.getSystemClassLoader()
,
ClassLoader.getParent()
,
System.getProperties()
,
JarFile
isNativeMethodPrefixSupported
boolean
isNativeMethodPrefixSupported
()
Returns whether the current JVM configuration supports
setting a native method prefix
. The ability to set a native method prefix is an optional capability of a JVM. Setting a native method prefix will only be supported if the Can-Set-Native-Method-Prefix manifest attribute is set to true in the agent JAR file (as described in the
package specification
) and the JVM supports this capability. During a single instantiation of a single JVM, multiple calls to this method will always return the same answer.
Returns:
true if the current JVM configuration supports setting a native method prefix, false if not.
Since:
1.6
See Also:
setNativeMethodPrefix(java.lang.instrument.ClassFileTransformer, java.lang.String)
setNativeMethodPrefix
void
setNativeMethodPrefix
(
ClassFileTransformer
transformer,
String
prefix)
This method modifies the failure handling of native method resolution by allowing retry with a prefix applied to the name. When used with the
ClassFileTransformer
, it enables native methods to be instrumented.
Since native methods cannot be directly instrumented (they have no bytecodes), they must be wrapped with a non-native method which can be instrumented. For example, if we had:
native boolean foo(int x);
We could transform the class file (with the ClassFileTransformer during the initial definition of the class) so that this becomes:
boolean foo(int x) {
... record entry to foo ...
return wrapped_foo(x); } native boolean wrapped_foo(int x);
Where foo becomes a wrapper for the actual native method with the appended prefix "wrapped_". Note that "wrapped_" would be a poor choice of prefix since it might conceivably form the name of an existing method thus something like "$$$MyAgentWrapped$$$_" would be better but would make these examples less readable.
The wrapper will allow data to be collected on the native method call, but now the problem becomes linking up the wrapped method with the native implementation. That is, the method wrapped_foo needs to be resolved to the native implementation of foo, which might be:
Java_somePackage_someClass_foo(JNIEnv* env, jint x)
This function allows the prefix to be specified and the proper resolution to occur. Specifically, when the standard resolution fails, the resolution is retried taking the prefix into consideration. There are two ways that resolution occurs, explicit resolution with the JNI function RegisterNatives and the normal automatic resolution. For RegisterNatives, the JVM will attempt this association:
method(foo) -> nativeImplementation(foo)
When this fails, the resolution will be retried with the specified prefix prepended to the method name, yielding the correct resolution:
method(wrapped_foo) -> nativeImplementation(foo)
For automatic resolution, the JVM will attempt:
method(wrapped_foo) -> nativeImplementation(wrapped_foo)
When this fails, the resolution will be retried with the specified prefix deleted from the implementation name, yielding the correct resolution:
method(wrapped_foo) -> nativeImplementation(foo)
Note that since the prefix is only used when standard resolution fails, native methods can be wrapped selectively.
Since each ClassFileTransformer can do its own transformation of the bytecodes, more than one layer of wrappers may be applied. Thus each transformer needs its own prefix. Since transformations are applied in order, the prefixes, if applied, will be applied in the same order (see
addTransformer
). Thus if three transformers applied wrappers, foo might become $trans3_$trans2_$trans1_foo. But if, say, the second transformer did not apply a wrapper to foo it would be just $trans3_$trans1_foo. To be able to efficiently determine the sequence of prefixes, an intermediate prefix is only applied if its non-native wrapper exists. Thus, in the last example, even though $trans1_foo is not a native method, the $trans1_ prefix is applied since $trans1_foo exists.
Parameters:
transformer - The ClassFileTransformer which wraps using this prefix.
prefix - The prefix which has been applied to wrapped native methods.
Throws:
NullPointerException
- if passed a null transformer.
UnsupportedOperationException
- if the current configuration of the JVM does not allow setting a native method prefix (
isNativeMethodPrefixSupported()
is false).
IllegalArgumentException
- if the transformer is not registered (see
addTransformer
).
Since:
1.6