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 an 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 an Instrumentation
instance is passed to the agentmain
method of the
agent code.
These mechanisms are described in the package specification.
Once an agent acquires an Instrumentation
instance,
the agent may call methods on the instance at any time.
Same as addTransformer(transformer, false)
.
Parameters:
- transformer - the transformer to register
Throws:
- java.lang.NullPointerException - if passed a null
transformer
See Also:
Instrumentation.addTransformer(ClassFileTransformer,boolean)
,
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:
- java.lang.NullPointerException - if passed a null
transformer
- java.lang.UnsupportedOperationException - if canRetransform
is true and the current configuration of the JVM does not allow
retransformation ({@link #isRetransformClassesSupported} is false)
Since:
1.6
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 agent should take care to ensure that the JAR does not contain any
classes or resources other than those to be defined by the bootstrap
class loader for the purpose of instrumentation.
Failure to observe this warning could result in unexpected
behaviour that is difficult to diagnose. For example, suppose there is a
loader L, and L's parent for delegation is the bootstrap class loader.
Furthermore, a method in class C, a class defined by L, makes reference to
a non-public accessor class C$1. If the JAR file contains a class C$1 then
the delegation to the bootstrap class loader will cause C$1 to be defined
by the bootstrap class loader. In this example an IllegalAccessError
will be thrown that may cause the application to fail. One approach to
avoiding these types of issues, is to use a unique package name for the
instrumentation classes.
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:
- NullPointerException - If jarfile
is null
.
Since:
1.6
See Also:
Instrumentation.appendToSystemClassLoaderSearch(java.util.jar.JarFile)
,
ClassLoader
,
JarFile
,
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 agent should take care to ensure that the JAR does not contain any
classes or resources other than those to be defined by the system class
loader for the purpose of instrumentation.
Failure to observe this warning could result in unexpected
behaviour that is difficult to diagnose (see
appendToBootstrapClassLoaderSearch
.
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 name of
the JAR file is obtained by invoking the getName()
method on the jarfile
and this is provided as the
parameter to the appendtoClassPathForInstrumentation
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:
- 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:
Instrumentation.appendToBootstrapClassLoaderSearch(java.util.jar.JarFile)
,
ClassLoader.getSystemClassLoader()
,
JarFile
,
loader
is an initiating loader.null
, classes initiated by the bootstrap classnull
.
true
.
If a class is not modifiable then this method returns false
.
For a class to be retransformed, Instrumentation.isRetransformClassesSupported()
must also be true.
But the value of isRetransformClassesSupported()
does not influence the value
returned by this function.
For a class to be redefined, Instrumentation.isRedefineClassesSupported()
must also be true.
But the value of isRedefineClassesSupported()
does not influence the value
returned by this function.
Primitive classes (for example, java.lang.Integer.TYPE
)
and array classes are never modifiable.
Throws:
- java.lang.NullPointerException - if the specified class is null
.
Since:
1.6
See Also:
Instrumentation.retransformClasses(java.lang.Class>...)
,
Instrumentation.isRetransformClassesSupported()
,
Instrumentation.redefineClasses(java.lang.instrument.ClassDefinition...)
,
Instrumentation.isRedefineClassesSupported()
,
Can-Set-Native-Method-Prefix
manifest attribute is set totrue
in the agent JAR file (as described in the Instrumentation.setNativeMethodPrefix(java.lang.instrument.ClassFileTransformer, java.lang.String)
,
Can-Redefine-Classes
manifest attribute is set totrue
in the agent JAR file (as described in the Instrumentation.redefineClasses(java.lang.instrument.ClassDefinition...)
,
Can-Retransform-Classes
manifest attribute is set totrue
in the agent JAR file (as described in the Instrumentation.retransformClasses(java.lang.Class>...)
,
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.
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.
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.
Parameters:
- definitions - array of classes to redefine with corresponding definitions;
a zero-length array is allowed, in this case, this method does nothing
Throws:
- java.lang.instrument.UnmodifiableClassException - if a specified class cannot be modified
({@link #isModifiableClass} would return false
)
- java.lang.UnsupportedOperationException - if the current configuration of the JVM does not allow
redefinition ({@link #isRedefineClassesSupported} is false) or the redefinition attempted
to make unsupported changes
- java.lang.ClassFormatError - if the data did not contain a valid class
- java.lang.NoClassDefFoundError - if the name in the class file is not equal to the name of the class
- java.lang.UnsupportedClassVersionError - if the class file version numbers are not supported
- java.lang.ClassCircularityError - if the new classes contain a circularity
- java.lang.LinkageError - if a linkage error occurs
- java.lang.NullPointerException - if the supplied definitions array or any of its components
is null
- java.lang.ClassNotFoundException - Can never be thrown (present for compatibility reasons only)
See Also:
Instrumentation.isRedefineClassesSupported()
,
Instrumentation.addTransformer(java.lang.instrument.ClassFileTransformer, boolean)
,
ClassFileTransformer
,
null
transformer
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:
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
is not called
canRetransform
true, the
transform
method is called in these transformers
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:
- java.lang.instrument.UnmodifiableClassException - if a specified class cannot be modified
({@link #isModifiableClass} would return false
)
- java.lang.UnsupportedOperationException - if the current configuration of the JVM does not allow
retransformation ({@link #isRetransformClassesSupported} is false) or the retransformation attempted
to make unsupported changes
- java.lang.ClassFormatError - if the data did not contain a valid class
- java.lang.NoClassDefFoundError - if the name in the class file is not equal to the name of the class
- java.lang.UnsupportedClassVersionError - if the class file version numbers are not supported
- java.lang.ClassCircularityError - if the new classes contain a circularity
- java.lang.LinkageError - if a linkage error occurs
- java.lang.NullPointerException - if the supplied classes array or any of its components
is null
.
Since:
1.6
See Also:
Instrumentation.isRetransformClassesSupported()
,
Instrumentation.addTransformer(java.lang.instrument.ClassFileTransformer, boolean)
,
ClassFileTransformer
,
ClassFileTransformer
,
native boolean foo(int x);
boolean foo(int x) {
... record entry to foo ...
return wrapped_foo(x);
}
native boolean wrapped_foo(int x);
foo
becomes a wrapper for the actual native wrapped_foo
needs to be foo
,
Java_somePackage_someClass_foo(JNIEnv* env, jint x)
RegisterNatives
RegisterNatives
, the JVM will attempt this
method(foo) -> nativeImplementation(foo)
method(wrapped_foo) -> nativeImplementation(foo)
method(wrapped_foo) -> nativeImplementation(wrapped_foo)
method(wrapped_foo) -> nativeImplementation(foo)
ClassFileTransformer
addTransformer
). foo
might become $trans3_$trans2_$trans1_foo
. But if, say,foo
it would be just $trans3_$trans1_foo
. To be able to $trans1_foo
is not a native method, the$trans1_
prefix is applied since $trans1_foo
exists.
null
transformer.