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
This commit is contained in:
parent
57db621b70
commit
2b83edeb27
|
|
@ -16,7 +16,9 @@
|
||||||
|
|
||||||
package org.springframework.boot.loader;
|
package org.springframework.boot.loader;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.JarURLConnection;
|
import java.net.JarURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
|
|
@ -38,6 +40,8 @@ import org.springframework.boot.loader.jar.Handler;
|
||||||
*/
|
*/
|
||||||
public class LaunchedURLClassLoader extends URLClassLoader {
|
public class LaunchedURLClassLoader extends URLClassLoader {
|
||||||
|
|
||||||
|
private static final int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ClassLoader.registerAsParallelCapable();
|
ClassLoader.registerAsParallelCapable();
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +100,7 @@ public class LaunchedURLClassLoader extends URLClassLoader {
|
||||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||||
if (name.startsWith("org.springframework.boot.loader.jarmode.")) {
|
if (name.startsWith("org.springframework.boot.loader.jarmode.")) {
|
||||||
try {
|
try {
|
||||||
Class<?> result = findClass(name);
|
Class<?> result = loadClassInLaunchedClassLoader(name);
|
||||||
if (resolve) {
|
if (resolve) {
|
||||||
resolveClass(result);
|
resolveClass(result);
|
||||||
}
|
}
|
||||||
|
|
@ -129,6 +133,35 @@ public class LaunchedURLClassLoader extends URLClassLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Class<?> loadClassInLaunchedClassLoader(String name) throws ClassNotFoundException {
|
||||||
|
String internalName = name.replace('.', '/') + ".class";
|
||||||
|
InputStream inputStream = getParent().getResourceAsStream(internalName);
|
||||||
|
if (inputStream == null) {
|
||||||
|
throw new ClassNotFoundException(name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
byte[] buffer = new byte[BUFFER_SIZE];
|
||||||
|
int bytesRead = -1;
|
||||||
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
inputStream.close();
|
||||||
|
byte[] bytes = outputStream.toByteArray();
|
||||||
|
Class<?> definedClass = defineClass(name, bytes, 0, bytes.length);
|
||||||
|
definePackageIfNecessary(name);
|
||||||
|
return definedClass;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new ClassNotFoundException("Cannot load resource for class [" + name + "]", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a package before a {@code findClass} call is made. This is necessary to
|
* Define a package before a {@code findClass} call is made. This is necessary to
|
||||||
* ensure that the appropriate manifest for nested JARs is associated with the
|
* ensure that the appropriate manifest for nested JARs is associated with the
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue