From a8777eda766a97698d2e0616216c0a1b142debc5 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 20 Jun 2014 09:20:55 -0700 Subject: [PATCH] Add JarFile caching Cache root jar files in the Handler and also store nested jar files in the JarEntryData. See gh-1119 --- .../boot/loader/jar/Handler.java | 32 ++++++++++++++++++- .../boot/loader/jar/JarEntryData.java | 2 ++ .../boot/loader/jar/JarFile.java | 19 +++++++---- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/Handler.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/Handler.java index 5f91138d92..fcc4b3d946 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/Handler.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/Handler.java @@ -18,11 +18,14 @@ package org.springframework.boot.loader.jar; import java.io.File; import java.io.IOException; +import java.lang.ref.SoftReference; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -55,6 +58,11 @@ public class Handler extends URLStreamHandler { OPEN_CONNECTION_METHOD = method; } + private static SoftReference> rootFileCache; + static { + rootFileCache = new SoftReference>(null); + } + private final Logger logger = Logger.getLogger(getClass().getName()); private final JarFile jarFile; @@ -153,7 +161,14 @@ public class Handler extends URLStreamHandler { throw new IllegalStateException("Not a file URL"); } String path = name.substring(FILE_PROTOCOL.length()); - return new JarFile(new File(path)); + File file = new File(path); + Map cache = rootFileCache.get(); + JarFile jarFile = (cache == null ? null : cache.get(file)); + if (jarFile == null) { + jarFile = new JarFile(file); + addToRootFileCache(file, jarFile); + } + return jarFile; } catch (Exception ex) { throw new IOException("Unable to open root Jar file '" + name + "'", ex); @@ -168,4 +183,19 @@ public class Handler extends URLStreamHandler { } return jarFile.getNestedJarFile(jarEntry); } + + /** + * Add the given {@link JarFile} to the root file cache. + * @param sourceFile the source file to add + * @param jarFile the jar file. + */ + static void addToRootFileCache(File sourceFile, JarFile jarFile) { + Map cache = rootFileCache.get(); + if (cache == null) { + cache = new ConcurrentHashMap(); + rootFileCache = new SoftReference>(cache); + } + cache.put(sourceFile, jarFile); + } + } diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarEntryData.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarEntryData.java index cce9f96d7a..1a336d93eb 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarEntryData.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarEntryData.java @@ -53,6 +53,8 @@ public final class JarEntryData { private SoftReference entry; + JarFile nestedJar; + public JarEntryData(JarFile source, byte[] header, InputStream inputStream) throws IOException { this.source = source; diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java index e1d917a30f..e52bc6c0f9 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java @@ -322,13 +322,13 @@ public class JarFile extends java.util.jar.JarFile implements Iterable