Java 包解析:java.lang.instrument

Java 包解析:java.lang.instrument_第1张图片
Java 包解析:java.lang.instrument_第2张图片

//这是一个包装类:将需要重新定义的类和增强字节码包装在一起
package java.lang.instrument
 //这个类作为Instrumentation.redefineClasses方法的参数
 //用于将需要重新定义的类绑定到新的字节码中
public final class ClassDefinition {    
    //需要重新定义的类
    private final Class mClass;
    //替换的字节码
    private final byte[]   mClassFile;
    //创建一个新的类绑定类和类文件字节码。
    //不复制提供的缓冲区,只是捕获对它的引用。只是赋值操作
   public ClassDefinition(Class theClass,byte[] theClassFile){
        if (theClass == null || theClassFile == null) {
          //传入参数为空
           throw new NullPointerException();
        }
        //赋值操作
        mClass=theClass;
        mClassFile=theClassFile;
    }
   public Class getDefinitionClass() {
        return mClass;
    }
  //返回包含新类文件的字节数组。
    public byte[] getDefinitionClassFile() {
        return mClassFile;
    }
}
package java.lang.instrument;

import  java.security.ProtectionDomain;

/**
  一个代理类提供了这个接口的实现用于转化class文件(字节码文件)。转换发生在class 被JVM定义之前。注意术语“class file”被用于定义在3.1"Java™ Virtual Machine Specification",虚拟机规范是指类文件格式中的一系列字节,不管它们是否驻留在文件中。
**/

