Commit 951d0b0f authored by Phillip Webb's avatar Phillip Webb

Fix exploded jar classloader issues

Fix a bug in `ExplodedURLClassLoader` and merge the code into the
existing `LaunchedURLClassLoader` class. Also polish a few method
names relating to layer support.

See gh-19848
See gh-19767
parent b4229239
......@@ -164,8 +164,8 @@ public abstract class ExecutableArchiveLauncher extends Launcher {
}
@Override
protected boolean supportsNestedJars() {
return this.archive.supportsNestedJars();
protected boolean isExploded() {
return this.archive.isExploded();
}
/**
......
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.loader;
import java.net.URL;
import java.net.URLClassLoader;
/**
* {@link URLClassLoader} used for exploded archives.
*
* @author Phillip Webb
*/
class ExplodedURLClassLoader extends URLClassLoader {
ExplodedURLClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
try {
Class<?> result = findClass(name);
if (resolve) {
resolveClass(result);
}
return result;
}
catch (ClassNotFoundException ex) {
}
return super.loadClass(name, resolve);
}
}
......@@ -42,17 +42,33 @@ public class LaunchedURLClassLoader extends URLClassLoader {
ClassLoader.registerAsParallelCapable();
}
private final boolean exploded;
/**
* Create a new {@link LaunchedURLClassLoader} instance.
* @param urls the URLs from which to load classes and resources
* @param parent the parent class loader for delegation
*/
public LaunchedURLClassLoader(URL[] urls, ClassLoader parent) {
this(false, urls, parent);
}
/**
* Create a new {@link LaunchedURLClassLoader} instance.
* @param exploded the the underlying archive is exploded
* @param urls the URLs from which to load classes and resources
* @param parent the parent class loader for delegation
*/
public LaunchedURLClassLoader(boolean exploded, URL[] urls, ClassLoader parent) {
super(urls, parent);
this.exploded = exploded;
}
@Override
public URL findResource(String name) {
if (this.exploded) {
return super.findResource(name);
}
Handler.setUseFastConnectionExceptions(true);
try {
return super.findResource(name);
......@@ -64,6 +80,9 @@ public class LaunchedURLClassLoader extends URLClassLoader {
@Override
public Enumeration<URL> findResources(String name) throws IOException {
if (this.exploded) {
return super.findResources(name);
}
Handler.setUseFastConnectionExceptions(true);
try {
return new UseFastConnectionExceptionsEnumeration(super.findResources(name));
......@@ -86,6 +105,9 @@ public class LaunchedURLClassLoader extends URLClassLoader {
catch (ClassNotFoundException ex) {
}
}
if (this.exploded) {
return super.loadClass(name, resolve);
}
Handler.setUseFastConnectionExceptions(true);
try {
try {
......@@ -168,6 +190,9 @@ public class LaunchedURLClassLoader extends URLClassLoader {
* Clear URL caches.
*/
public void clearCache() {
if (this.exploded) {
return;
}
for (URL url : getURLs()) {
try {
URLConnection connection = url.openConnection();
......
......@@ -49,7 +49,7 @@ public abstract class Launcher {
* @throws Exception if the application fails to launch
*/
protected void launch(String[] args) throws Exception {
if (supportsNestedJars()) {
if (!isExploded()) {
JarFile.registerUrlProtocolHandler();
}
ClassLoader classLoader = createClassLoader(getClassPathArchivesIterator());
......@@ -94,10 +94,7 @@ public abstract class Launcher {
* @throws Exception if the classloader cannot be created
*/
protected ClassLoader createClassLoader(URL[] urls) throws Exception {
if (supportsNestedJars()) {
return new LaunchedURLClassLoader(urls, getClass().getClassLoader());
}
return new ExplodedURLClassLoader(urls, getClass().getClassLoader());
return new LaunchedURLClassLoader(isExploded(), urls, getClass().getClassLoader());
}
/**
......@@ -168,12 +165,12 @@ public abstract class Launcher {
}
/**
* Returns if the launcher needs to support fully nested JARs. If this method returns
* {@code false} then only regular JARs are supported and the additional URL and
* ClassLoader support infrastructure will not be installed.
* @return if nested JARs are supported
* Returns if the launcher is running in an exploded mode. If this method returns
* {@code true} then only regular JARs are supported and the additional URL and
* ClassLoader support infrastructure can be optimized.
* @return if the jar is exploded.
*/
protected boolean supportsNestedJars() {
protected boolean isExploded() {
return true;
}
......
......@@ -90,8 +90,12 @@ public interface Archive extends Iterable<Archive.Entry>, AutoCloseable {
@Override
Iterator<Entry> iterator();
default boolean supportsNestedJars() {
return true;
/**
* Return if the archive is exploded (already unpacked).
* @return if the archive is exploded
*/
default boolean isExploded() {
return false;
}
/**
......
......@@ -114,8 +114,8 @@ public class ExplodedArchive implements Archive {
}
@Override
public boolean supportsNestedJars() {
return false;
public boolean isExploded() {
return true;
}
@Override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment