Skip to content

Commit e48ed10

Browse files
committed
Throw ClassNotFoundException for missing class resource
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. Re-throw the original ClassNotFoundException when the resource fallback yields no class. Signed-off-by: junhyeong9812 <pickjog@gmail.com>
1 parent 0c60266 commit e48ed10

2 files changed

Lines changed: 54 additions & 1 deletion

File tree

spring-core/src/main/java/org/springframework/aot/nativex/feature/ThrowawayClassLoader.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
5454
return super.loadClass(name, true);
5555
}
5656
catch (ClassNotFoundException ex) {
57-
return loadClassFromResource(name);
57+
Class<?> loadedFromResource = loadClassFromResource(name);
58+
if (loadedFromResource == null) {
59+
throw ex;
60+
}
61+
return loadedFromResource;
5862
}
5963
}
6064
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2002-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.aot.nativex.feature;
18+
19+
import java.io.InputStream;
20+
21+
import org.junit.jupiter.api.Test;
22+
23+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
24+
25+
/**
26+
* Tests for {@link ThrowawayClassLoader}.
27+
*
28+
* @author Junhyeong Kim
29+
*/
30+
class ThrowawayClassLoaderTests {
31+
32+
@Test
33+
void loadClassThrowsClassNotFoundExceptionWhenClassResourceIsMissing() {
34+
// The grandparent resolves bootstrap classes only, so super.loadClass(...) fails,
35+
// and the resource loader provides no class bytes. The fallback must then honor the
36+
// ClassLoader.loadClass contract by reporting the failure instead of returning null.
37+
ClassLoader resourceLoader = new ClassLoader(new ClassLoader(null) {}) {
38+
@Override
39+
public InputStream getResourceAsStream(String name) {
40+
return null;
41+
}
42+
};
43+
ThrowawayClassLoader classLoader = new ThrowawayClassLoader(resourceLoader);
44+
45+
assertThatExceptionOfType(ClassNotFoundException.class)
46+
.isThrownBy(() -> classLoader.loadClass("com.example.MissingClass"));
47+
}
48+
49+
}

0 commit comments

Comments
 (0)