APIdia Launch Partner
Top Description Inners Fields Constructors Methods
sun.instrument

public Class InstrumentationImpl

extends Object
implements Instrumentation
Class Inheritance
All Implemented Interfaces
java.lang.instrument.Instrumentation
Annotations
@SuppressWarnings:restricted
Imports
java.lang.instrument.UnmodifiableModuleException, .ClassFileTransformer, .ClassDefinition, .Instrumentation, java.lang.reflect.Method, .Modifier, .AccessibleObject, java.io.PrintStream, java.nio.file.Path, .InvalidPathException, java.net.URL, java.security.CodeSource, .PrivilegedAction, .ProtectionDomain, java.util.Collections, .ArrayList, .HashMap, .HashSet, .List, .Map, .Set, java.util.jar.JarFile, java.util.stream.Collectors, jdk.internal.module.Modules, jdk.internal.vm.annotation.IntrinsicCandidate

The Java side of the JPLIS implementation. Works in concert with a native JVMTI agent to implement the JPLIS API set. Provides both the Java API implementation of the Instrumentation interface and utility Java routines to support the native code. Keeps a pointer to the native data structure in a scalar field to allow native processing behind native methods.

Nested and Inner Type Summary

Modifier and TypeClass and Description
private static class
InstrumentationImpl.HolderStackWalker

Holder for StackWalker object.

Field Summary

Modifier and TypeField and Description
private final boolean
private final boolean
private volatile boolean
private volatile boolean
private final long
private TransformerManager
private final TransformerManager
private static final boolean
private static final String

Constructor Summary

AccessConstructor and Description
private
InstrumentationImpl(long nativeAgent, boolean environmentSupportsRedefineClasses, boolean environmentSupportsNativeMethodPrefix, boolean printWarning)

Method Summary

Modifier and TypeMethod and Description
public void
addTransformer(ClassFileTransformer transformer)

Implements java.lang.instrument.Instrumentation.addTransformer.

Registers the supplied transformer.

public void
addTransformer(ClassFileTransformer transformer, boolean canRetransform)

Implements java.lang.instrument.Instrumentation.addTransformer.

Registers the supplied transformer.

public void
appendToBootstrapClassLoaderSearch(JarFile jarfile)

Implements java.lang.instrument.Instrumentation.appendToBootstrapClassLoaderSearch.

Specifies a JAR file with instrumentation classes to be defined by the bootstrap class loader.

private native void
appendToClassLoaderSearch0(long nativeAgent, String jarfile, boolean bootLoader)

public void
appendToSystemClassLoaderSearch(JarFile jarfile)

Implements java.lang.instrument.Instrumentation.appendToSystemClassLoaderSearch.

Specifies a JAR file with instrumentation classes to be defined by the system class loader.

private Map<String, Set<Module>>
private static URL
codeSource(Class<?> clazz)

Returns the possibly-bnull code source of the given class.

private TransformerManager
public Class<T>[]
getAllLoadedClasses()

Implements java.lang.instrument.Instrumentation.getAllLoadedClasses.

Returns an array of all classes currently loaded by the JVM.

private native Class<T>[]
getAllLoadedClasses0(long nativeAgent)

public Class<T>[]
getInitiatedClasses(ClassLoader loader)

Implements java.lang.instrument.Instrumentation.getInitiatedClasses.

Returns an array of all classes which loader can find by name via ClassLoader::loadClass, Class::forName and bytecode linkage.

private native Class<T>[]
getInitiatedClasses0(long nativeAgent, ClassLoader loader)

public long
getObjectSize(Object objectToSize)

Implements java.lang.instrument.Instrumentation.getObjectSize.

Returns an implementation-specific approximation of the amount of storage consumed by the specified object.

private native long
getObjectSize0(long nativeAgent, Object objectToSize)

public boolean
isModifiableClass(Class<?> theClass)

Implements java.lang.instrument.Instrumentation.isModifiableClass.

Tests whether a class is modifiable by retransformation or redefinition.

private native boolean
isModifiableClass0(long nativeAgent, Class<?> theClass)

public boolean
isModifiableModule(Module module)

Implements java.lang.instrument.Instrumentation.isModifiableModule.

Tests whether a module can be modified with redefineModule.

public boolean
public boolean
isRedefineClassesSupported()

Implements java.lang.instrument.Instrumentation.isRedefineClassesSupported.

Returns whether or not the current JVM configuration supports redefinition of classes.

public boolean
isRetransformClassesSupported()

Implements java.lang.instrument.Instrumentation.isRetransformClassesSupported.

Returns whether or not the current JVM configuration supports retransformation of classes.

private native boolean
private native String
jarFile(long nativeAgent)

public static void
loadAgent(String path)

Invoked by the java launcher to load a java agent that is packaged with the main application in an executable JAR file.

