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
pull/19880/head
Phillip Webb 5 years ago
parent 57db621b70
commit 2b83edeb27

@ -16,7 +16,9 @@
package org.springframework.boot.loader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
@ -38,6 +40,8 @@ import org.springframework.boot.loader.jar.Handler;
*/
public class LaunchedURLClassLoader extends URLClassLoader {
private static final int BUFFER_SIZE = 4096;
static {
ClassLoader.registerAsParallelCapable();
}
@ -96,7 +100,7 @@ public class LaunchedURLClassLoader extends URLClassLoader {
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if (name.startsWith("org.springframework.boot.loader.jarmode.")) {
try {
Class<?> result = findClass(name);
Class<?> result = loadClassInLaunchedClassLoader(name);
if (resolve) {
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
* ensure that the appropriate manifest for nested JARs is associated with the

Loading…
Cancel
Save