From 50e967463173e4f4209b3d18ab2b1665f2b1b02f Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 27 Apr 2020 19:03:52 -0700 Subject: [PATCH] Backport "Attempt to prevent JarFiles from being left open" Update `JarFile` so that `super.close()` is called early so that the file is not left open. Since we re-implement `JarFile` methods to work directly on the underlying `RandomAccessDataFile`, it should be safe to close immediately. Closes gh-21177 --- .../springframework/boot/loader/jar/JarFile.java | 13 ++++++++++++- .../boot/loader/jar/JarURLConnectionTests.java | 4 +--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java index 82bc85cef8..2649588f6e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java @@ -84,6 +84,8 @@ public class JarFile extends java.util.jar.JarFile { private String comment; + private volatile boolean closed; + /** * Create a new {@link JarFile} backed by the specified file. * @param file the root jar file @@ -109,6 +111,7 @@ public class JarFile extends java.util.jar.JarFile { */ JarFile(JarFile parent) throws IOException { super(parent.rootFile.getFile()); + super.close(); this.parent = parent; this.rootFile = parent.rootFile; this.pathFromRoot = parent.pathFromRoot; @@ -140,6 +143,7 @@ public class JarFile extends java.util.jar.JarFile { private JarFile(JarFile parent, RandomAccessDataFile rootFile, String pathFromRoot, RandomAccessData data, JarEntryFilter filter, JarFileType type, Supplier manifestSupplier) throws IOException { super(rootFile.getFile()); + super.close(); this.parent = parent; this.rootFile = rootFile; this.pathFromRoot = pathFromRoot; @@ -334,12 +338,19 @@ public class JarFile extends java.util.jar.JarFile { @Override public void close() throws IOException { - super.close(); + if (this.closed) { + return; + } + this.closed = true; if (this.type == JarFileType.DIRECT && this.parent == null) { this.rootFile.close(); } } + boolean isClosed() { + return this.closed; + } + String getUrlString() throws MalformedURLException { if (this.urlString == null) { this.urlString = getUrl().toString(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java index fcaa296dda..e03ad09cd6 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java @@ -20,7 +20,6 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.net.URL; -import java.util.zip.ZipFile; import org.junit.Before; import org.junit.Rule; @@ -29,7 +28,6 @@ import org.junit.rules.TemporaryFolder; import org.springframework.boot.loader.TestJarCreator; import org.springframework.boot.loader.jar.JarURLConnection.JarEntryName; -import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -201,7 +199,7 @@ public class JarURLConnectionTests { JarURLConnection connection = JarURLConnection.get(url, this.jarFile); JarFile connectionJarFile = connection.getJarFile(); connectionJarFile.close(); - assertThat((Boolean) ReflectionTestUtils.getField(this.jarFile, ZipFile.class, "closeRequested")).isFalse(); + assertThat(this.jarFile.isClosed()).isFalse(); } private String getRelativePath() {