private static native void
private void
loadClassAndCallAgentmain(String classname, String optionsString)

private void
loadClassAndCallPremain(String classname, String optionsString)

private void
loadClassAndStartAgent(String classname, String methodname, String optionsString)

public void
redefineClasses(ClassDefinition... definitions)

Implements java.lang.instrument.Instrumentation.redefineClasses.

Redefine the supplied set of classes using the supplied class files.

private native void
redefineClasses0(long nativeAgent, ClassDefinition[] definitions)

public void
redefineModule(Module module, Set<Module> extraReads, Map<String, Set<Module>> extraExports, Map<String, Set<Module>> extraOpens, Set<Class<?>> extraUses, Map<Class<?>, List<Class<?>>> extraProvides)

Implements java.lang.instrument.Instrumentation.redefineModule.

Redefine a module to expand the set of modules that it reads, the set of packages that it exports or opens, or the services that it uses or provides.

public boolean
removeTransformer(ClassFileTransformer transformer)

Implements java.lang.instrument.Instrumentation.removeTransformer.

Unregisters the supplied transformer.

public void
retransformClasses(Class<?>... classes)

Implements java.lang.instrument.Instrumentation.retransformClasses.

Retransform the supplied set of classes.

private native void
retransformClasses0(long nativeAgent, Class<?>[] classes)

private native void
setHasRetransformableTransformers(long nativeAgent, boolean has)

private native void
setHasTransformers(long nativeAgent, boolean has)

public void
setNativeMethodPrefix(ClassFileTransformer transformer, String prefix)

Implements java.lang.instrument.Instrumentation.setNativeMethodPrefix.

This method modifies the failure handling of native method resolution by allowing retry with a prefix applied to the name.

private native void
setNativeMethodPrefixes(long nativeAgent, String[] prefixes, boolean isRetransformable)

private void
trace(String methodName)

Prints a trace message and stack trace when tracing is enabled.

private byte[]
transform(Module module, ClassLoader loader, String classname, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer, boolean isRetransformer)

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

mEnvironmentSupportsNativeMethodPrefixback to summary
private final boolean mEnvironmentSupportsNativeMethodPrefix
mEnvironmentSupportsRedefineClassesback to summary
private final boolean mEnvironmentSupportsRedefineClasses
mEnvironmentSupportsRetransformClassesback to summary
private volatile boolean mEnvironmentSupportsRetransformClasses
mEnvironmentSupportsRetransformClassesKnownback to summary
private volatile boolean mEnvironmentSupportsRetransformClassesKnown
mNativeAgentback to summary
private final long mNativeAgent
mRetransfomableTransformerManagerback to summary
private TransformerManager mRetransfomableTransformerManager
mTransformerManagerback to summary
private final TransformerManager mTransformerManager
TRACE_USAGEback to summary
private static final boolean TRACE_USAGE
TRACE_USAGE_PROP_NAMEback to summary
private static final String TRACE_USAGE_PROP_NAME

Constructor Detail

InstrumentationImplback to summary
private InstrumentationImpl(long nativeAgent, boolean environmentSupportsRedefineClasses, boolean environmentSupportsNativeMethodPrefix, boolean printWarning)

Method Detail

addTransformerback to summary
public void addTransformer(ClassFileTransformer transformer)

Implements java.lang.instrument.Instrumentation.addTransformer.

Doc from java.lang.instrument.Instrumentation.addTransformer.

Registers the supplied transformer.

Same as addTransformer(transformer, false).

Annotations
@Override
addTransformerback to summary
public void addTransformer(ClassFileTransformer transformer, boolean canRetransform)

Implements java.lang.instrument.Instrumentation.addTransformer.

Doc from java.lang.instrument.Instrumentation.addTransformer.

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. ClassFileTransformer defines 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 transformer class.

This method is intended for use in instrumentation, as described in the class specification.

Annotations
@Override
appendToBootstrapClassLoaderSearchback to summary
public void appendToBootstrapClassLoaderSearch(JarFile jarfile)

Implements java.lang.instrument.Instrumentation.appendToBootstrapClassLoaderSearch.

Doc from java.lang.instrument.Instrumentation.appendToBootstrapClassLoaderSearch.

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 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 behavior 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.

Annotations
@Override
appendToClassLoaderSearch0back to summary
private native void appendToClassLoaderSearch0(long nativeAgent, String jarfile, boolean bootLoader)
appendToSystemClassLoaderSearchback to summary
public void appendToSystemClassLoaderSearch(JarFile jarfile)

Implements java.lang.instrument.Instrumentation.appendToSystemClassLoaderSearch.

Doc from java.lang.instrument.Instrumentation.appendToSystemClassLoaderSearch.

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 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 behavior 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.

Annotations
@Override
cloneAndCheckMapback to summary
private Map<String, Set<Module>> cloneAndCheckMap(Module module, Map<String, Set<Module>> map)
codeSourceback to summary
private static URL codeSource(Class<?> clazz)

