< prev index next >

src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java

Print this page
rev 49703 : 8200559: Java agents doing instrumentation need a means to define auxiliary classes
Reviewed-by: duke

@@ -23,12 +23,10 @@
  * questions.
  */
 
 package java.lang.instrument;
 
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 
 /*
  * Copyright 2003 Wily Technology, Inc.
  */

@@ -140,20 +138,26 @@
  * retransformed or redefined, the
  * transformer must insure that the second class output class file is a legal
  * redefinition of the first output class file.
  *
  * <P>
+ * The transformers can define additional classes when a class is
+ * being transformed via {@link ClassDefiner#defineClass(byte[])
+ * ClassDefiner.defineClass}. They will be defined to the same class loader and
+ * the same protection domain as the class being transformed.
+ *
+ * <P>
  * 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 <code>null</code>.
+ * Thus, throwing an exception has the same effect as returning {@code null}.
  * To prevent unexpected behavior when unchecked exceptions are generated
  * in transformer code, a transformer can catch <code>Throwable</code>.
  * If the transformer believes the <code>classFileBuffer</code> does not
  * represent a validly formatted class file, it should throw
  * an <code>IllegalClassFormatException</code>;
- * while this has the same effect as returning null. it facilitates the
+ * while this has the same effect as returning {@code null}, it facilitates the
  * logging or debugging of format corruptions.
  *
  * <P>
  * Note the term <i>class file</i> is used as defined in section 3.1 of
  * <cite>The Java&trade; Virtual Machine Specification</cite>, to mean a

@@ -163,10 +167,54 @@
  * @see     java.lang.instrument.Instrumentation
  * @since   1.5
  */
 
 public interface ClassFileTransformer {
+    /**
+     * A {@code ClassDefiner} provides the mechanism for {@code ClassFileTransformer}
+     * to define additional classes during the
+     * {@linkplain ClassFileTransformer#transform(ClassDefiner, Module, ClassLoader, String, Class, ProtectionDomain, byte[])
+     * transformation process} of a class.
+     *
+     * <p> When a {@linkplain ClassFileTransformer#transform(ClassDefiner, Module, ClassLoader, String, Class, ProtectionDomain, byte[])
+     * transformer} is called to retransform a class, the transformer can call
+     * {@link ClassDefiner#defineClass(byte[])} to define additional classes.
+     * If it is called after {@link ClassFileTransformer#transform(ClassDefiner, Module, ClassLoader, String, Class, ProtectionDomain, byte[])
+     * ClassFileTransformer.tranform} method returns or called by another
+     * thread, {@code IllegalStateException} will be thrown.
+     *
+     * @since 11
+     */
+    static interface ClassDefiner {
+        /**
+         * Defines a class of the given bytes to the runtime.
+         * The given bytes will be defined to the same class loader and in the
+         * same runtime package and
+         * {@linkplain java.security.ProtectionDomain protection domain} as
+         * the class being transformed.
+         *
+         * <p> No transformation is applied to the bytes passed to this
+         * {@code ClassDefiner.defineClass} method.
+         * {@link Instrumentation#retransformClasses(Class[])} can be called
+         * later to retransform the {@code Class} returned by this method
+         * if desired.
+         *
+         * @param bytes the class bytes
+         * @return the {@code Class} object for the class
+         *
+         * @throws IllegalArgumentException
+         *         the bytes are for a class of a different package than
+         *         the class being transformed
+         * @throws LinkageError if the class is malformed ({@code ClassFormatError}),
+         *         cannot be verified ({@code VerifyError}), is already defined,
+         *         or another linkage error occurs
+         * @throws IllegalStateException if this {@code ClassDefiner} is called
+         *         by a thread other than the thread doing the transformation,
+         *         or after all transformers are called.
+         */
+        Class<?> defineClass(byte[] bytes);
+    }
 
     /**
      * Transforms the given class file and returns a new replacement class file.
      * This method is invoked when the {@link Module Module} bearing {@link
      * ClassFileTransformer#transform(Module,ClassLoader,String,Class,ProtectionDomain,byte[])

@@ -247,6 +295,61 @@
                          className,
                          classBeingRedefined,
                          protectionDomain,
                          classfileBuffer);
     }
+
+    /**
+     * Transforms the given class file and returns a new replacement class file.
+     *
+     * <p> A {@code ClassFileTransformer} may define additional classes
+     * to the same class loader and the same runtime package as the class being
+     * transformed by calling {@link ClassDefiner#defineClass(byte[])}
+     * classDefiner.defineClass} method.   If an attempt to use {@code classDefiner}
+     * is made after this {@code transform} method returns,
+     * {@code IllegalStateException} will be thrown.
+     *
+     * @implSpec The default implementation of this method invokes the
+     * {@link #transform(Module,ClassLoader,String,Class,ProtectionDomain,byte[]) transform}
+     * method.
+     *
+     * @param classDefiner          a {@code ClassDefiner} that this class transformer
+     *                              can define additional classes
+     * @param module                the module of the class to be transformed
+     * @param loader                the defining loader of the class to be transformed,
+     *                              may be {@code 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
+     *                              <i>The Java Virtual Machine Specification</i>.
+     *                              For example, <code>"java/util/List"</code>.
+     * @param classBeingRedefined   if this is triggered by a redefine or retransform,
+     *                              the class being redefined or retransformed;
+     *                              if this is a class load, {@code 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 {@code null} if no transform is performed
+     *
+     * @since  11
+     */
+    default byte[]
+    transform(  ClassFileTransformer.ClassDefiner classDefiner,
+                Module              module,
+                ClassLoader         loader,
+                String              className,
+                Class<?>            classBeingRedefined,
+                ProtectionDomain    protectionDomain,
+                byte[]              classfileBuffer)
+        throws IllegalClassFormatException {
+
+        // invoke the transform method
+        return transform(module,
+                         loader,
+                         className,
+                         classBeingRedefined,
+                         protectionDomain,
+                         classfileBuffer);
+    }
 }
< prev index next >