-
CSR
-
Resolution: Withdrawn
-
P3
-
minimal
-
New API.
-
Java API
Summary
Update the java.lang.instrument API to allow agents doing load time or dynamic instrumentation to define additional classes in the same runtime package as the class being transformed.
Problem
Tool agents that instrument code with references to agent provided classes
need to ensure that those classes are visible to the and accessible to the
instrumented class. Instrumentation::appendToBootstrapClassLoaderSearch
​
and appendToSystemClassLoaderSearch​
APIs are too limited - they aren't
useful when the bytecode of the supporting classes is generated with the
intention of being loaded into the same runtime package as the instrumented
class (a non-public helper class for example).
Solution
Define a new java.lang.instrument.ClassFileTransformer.ClassDefiner
interface and a new java.lang.instrument.ClassFileTransformer::transform
method that takes ClassDefiner
parameter. This way an agent can define
additional classes in the same runtime package as the class being transformed.
Specification
- New
java.lang.instrument.ClassFileTransformer.ClassDefiner
interface and newjava.lang.instrument.ClassFileTransformer::transform
method that takes an additionalClassDefiner
parameter:
/**
* 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 NullPointerException
* {@code bytes} is {@code null}
* @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.
*
- <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
- The class specification of
ClassFileTransformer
is updated to mentionClassDefiner
.
@@ -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>
+ * Transformers may 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.
+ *
- blocks
-
JMC-6246 Making the agent stop using Unsafe
-
- Open
-
- csr of
-
JDK-8200559 Java agents doing instrumentation need a means to define auxiliary classes
-
- Open
-