Returns the possibly-bnull code source of the given class.

findTransformerManagerback to summary
private TransformerManager findTransformerManager(ClassFileTransformer transformer)
getAllLoadedClassesback to summary
public Class<T>[] getAllLoadedClasses()

Implements java.lang.instrument.Instrumentation.getAllLoadedClasses.

Doc from java.lang.instrument.Instrumentation.getAllLoadedClasses.

Returns an array of all classes currently loaded by the JVM. The returned array includes all classes and interfaces, including hidden classes or interfaces, and array classes of all types.

Annotations
@Override
@SuppressWarnings:rawtypes
getAllLoadedClasses0back to summary
private native Class<T>[] getAllLoadedClasses0(long nativeAgent)
Annotations
@SuppressWarnings:rawtypes
getInitiatedClassesback to summary
public Class<T>[] getInitiatedClasses(ClassLoader loader)

Implements java.lang.instrument.Instrumentation.getInitiatedClasses.

Doc from java.lang.instrument.Instrumentation.getInitiatedClasses.

Returns an array of all classes which loader can find by name via ClassLoader::loadClass, Class::forName and bytecode linkage. That is, all classes for which loader has been recorded as an initiating loader. If the supplied loader is null, classes that the bootstrap class loader can find by name are returned.

The returned array does not include hidden classes or interfaces or array classes whose element type is a hidden class or interface. as they cannot be discovered by any class loader.

Annotations
@Override
@SuppressWarnings:rawtypes
getInitiatedClasses0back to summary
private native Class<T>[] getInitiatedClasses0(long nativeAgent, ClassLoader loader)
Annotations
@SuppressWarnings:rawtypes
getObjectSizeback to summary
public long getObjectSize(Object objectToSize)

Implements java.lang.instrument.Instrumentation.getObjectSize.

Doc from java.lang.instrument.Instrumentation.getObjectSize.

Returns an implementation-specific approximation of the amount of storage consumed by the specified object. The result may include some or all of the object's overhead, and thus is useful for comparison within an implementation but not between implementations. The estimate may change during a single invocation of the JVM.

Annotations
@Override
getObjectSize0back to summary
private native long getObjectSize0(long nativeAgent, Object objectToSize)
Annotations
@IntrinsicCandidate
isModifiableClassback to summary
public boolean isModifiableClass(Class<?> theClass)

Implements java.lang.instrument.Instrumentation.isModifiableClass.

Doc from java.lang.instrument.Instrumentation.isModifiableClass.

Tests whether a class is modifiable by retransformation or redefinition. If a class is modifiable then this method returns true. If a class is not modifiable then this method returns false.

For a class to be retransformed, 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, 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.

Annotations
@Override
isModifiableClass0back to summary
private native boolean isModifiableClass0(long nativeAgent, Class<?> theClass)
isModifiableModuleback to summary
public boolean isModifiableModule(Module module)

Implements java.lang.instrument.Instrumentation.isModifiableModule.

Doc from java.lang.instrument.Instrumentation.isModifiableModule.

Tests whether a module can be modified with redefineModule. If a module is modifiable then this method returns true. If a module is not modifiable then this method returns false. This method always returns true when the module is an unnamed module (as redefining an unnamed module is a no-op).

Annotations
@Override
isNativeMethodPrefixSupportedback to summary
public boolean isNativeMethodPrefixSupported()

Implements java.lang.instrument.Instrumentation.isNativeMethodPrefixSupported.

Doc from java.lang.instrument.Instrumentation.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.

Annotations
@Override
isRedefineClassesSupportedback to summary
public boolean isRedefineClassesSupported()

Implements java.lang.instrument.Instrumentation.isRedefineClassesSupported.

Doc from java.lang.instrument.Instrumentation.isRedefineClassesSupported.

Returns whether or not the current JVM configuration supports redefinition of classes. The ability to redefine an already loaded class is an optional capability of a JVM. 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.

Annotations
@Override
isRetransformClassesSupportedback to summary
public boolean isRetransformClassesSupported()

Implements java.lang.instrument.Instrumentation.isRetransformClassesSupported.

Doc from java.lang.instrument.Instrumentation.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.

Annotations
@Override
isRetransformClassesSupported0back to summary
private native boolean isRetransformClassesSupported0(long nativeAgent)
jarFileback to summary
private native String jarFile(long nativeAgent)
loadAgentback to summary
public static void loadAgent(String path)

Invoked by the java launcher to load a java agent that is packaged with the main application in an executable JAR file.

