Only prefer JDK 9+ Lookup.defineClass API if ClassLoader matches
Closes gh-22416
This commit is contained in:
parent
7a7c7f51e3
commit
5d8a34fee6
|
|
@ -491,7 +491,10 @@ public class ReflectUtils {
|
|||
ProtectionDomain protectionDomain, Class<?> contextClass) throws Exception {
|
||||
|
||||
Class c = null;
|
||||
if (contextClass != null && privateLookupInMethod != null && lookupDefineClassMethod != null) {
|
||||
|
||||
// Preferred option: JDK 9+ Lookup.defineClass API if ClassLoader matches
|
||||
if (contextClass != null && contextClass.getClassLoader() == loader &&
|
||||
privateLookupInMethod != null && lookupDefineClassMethod != null) {
|
||||
try {
|
||||
MethodHandles.Lookup lookup = (MethodHandles.Lookup)
|
||||
privateLookupInMethod.invoke(null, contextClass, MethodHandles.lookup());
|
||||
|
|
@ -510,29 +513,52 @@ public class ReflectUtils {
|
|||
throw new CodeGenerationException(ex);
|
||||
}
|
||||
}
|
||||
if (protectionDomain == null) {
|
||||
protectionDomain = PROTECTION_DOMAIN;
|
||||
}
|
||||
if (c == null) {
|
||||
if (classLoaderDefineClassMethod != null) {
|
||||
Object[] args = new Object[]{className, b, 0, b.length, protectionDomain};
|
||||
try {
|
||||
if (!classLoaderDefineClassMethod.isAccessible()) {
|
||||
classLoaderDefineClassMethod.setAccessible(true);
|
||||
}
|
||||
c = (Class) classLoaderDefineClassMethod.invoke(loader, args);
|
||||
|
||||
// Classic option: protected ClassLoader.defineClass method
|
||||
if (c == null && classLoaderDefineClassMethod != null) {
|
||||
if (protectionDomain == null) {
|
||||
protectionDomain = PROTECTION_DOMAIN;
|
||||
}
|
||||
Object[] args = new Object[]{className, b, 0, b.length, protectionDomain};
|
||||
try {
|
||||
if (!classLoaderDefineClassMethod.isAccessible()) {
|
||||
classLoaderDefineClassMethod.setAccessible(true);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new CodeGenerationException(ex.getTargetException());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
c = (Class) classLoaderDefineClassMethod.invoke(loader, args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new CodeGenerationException(ex.getTargetException());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Fall through if setAccessible fails with InaccessibleObjectException on JDK 9+
|
||||
// (on the module path and/or with a JVM bootstrapped with --illegal-access=deny)
|
||||
if (!ex.getClass().getName().endsWith("InaccessibleObjectException")) {
|
||||
throw new CodeGenerationException(ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new CodeGenerationException(THROWABLE);
|
||||
}
|
||||
|
||||
// Fallback option: JDK 9+ Lookup.defineClass API even if ClassLoader does not match
|
||||
if (c == null && contextClass != null && contextClass.getClassLoader() != loader &&
|
||||
privateLookupInMethod != null && lookupDefineClassMethod != null) {
|
||||
try {
|
||||
MethodHandles.Lookup lookup = (MethodHandles.Lookup)
|
||||
privateLookupInMethod.invoke(null, contextClass, MethodHandles.lookup());
|
||||
c = (Class) lookupDefineClassMethod.invoke(lookup, b);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new CodeGenerationException(ex.getTargetException());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new CodeGenerationException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// No defineClass variant available at all?
|
||||
if (c == null) {
|
||||
throw new CodeGenerationException(THROWABLE);
|
||||
}
|
||||
|
||||
// Force static initializers to run.
|
||||
Class.forName(className, true, loader);
|
||||
return c;
|
||||
|
|
|
|||
Loading…
Reference in New Issue