Only prefer JDK 9+ Lookup.defineClass API if ClassLoader matches

Closes gh-22416
master
Juergen Hoeller 6 years ago
parent 7a7c7f51e3
commit 5d8a34fee6
  1. 62
      spring-core/src/main/java/org/springframework/cglib/core/ReflectUtils.java

@ -491,7 +491,10 @@ public class ReflectUtils {
ProtectionDomain protectionDomain, Class<?> contextClass) throws Exception { ProtectionDomain protectionDomain, Class<?> contextClass) throws Exception {
Class c = null; 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 { try {
MethodHandles.Lookup lookup = (MethodHandles.Lookup) MethodHandles.Lookup lookup = (MethodHandles.Lookup)
privateLookupInMethod.invoke(null, contextClass, MethodHandles.lookup()); privateLookupInMethod.invoke(null, contextClass, MethodHandles.lookup());
@ -510,29 +513,52 @@ public class ReflectUtils {
throw new CodeGenerationException(ex); throw new CodeGenerationException(ex);
} }
} }
if (protectionDomain == null) {
protectionDomain = PROTECTION_DOMAIN; // Classic option: protected ClassLoader.defineClass method
} if (c == null && classLoaderDefineClassMethod != null) {
if (c == null) { if (protectionDomain == null) {
if (classLoaderDefineClassMethod != null) { protectionDomain = PROTECTION_DOMAIN;
Object[] args = new Object[]{className, b, 0, b.length, protectionDomain}; }
try { Object[] args = new Object[]{className, b, 0, b.length, protectionDomain};
if (!classLoaderDefineClassMethod.isAccessible()) { try {
classLoaderDefineClassMethod.setAccessible(true); if (!classLoaderDefineClassMethod.isAccessible()) {
} classLoaderDefineClassMethod.setAccessible(true);
c = (Class) classLoaderDefineClassMethod.invoke(loader, args);
}
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); 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. // Force static initializers to run.
Class.forName(className, true, loader); Class.forName(className, true, loader);
return c; return c;

Loading…
Cancel
Save