From 77cbab794ef170f2e557e51d916cfdc895029777 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 17 Oct 2017 16:03:13 +0100 Subject: [PATCH] Make TomcatEmbeddedWebappClassLoader parallel capable Closes gh-10477 --- .../TomcatEmbeddedWebappClassLoader.java | 26 ++++++++++++------- .../TomcatEmbeddedWebappClassLoaderTests.java | 4 +-- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java index 67ee0ba34e..b938ab0a72 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java @@ -21,24 +21,28 @@ import java.net.URL; import java.util.Collections; import java.util.Enumeration; -import org.apache.catalina.loader.WebappClassLoader; +import org.apache.catalina.loader.ParallelWebappClassLoader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** - * Extension of Tomcat's {@link WebappClassLoader} that does not consider the + * Extension of Tomcat's {@link ParallelWebappClassLoader} that does not consider the * {@link ClassLoader#getSystemClassLoader() system classloader}. This is required to - * ensure that any custom context classloader is always used (as is the case with some + * ensure that any custom context class loader is always used (as is the case with some * executable archives). * * @author Phillip Webb * @since 2.0.0 */ -public class TomcatEmbeddedWebappClassLoader extends WebappClassLoader { +public class TomcatEmbeddedWebappClassLoader extends ParallelWebappClassLoader { private static final Log logger = LogFactory .getLog(TomcatEmbeddedWebappClassLoader.class); + static { + ClassLoader.registerAsParallelCapable(); + } + public TomcatEmbeddedWebappClassLoader() { super(); } @@ -58,14 +62,16 @@ public class TomcatEmbeddedWebappClassLoader extends WebappClassLoader { } @Override - public synchronized Class loadClass(String name, boolean resolve) + public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - Class result = findExistingLoadedClass(name); - result = (result == null ? doLoadClass(name) : result); - if (result == null) { - throw new ClassNotFoundException(name); + synchronized (getClassLoadingLock(name)) { + Class result = findExistingLoadedClass(name); + result = (result == null ? doLoadClass(name) : result); + if (result == null) { + throw new ClassNotFoundException(name); + } + return resolveIfNecessary(result, resolve); } - return resolveIfNecessary(result, resolve); } private Class findExistingLoadedClass(String name) { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoaderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoaderTests.java index 44a0c7028c..ed43994b13 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoaderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoaderTests.java @@ -28,7 +28,7 @@ import java.util.jar.JarOutputStream; import java.util.zip.ZipEntry; import org.apache.catalina.core.StandardContext; -import org.apache.catalina.loader.WebappClassLoader; +import org.apache.catalina.loader.ParallelWebappClassLoader; import org.apache.catalina.webresources.StandardRoot; import org.apache.catalina.webresources.WarResourceSet; import org.junit.Rule; @@ -73,7 +73,7 @@ public class TomcatEmbeddedWebappClassLoaderTests { throws Exception { URLClassLoader parent = new URLClassLoader( new URL[] { new URL(webInfClassesUrlString(war)) }, null); - try (WebappClassLoader classLoader = new TomcatEmbeddedWebappClassLoader( + try (ParallelWebappClassLoader classLoader = new TomcatEmbeddedWebappClassLoader( parent)) { StandardContext context = new StandardContext(); context.setName("test");