public interface ClassFileTransformer {
   /**
此方法的实现可能会转换提供的类文件并返回一个新的替换类文件。有两种变换器,由java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer ,boolean)的“canRetransform”参数确定。
    a.canRetransform=true 允许重新转换
    b.canRetransform=false 不允许重新转换
    c.addTransformer(ClassFileTransformer) 不允许重新转换
一旦转换器已经用java.lang.instrument.Instrumentation注册#addTransformer(ClassFileTransformer,boolean)
addTransformer,将为每个新的类定义和每个类的重新定义调用转换器。每个类重新转换也将调用能够转换的变换器.
    /**
     * The implementation of this method may transform the supplied class file and
     * return a new replacement class file.
     *
     * 

* There are two kinds of transformers, determined by the canRetransform * parameter of * {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer,boolean)}: *

    *
  • retransformation capable transformers that were added with * canRetransform as true *
  • *
  • retransformation incapable transformers that were added with * canRetransform as false or where added with * {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer)} *
  • *
* *

* Once a transformer has been registered with * {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer,boolean) * addTransformer}, * the transformer will be called for every new class definition and every class redefinition. * Retransformation capable transformers will also be called on every class retransformation. * The request for a new class definition is made with * {@link java.lang.ClassLoader#defineClass ClassLoader.defineClass} * or its native equivalents. * The request for a class redefinition is made with * {@link java.lang.instrument.Instrumentation#redefineClasses Instrumentation.redefineClasses} * or its native equivalents. * The request for a class retransformation is made with * {@link java.lang.instrument.Instrumentation#retransformClasses Instrumentation.retransformClasses} * or its native equivalents. * The transformer is called during the processing of the request, before the class file bytes * have been verified or applied. * When there are multiple transformers, transformations are composed by chaining the * transform calls. * That is, the byte array returned by one call to transform becomes the input * (via the classfileBuffer parameter) to the next call. * *

* Transformations are applied in the following order: *

    *
  • Retransformation incapable transformers *
  • *
  • Retransformation incapable native transformers *
  • *
  • Retransformation capable transformers *
  • *
  • Retransformation capable native transformers *
  • *
* *

* For retransformations, the retransformation incapable transformers are not * called, instead the result of the previous transformation is reused. * In all other cases, this method is called. * Within each of these groupings, transformers are called in the order registered. * Native transformers are provided by the ClassFileLoadHook event * in the Java Virtual Machine Tool Interface). * *

* The input (via the classfileBuffer parameter) to the first * transformer is: *

    *
  • for new class definition, * the bytes passed to ClassLoader.defineClass *
  • *
  • for class redefinition, * definitions.getDefinitionClassFile() where * definitions is the parameter to * {@link java.lang.instrument.Instrumentation#redefineClasses * Instrumentation.redefineClasses} *
  • *
  • for class retransformation, * the bytes passed to the new class definition or, if redefined, * the last redefinition, with all transformations made by retransformation * incapable transformers reapplied automatically and unaltered; * for details see * {@link java.lang.instrument.Instrumentation#retransformClasses * Instrumentation.retransformClasses} *
  • *
* *

* If the implementing method determines that no transformations are needed, * it should return null. * Otherwise, it should create a new byte[] array, * copy the input classfileBuffer into it, * along with all desired transformations, and return the new array. * The input classfileBuffer must not be modified. * *

* In the retransform and redefine cases, * the transformer must support the redefinition semantics: * if a class that the transformer changed during initial definition is later * retransformed or redefined, the * transformer must insure that the second class output class file is a legal * redefinition of the first output class file. * *

* If the transformer throws an exception (which it doesn't catch), * subsequent transformers will still be called and the load, redefine * or retransform will still be attempted. * Thus, throwing an exception has the same effect as returning null. * To prevent unexpected behavior when unchecked exceptions are generated * in transformer code, a transformer can catch Throwable. * If the transformer believes the classFileBuffer does not * represent a validly formatted class file, it should throw * an IllegalClassFormatException; * while this has the same effect as returning null. it facilitates the * logging or debugging of format corruptions. * * @param loader the defining loader of the class to be transformed, * may be null if the bootstrap loader * @param className the name of the class in the internal form of fully * qualified class and interface names as defined in * The Java Virtual Machine Specification. * For example, "java/util/List". * @param classBeingRedefined if this is triggered by a redefine or retransform, * the class being redefined or retransformed; * if this is a class load, null * @param protectionDomain the protection domain of the class being defined or redefined * @param classfileBuffer the input byte buffer in class file format - must not be modified * * @throws IllegalClassFormatException if the input does not represent a well-formed class file * @return a well-formed class file buffer (the result of the transform), or null if no transform is performed. * @see Instrumentation#redefineClasses */ byte[] transform( ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException; }

/*
 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang.instrument;

import  java.io.File;
import  java.io.IOException;
import  java.util.jar.JarFile;

/*
 * Copyright 2003 Wily Technology, Inc.
 */

/**
 * 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: * *

    *
  1. 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. *

  2. *
  3. 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.

  4. *
*

* These mechanisms are described in the * {@linkplain java.lang.instrument package specification}. *

* Once an agent acquires an Instrumentation instance, * the agent may call methods on the instance at any time. * * @since 1.5 */ public interface Instrumentation { /** * 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 * {@linkplain #redefineClasses redefined}. and if canRetransform is true, * when they are {@linkplain #retransformClasses retransformed}. * See {@link java.lang.instrument.ClassFileTransformer#transform * 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 * transformer class. *

* This method is intended for use in instrumentation, as described in the * {@linkplain Instrumentation class specification}. * * @param transformer the transformer to register * @param canRetransform can this transformer's transformations be retransformed * @throws java.lang.NullPointerException if passed a null transformer * @throws 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 */ void addTransformer(ClassFileTransformer transformer, boolean canRetransform); /** * Registers the supplied transformer. *

* Same as addTransformer(transformer, false). * * @param transformer the transformer to register * @throws java.lang.NullPointerException if passed a null transformer * @see #addTransformer(ClassFileTransformer,boolean) */ void addTransformer(ClassFileTransformer transformer); /** * 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. * * @param transformer the transformer to unregister * @return true if the transformer was found and removed, false if the * transformer was not found * @throws java.lang.NullPointerException if passed a null transformer */ boolean removeTransformer(ClassFileTransformer transformer); /** * 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 * {@linkplain java.lang.instrument 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. * @return true if the current JVM configuration supports retransformation of * classes, false if not. * @see #retransformClasses * @since 1.6 */ boolean isRetransformClassesSupported(); /** * Retransform the supplied set of classes. * *

* This function facilitates the instrumentation * of already loaded classes. * When classes are initially loaded or when they are * {@linkplain #redefineClasses redefined}, * the initial class file bytes can be transformed with the * {@link java.lang.instrument.ClassFileTransformer 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 * {@link java.lang.instrument.ClassFileTransformer#transform 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 * {@link java.lang.instrument.ClassFileTransformer#transform transform} * is not called *
  • *
  • for each transformer that was added with canRetransform * true, the * {@link java.lang.instrument.ClassFileTransformer#transform 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 the * {@link java.lang.instrument.ClassFileTransformer#transform 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 * {@link java.lang.ClassLoader#defineClass ClassLoader.defineClass} or * {@link #redefineClasses 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 * {@linkplain Instrumentation class specification}. * * @param 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) * @throws 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 * @throws java.lang.ClassFormatError if the data did not contain a valid class * @throws java.lang.NoClassDefFoundError if the name in the class file is not equal to the name of the class * @throws java.lang.UnsupportedClassVersionError if the class file version numbers are not supported * @throws java.lang.ClassCircularityError if the new classes contain a circularity * @throws java.lang.LinkageError if a linkage error occurs * @throws java.lang.NullPointerException if the supplied classes array or any of its components * is null. * * @see #isRetransformClassesSupported * @see #addTransformer * @see java.lang.instrument.ClassFileTransformer * @since 1.6 */ void retransformClasses(Class... classes) throws UnmodifiableClassException; /** * 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 * {@linkplain java.lang.instrument 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. * @return true if the current JVM configuration supports redefinition of classes, * false if not. * @see #redefineClasses */ boolean isRedefineClassesSupported(); /** * 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) * {@link #retransformClasses 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 * {@linkplain Instrumentation class specification}. * * @param 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) * @throws 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 * @throws java.lang.ClassFormatError if the data did not contain a valid class * @throws java.lang.NoClassDefFoundError if the name in the class file is not equal to the name of the class * @throws java.lang.UnsupportedClassVersionError if the class file version numbers are not supported * @throws java.lang.ClassCircularityError if the new classes contain a circularity * @throws java.lang.LinkageError if a linkage error occurs * @throws java.lang.NullPointerException if the supplied definitions array or any of its components * is null * @throws java.lang.ClassNotFoundException Can never be thrown (present for compatibility reasons only) * * @see #isRedefineClassesSupported * @see #addTransformer * @see java.lang.instrument.ClassFileTransformer */ void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException, UnmodifiableClassException; /** * Determines whether a class is modifiable by * {@linkplain #retransformClasses retransformation} * or {@linkplain #redefineClasses 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, {@link #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, {@link #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. * * @param theClass the class to check for being modifiable * @return whether or not the argument class is modifiable * @throws java.lang.NullPointerException if the specified class is null. * * @see #retransformClasses * @see #isRetransformClassesSupported * @see #redefineClasses * @see #isRedefineClassesSupported * @since 1.6 */ boolean isModifiableClass(Class theClass); /** * Returns an array of all classes currently loaded by the JVM. * * @return an array containing all the classes loaded by the JVM, zero-length if there are none */ @SuppressWarnings("rawtypes") Class[] getAllLoadedClasses(); /** * Returns an array of all classes for which loader is an initiating loader. * If the supplied loader is null, classes initiated by the bootstrap class * loader are returned. * * @param loader the loader whose initiated class list will be returned * @return an array containing all the classes for which loader is an initiating loader, * zero-length if there are none */ @SuppressWarnings("rawtypes") Class[] getInitiatedClasses(ClassLoader loader); /** * 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. * * @param objectToSize the object to size * @return an implementation-specific approximation of the amount of storage consumed by the specified object * @throws java.lang.NullPointerException if the supplied Object is null. */ long getObjectSize(Object objectToSize); /** * 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 {@link * java.util.jar.JarFile 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. * * @param jarfile * The JAR file to be searched when the bootstrap class loader * unsuccessfully searches for a class. * * @throws NullPointerException * If jarfile is null. * * @see #appendToSystemClassLoaderSearch * @see java.lang.ClassLoader * @see java.util.jar.JarFile * * @since 1.6 */ void appendToBootstrapClassLoaderSearch(JarFile jarfile); /** * Specifies a JAR file with instrumentation classes to be defined by the * system class loader. * * When the system class loader for delegation (see * {@link java.lang.ClassLoader#getSystemClassLoader getSystemClassLoader()}) * unsuccessfully searches for a class, the entries in the {@link * java.util.jar.JarFile 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 * {@link #appendToBootstrapClassLoaderSearch * 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 {@link java.util.zip.ZipFile#getName * 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 * {@link java.lang.System#getProperties system property}. * * @param 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. * * @throws NullPointerException * If jarfile is null. * * @see #appendToBootstrapClassLoaderSearch * @see java.lang.ClassLoader#getSystemClassLoader * @see java.util.jar.JarFile * @since 1.6 */ void appendToSystemClassLoaderSearch(JarFile jarfile); /** * Returns whether the current JVM configuration supports * {@linkplain #setNativeMethodPrefix(ClassFileTransformer,String) * 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 * {@linkplain java.lang.instrument 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. * @return true if the current JVM configuration supports * setting a native method prefix, false if not. * @see #setNativeMethodPrefix * @since 1.6 */ boolean isNativeMethodPrefixSupported(); /** * This method modifies the failure handling of * native method resolution by allowing retry * with a prefix applied to the name. * When used with the * {@link java.lang.instrument.ClassFileTransformer 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: *

{@code
     *   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: *

{@code
     *   method(wrapped_foo) -> nativeImplementation(foo)
     * }
*

* For automatic resolution, the JVM will attempt: *

{@code
     *   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: *

{@code
     *   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 {@link #addTransformer(ClassFileTransformer,boolean) 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. * * @param transformer * The ClassFileTransformer which wraps using this prefix. * @param prefix * The prefix to apply to wrapped native methods when * retrying a failed native method resolution. If prefix * is either null or the empty string, then * failed native method resolutions are not retried for * this transformer. * @throws java.lang.NullPointerException if passed a null transformer. * @throws java.lang.UnsupportedOperationException if the current configuration of * the JVM does not allow setting a native method prefix * ({@link #isNativeMethodPrefixSupported} is false). * @throws java.lang.IllegalArgumentException if the transformer is not registered * (see {@link #addTransformer(ClassFileTransformer,boolean) addTransformer}). * * @since 1.6 */ void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix); }

你可能感兴趣的:(java)