Commit a31180dd authored by Andy Wilkinson's avatar Andy Wilkinson

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
parent 24f8c737
...@@ -24,9 +24,9 @@ import java.net.URLConnection; ...@@ -24,9 +24,9 @@ import java.net.URLConnection;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.jar.JarFile;
import org.springframework.boot.loader.jar.Handler; import org.springframework.boot.loader.jar.Handler;
import org.springframework.boot.loader.jar.JarFile;
/** /**
* {@link ClassLoader} used by the {@link Launcher}. * {@link ClassLoader} used by the {@link Launcher}.
...@@ -131,8 +131,10 @@ public class LaunchedURLClassLoader extends URLClassLoader { ...@@ -131,8 +131,10 @@ public class LaunchedURLClassLoader extends URLClassLoader {
String classEntryName = className.replace(".", "/") + ".class"; String classEntryName = className.replace(".", "/") + ".class";
for (URL url : getURLs()) { for (URL url : getURLs()) {
try { try {
if (url.getContent() instanceof JarFile) { URLConnection connection = url.openConnection();
JarFile jarFile = (JarFile) url.getContent(); if (connection instanceof JarURLConnection) {
JarFile jarFile = ((JarURLConnection) connection)
.getJarFile();
if (jarFile.getEntry(classEntryName) != null if (jarFile.getEntry(classEntryName) != null
&& jarFile.getEntry(packageEntryName) != null && jarFile.getEntry(packageEntryName) != null
&& jarFile.getManifest() != null) { && jarFile.getManifest() != null) {
...@@ -175,8 +177,8 @@ public class LaunchedURLClassLoader extends URLClassLoader { ...@@ -175,8 +177,8 @@ public class LaunchedURLClassLoader extends URLClassLoader {
private void clearCache(URLConnection connection) throws IOException { private void clearCache(URLConnection connection) throws IOException {
Object jarFile = ((JarURLConnection) connection).getJarFile(); Object jarFile = ((JarURLConnection) connection).getJarFile();
if (jarFile instanceof JarFile) { if (jarFile instanceof org.springframework.boot.loader.jar.JarFile) {
((JarFile) jarFile).clearCache(); ((org.springframework.boot.loader.jar.JarFile) jarFile).clearCache();
} }
} }
......
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