mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-21 21:39:05 +00:00
Throw ClassNotFoundException for missing class resource in ThrowawayClassLoader
Prior to this commit, ThrowawayClassLoader.loadClass fell back to loadClassFromResource(), which returns null when no class resource is available. Returning null from loadClass violates the ClassLoader contract and leads to a NullPointerException in callers such as PreComputeFieldFeature. To address that, this commit rethrows the original ClassNotFoundException when the resource fallback yields no class. Closes gh-36938 Signed-off-by: junhyeong9812 <pickjog@gmail.com>
This commit is contained in:
+5
-1
@@ -54,7 +54,11 @@ class ThrowawayClassLoader extends ClassLoader {
|
||||
return super.loadClass(name, true);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
return loadClassFromResource(name);
|
||||
Class<?> loadedFromResource = loadClassFromResource(name);
|
||||
if (loadedFromResource == null) {
|
||||
throw ex;
|
||||
}
|
||||
return loadedFromResource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -25,6 +25,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for {@link ThrowawayClassLoader}.
|
||||
@@ -56,6 +57,23 @@ class ThrowawayClassLoaderTests {
|
||||
assertThat(closed).as("InputStream closed").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadClassThrowsClassNotFoundExceptionWhenClassResourceIsMissing() {
|
||||
// The grandparent resolves bootstrap classes only, so super.loadClass(...) fails,
|
||||
// and the resource loader provides no class bytes. The fallback must then honor the
|
||||
// ClassLoader.loadClass contract by reporting the failure instead of returning null.
|
||||
ClassLoader resourceLoader = new ClassLoader(new ClassLoader(null) {}) {
|
||||
@Override
|
||||
public InputStream getResourceAsStream(String name) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
ThrowawayClassLoader classLoader = new ThrowawayClassLoader(resourceLoader);
|
||||
|
||||
assertThatExceptionOfType(ClassNotFoundException.class)
|
||||
.isThrownBy(() -> classLoader.loadClass("com.example.MissingClass"));
|
||||
}
|
||||
|
||||
private static byte[] classBytesOf(String className) throws IOException {
|
||||
String resourceName = className.replace('.', '/') + ".class";
|
||||
try (InputStream in = ThrowawayClassLoaderTests.class.getClassLoader().getResourceAsStream(resourceName)) {
|
||||
|
||||
Reference in New Issue
Block a user