From a31180dd684d5775da743d21db3c448c78159022 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 18 Oct 2016 13:35:33 +0100 Subject: [PATCH] Avoid calling URL.getContent() when defining a package URL.getContent() is shorthand for URL.openConnection().getContent(). It creates an InputStream that isn't explicitly closed. This means that a file handle remains open until the URLConnection is garbage collected. This can lead to the process exceeding the limit for open files. Previously, LaunchedURLClassLoader was using getConent() when proactively defining a package for a class that is about to be loaded. getContent() was used to access nested jar files to check if they contained the package and, if so, to retrieve the jar's manifest. In place of using getContent(), this commit uses JarURLConnection's getJarFile() method which provides access to the JarFile without the unwanted side-effect of opening an input stream. Closes gh-7180 --- .../boot/loader/LaunchedURLClassLoader.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java index 5609899813b..0ac84d87655 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java @@ -24,9 +24,9 @@ import java.net.URLConnection; import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.util.Enumeration; +import java.util.jar.JarFile; import org.springframework.boot.loader.jar.Handler; -import org.springframework.boot.loader.jar.JarFile; /** * {@link ClassLoader} used by the {@link Launcher}. @@ -131,8 +131,10 @@ public class LaunchedURLClassLoader extends URLClassLoader { String classEntryName = className.replace(".", "/") + ".class"; for (URL url : getURLs()) { try { - if (url.getContent() instanceof JarFile) { - JarFile jarFile = (JarFile) url.getContent(); + URLConnection connection = url.openConnection(); + if (connection instanceof JarURLConnection) { + JarFile jarFile = ((JarURLConnection) connection) + .getJarFile(); if (jarFile.getEntry(classEntryName) != null && jarFile.getEntry(packageEntryName) != null && jarFile.getManifest() != null) { @@ -175,8 +177,8 @@ public class LaunchedURLClassLoader extends URLClassLoader { private void clearCache(URLConnection connection) throws IOException { Object jarFile = ((JarURLConnection) connection).getJarFile(); - if (jarFile instanceof JarFile) { - ((JarFile) jarFile).clearCache(); + if (jarFile instanceof org.springframework.boot.loader.jar.JarFile) { + ((org.springframework.boot.loader.jar.JarFile) jarFile).clearCache(); } }