Skip to content

Commit 2b83ede

Browse files
committed
Fix jarmode support in unexploded jars
Update `LaunchedURLClassLoader` to ensure that the `JarModeLauncher` is created in the correct classloader. Prior to this commit the launcher was created by the application classloader and did not have access to any of the required `org.springframework` classes. See gh-19848
1 parent 57db621 commit 2b83ede

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
package org.springframework.boot.loader;
1818

19+
import java.io.ByteArrayOutputStream;
1920
import java.io.IOException;
21+
import java.io.InputStream;
2022
import java.net.JarURLConnection;
2123
import java.net.URL;
2224
import java.net.URLClassLoader;
@@ -38,6 +40,8 @@
3840
*/
3941
public class LaunchedURLClassLoader extends URLClassLoader {
4042

43+
private static final int BUFFER_SIZE = 4096;
44+
4145
static {
4246
ClassLoader.registerAsParallelCapable();
4347
}
@@ -96,7 +100,7 @@ public Enumeration<URL> findResources(String name) throws IOException {
96100
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
97101
if (name.startsWith("org.springframework.boot.loader.jarmode.")) {
98102
try {
99-
Class<?> result = findClass(name);
103+
Class<?> result = loadClassInLaunchedClassLoader(name);
100104
if (resolve) {
101105
resolveClass(result);
102106
}
@@ -129,6 +133,35 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
129133
}
130134
}
131135

136+
private Class<?> loadClassInLaunchedClassLoader(String name) throws ClassNotFoundException {
137+
String internalName = name.replace('.', '/') + ".class";
138+
InputStream inputStream = getParent().getResourceAsStream(internalName);
139+
if (inputStream == null) {
140+
throw new ClassNotFoundException(name);
141+
}
142+
try {
143+
try {
144+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
145+
byte[] buffer = new byte[BUFFER_SIZE];
146+
int bytesRead = -1;
147+
while ((bytesRead = inputStream.read(buffer)) != -1) {
148+
outputStream.write(buffer, 0, bytesRead);
149+
}
150+
inputStream.close();
151+
byte[] bytes = outputStream.toByteArray();
152+
Class<?> definedClass = defineClass(name, bytes, 0, bytes.length);
153+
definePackageIfNecessary(name);
154+
return definedClass;
155+
}
156+
finally {
157+
inputStream.close();
158+
}
159+
}
160+
catch (IOException ex) {
161+
throw new ClassNotFoundException("Cannot load resource for class [" + name + "]", ex);
162+
}
163+
}
164+
132165
/**
133166
* Define a package before a {@code findClass} call is made. This is necessary to
134167
* ensure that the appropriate manifest for nested JARs is associated with the

0 commit comments

Comments
 (0)