loadAgent0back to summary
private static native void loadAgent0(String path)
loadClassAndCallAgentmainback to summary
private void loadClassAndCallAgentmain(String classname, String optionsString) throws Throwable
loadClassAndCallPremainback to summary
private void loadClassAndCallPremain(String classname, String optionsString) throws Throwable
loadClassAndStartAgentback to summary
private void loadClassAndStartAgent(String classname, String methodname, String optionsString) throws Throwable
redefineClassesback to summary
public void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException

Implements java.lang.instrument.Instrumentation.redefineClasses.

Doc from java.lang.instrument.Instrumentation.redefineClasses.

Redefine the supplied set of classes using the supplied class files.

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 supported class file changes are described in JVM TI RedefineClasses. 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.

Annotations
@Override
Exceptions
ClassNotFoundException:
Can never be thrown (present for compatibility reasons only)
redefineClasses0back to summary
private native void redefineClasses0(long nativeAgent, ClassDefinition[] definitions) throws ClassNotFoundException
redefineModuleback to summary
public void redefineModule(Module module, Set<Module> extraReads, Map<String, Set<Module>> extraExports, Map<String, Set<Module>> extraOpens, Set<Class<?>> extraUses, Map<Class<?>, List<Class<?>>> extraProvides)

Implements java.lang.instrument.Instrumentation.redefineModule.

Doc from java.lang.instrument.Instrumentation.redefineModule.

Redefine a module to expand the set of modules that it reads, the set of packages that it exports or opens, or the services that it uses or provides. This method facilitates the instrumentation of code in named modules where that instrumentation requires changes to the set of modules that are read, the packages that are exported or open, or the services that are used or provided.

This method cannot reduce the set of modules that a module reads, nor reduce the set of packages that it exports or opens, nor reduce the set of services that it uses or provides. This method is a no-op when invoked to redefine an unnamed module.

When expanding the services that a module uses or provides then the onus is on the agent to ensure that the service type will be accessible at each instrumentation site where the service type is used. This method does not check if the service type is a member of the module or in a package exported to the module by another module that it reads.

The extraExports parameter is the map of additional packages to export. The extraOpens parameter is the map of additional packages to open. In both cases, the map key is the fully-qualified name of the package as defined in section 6.5.3 of The Java Language Specification , for example, "java.lang". The map value is the non-empty set of modules that the package should be exported or opened to.

The extraProvides parameter is the additional service providers for the module to provide. The map key is the service type. The map value is the non-empty list of implementation types, each of which is a member of the module and an implementation of the service.

This method is safe for concurrent use and so allows multiple agents to instrument and update the same module at around the same time.

Annotations
@Override
removeTransformerback to summary
public boolean removeTransformer(ClassFileTransformer transformer)

Implements java.lang.instrument.Instrumentation.removeTransformer.

Doc from java.lang.instrument.Instrumentation.removeTransformer.

Unregisters the supplied transformer. Future class definitions will not be shown to the transformer. Removes the most-recently-added matching instance of the transformer. Due to the multi-threaded nature of class loading, it is possible for a transformer to receive calls after it has been removed. Transformers should be written defensively to expect this situation.

Annotations
@Override
retransformClassesback to summary
public void retransformClasses(Class<?>... classes)

Implements java.lang.instrument.Instrumentation.retransformClasses.

Doc from java.lang.instrument.Instrumentation.retransformClasses.

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 method is not called.
  • for each transformer that was added with canRetransform true, the transform method is called in these transformers
  • the transformed class file bytes are installed as the new definition of the class

The order of transformation is described in ClassFileTransformer. 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 supported class file changes are described in JVM TI RetransformClasses. 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.

Annotations
@Override
retransformClasses0back to summary
private native void retransformClasses0(long nativeAgent, Class<?>[] classes)
setHasRetransformableTransformersback to summary
private native void setHasRetransformableTransformers(long nativeAgent, boolean has)
setHasTransformersback to summary
private native void setHasTransformers(long nativeAgent, boolean has)
setNativeMethodPrefixback to summary
public void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix)

Implements java.lang.instrument.Instrumentation.setNativeMethodPrefix.

Doc from java.lang.instrument.Instrumentation.setNativeMethodPrefix.

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.

Annotations
@Override
setNativeMethodPrefixesback to summary
private native void setNativeMethodPrefixes(long nativeAgent, String[] prefixes, boolean isRetransformable)
traceback to summary
private void trace(String methodName)

Prints a trace message and stack trace when tracing is enabled.

transformback to summary
private byte[] transform(Module module, ClassLoader loader, String classname, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer, boolean isRetransformer)
sun.instrument back to summary

private Class InstrumentationImpl.HolderStackWalker

extends Object
Class Inheritance

Holder for StackWalker object.

Field Summary

Modifier and TypeField and Description
pack-priv static final StackWalker

Constructor Summary

AccessConstructor and Description
private

Method Summary

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

walkerback to summary
pack-priv static final StackWalker walker

Constructor Detail

HolderStackWalkerback to summary
private HolderStackWalker()