8159147: Add ClassLoader parameter to new ClassFileTransformer transform method

Add ClassLoader parameter to new ClassFileTransformer transform method

Reviewed-by: alanb, dholmes, dcubed, mchung
This commit is contained in:
Serguei Spitsyn 2016-07-09 21:41:14 -07:00
parent 327708637b
commit 3a2d3df9ed
9 changed files with 25 additions and 24 deletions

View File

@ -38,7 +38,7 @@ import java.security.ProtectionDomain;
* A transformer of class files. An agent registers an implementation of this
* interface using the {@link Instrumentation#addTransformer addTransformer}
* method so that the transformer's {@link
* ClassFileTransformer#transform(Module,String,Class,ProtectionDomain,byte[])
* ClassFileTransformer#transform(Module,ClassLoader,String,Class,ProtectionDomain,byte[])
* transform} method is invoked when classes are loaded,
* {@link Instrumentation#redefineClasses redefined}, or
* {@link Instrumentation#retransformClasses retransformed}. The implementation
@ -170,13 +170,13 @@ public interface ClassFileTransformer {
/**
* 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,String,Class,ProtectionDomain,byte[])
* ClassFileTransformer#transform(Module,ClassLoader,String,Class,ProtectionDomain,byte[])
* transform} is not overridden.
*
* @implSpec The default implementation returns null.
*
* @param loader the defining loader of the class to be transformed,
* may be <code>null</code> if the bootstrap loader
* 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>.
@ -208,9 +208,11 @@ public interface ClassFileTransformer {
*
* @implSpec The default implementation of this method invokes the
* {@link #transform(ClassLoader,String,Class,ProtectionDomain,byte[]) transform}
* method with the {@link Module#getClassLoader() ClassLoader} for the module.
* method.
*
* @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>.
@ -230,15 +232,13 @@ public interface ClassFileTransformer {
*/
default byte[]
transform( Module module,
ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer)
throws IllegalClassFormatException {
PrivilegedAction<ClassLoader> pa = module::getClassLoader;
ClassLoader loader = AccessController.doPrivileged(pa);
// invoke the legacy transform method
return transform(loader,
className,

View File

@ -162,7 +162,7 @@ public interface Instrumentation {
* </li>
* <li>for each transformer that was added with <code>canRetransform</code>
* false, the bytes returned by
* {@link ClassFileTransformer#transform(Module,String,Class,ProtectionDomain,byte[])
* {@link ClassFileTransformer#transform(Module,ClassLoader,String,Class,ProtectionDomain,byte[])
* 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;
@ -170,7 +170,7 @@ public interface Instrumentation {
* </li>
* <li>for each transformer that was added with <code>canRetransform</code>
* true, the
* {@link ClassFileTransformer#transform(Module,String,Class,ProtectionDomain,byte[])
* {@link ClassFileTransformer#transform(Module,ClassLoader,String,Class,ProtectionDomain,byte[])
* transform} method is called in these transformers
* </li>
* <li>the transformed class file bytes are installed as the new

View File

@ -420,8 +420,8 @@ public class InstrumentationImpl implements Instrumentation {
// WARNING: the native code knows the name & signature of this method
private byte[]
transform( ClassLoader loader,
Module module,
transform( Module module,
ClassLoader loader,
String classname,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
@ -444,6 +444,7 @@ public class InstrumentationImpl implements Instrumentation {
return null; // no manager, no transform
} else {
return mgr.transform( module,
loader,
classname,
classBeingRedefined,
protectionDomain,

View File

@ -169,6 +169,7 @@ public class TransformerManager
public byte[]
transform( Module module,
ClassLoader loader,
String classname,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
@ -187,6 +188,7 @@ public class TransformerManager
try {
transformedBytes = transformer.transform( module,
loader,
classname,
classBeingRedefined,
protectionDomain,

View File

@ -771,12 +771,11 @@ addRedefineClassesCapability(JPLISAgent * agent) {
}
static jobject
getModuleObject(JNIEnv * jnienv,
getModuleObject(jvmtiEnv* jvmti,
jobject loaderObject,
const char* cname) {
jboolean errorOutstanding = JNI_FALSE;
jvmtiError err = JVMTI_ERROR_NONE;
jobject moduleObject = NULL;
jstring package = NULL;
/* find last slash in the class name */
char* last_slash = (cname == NULL) ? NULL : strrchr(cname, '/');
@ -789,14 +788,9 @@ getModuleObject(JNIEnv * jnienv,
}
pkg_name_buf[len] = '\0';
package = (*jnienv)->NewStringUTF(jnienv, pkg_name_buf);
jplis_assert_msg(package != NULL, "OOM error in NewStringUTF");
err = (*jvmti)->GetNamedModule(jvmti, loaderObject, pkg_name_buf, &moduleObject);
jplis_assert_msg(err == JVMTI_ERROR_NONE, "error in the JVMTI GetNamedModule");
moduleObject = JVM_GetModuleByPackageName(jnienv, loaderObject, package);
errorOutstanding = checkForAndClearThrowable(jnienv);
jplis_assert_msg(!errorOutstanding,
"error in lookup of a module of the class being instrumented");
free((void*)pkg_name_buf);
return moduleObject;
}
@ -862,7 +856,7 @@ transformClassFile( JPLISAgent * agent,
jobject moduleObject = NULL;
if (classBeingRedefined == NULL) {
moduleObject = getModuleObject(jnienv, loaderObject, name);
moduleObject = getModuleObject(jvmti(agent), loaderObject, name);
} else {
// Redefine or retransform, InstrumentationImpl.transform() will use
// classBeingRedefined.getModule() to get the module.
@ -873,8 +867,8 @@ transformClassFile( JPLISAgent * agent,
jnienv,
agent->mInstrumentationImpl,
agent->mTransform,
loaderObject,
moduleObject,
loaderObject,
classNameStringObject,
classBeingRedefined,
protectionDomain,

View File

@ -66,7 +66,7 @@ typedef struct _JPLISEnvironment JPLISEnvironment;
#define JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODSIGNATURE "(Ljava/lang/String;Ljava/lang/String;)V"
#define JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODNAME "transform"
#define JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODSIGNATURE \
"(Ljava/lang/ClassLoader;Ljava/lang/reflect/Module;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[BZ)[B"
"(Ljava/lang/reflect/Module;Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[BZ)[B"
/*

View File

@ -302,6 +302,7 @@ ATransformerManagementTestCase
public byte[]
transform(
Module module,
ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
@ -311,6 +312,7 @@ ATransformerManagementTestCase
if (classBeingRedefined != null) checkInTransformer(MyClassFileTransformer.this);
return super.transform( module,
loader,
className,
classBeingRedefined,
protectionDomain,

View File

@ -69,6 +69,7 @@ class RetransformAgent {
}
public byte[] transform(Module module,
ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,

View File

@ -63,6 +63,7 @@ SimpleIdentityTransformer implements ClassFileTransformer {
public byte[]
transform(
Module module,
ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,