Skip to content

Commit 16fd70a

Browse files
committed
Avoid illegal reflective access in ContextOverridingClassLoader
Closes gh-22791 (cherry picked from commit 0b02a5e)
1 parent c1bf099 commit 16fd70a

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

spring-context/src/main/java/org/springframework/context/support/ContextTypeMatchClassLoader.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@
2121
import java.util.Map;
2222
import java.util.concurrent.ConcurrentHashMap;
2323

24+
import org.apache.commons.logging.LogFactory;
25+
2426
import org.springframework.core.DecoratingClassLoader;
2527
import org.springframework.core.OverridingClassLoader;
2628
import org.springframework.core.SmartClassLoader;
@@ -45,15 +47,26 @@ class ContextTypeMatchClassLoader extends DecoratingClassLoader implements Smart
4547
}
4648

4749

48-
private static Method findLoadedClassMethod;
50+
@Nullable
51+
private static final Method findLoadedClassMethod;
4952

5053
static {
54+
// Try to enable findLoadedClass optimization which allows us to selectively
55+
// override classes that have not been loaded yet. If not accessible, we will
56+
// always override requested classes, even when the classes have been loaded
57+
// by the parent ClassLoader already and cannot be transformed anymore anyway.
58+
Method method = null;
5159
try {
52-
findLoadedClassMethod = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
60+
method = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
61+
ReflectionUtils.makeAccessible(method);
5362
}
54-
catch (NoSuchMethodException ex) {
55-
throw new IllegalStateException("Invalid [java.lang.ClassLoader] class: no 'findLoadedClass' method defined!");
63+
catch (Throwable ex) {
64+
// Typically a JDK 9+ InaccessibleObjectException...
65+
// Avoid through JVM startup with --add-opens=java.base/java.lang=ALL-UNNAMED
66+
LogFactory.getLog(ContextTypeMatchClassLoader.class).debug(
67+
"ClassLoader.findLoadedClass not accessible -> will always override requested class", ex);
5668
}
69+
findLoadedClassMethod = method;
5770
}
5871

5972

@@ -96,13 +109,14 @@ protected boolean isEligibleForOverriding(String className) {
96109
if (isExcluded(className) || ContextTypeMatchClassLoader.this.isExcluded(className)) {
97110
return false;
98111
}
99-
ReflectionUtils.makeAccessible(findLoadedClassMethod);
100-
ClassLoader parent = getParent();
101-
while (parent != null) {
102-
if (ReflectionUtils.invokeMethod(findLoadedClassMethod, parent, className) != null) {
103-
return false;
112+
if (findLoadedClassMethod != null) {
113+
ClassLoader parent = getParent();
114+
while (parent != null) {
115+
if (ReflectionUtils.invokeMethod(findLoadedClassMethod, parent, className) != null) {
116+
return false;
117+
}
118+
parent = parent.getParent();
104119
}
105-
parent = parent.getParent();
106120
}
107121
return true;
108122
}

0 commit comments

Comments
 (0)