< 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™ 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 >