mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-10-08 02:09:06 +00:00
Avoid parsing nested jar URLs for cached resource lookups
Construct JarFileUrlKey directly from already-parsed URL specification to avoid unnecessary URL construction and parsing on cache hits. A URL is only created on a cache miss when the JarFile needs to be instantiated. This eliminates redundant object allocation in the hot path when frameworks probe for optional classes or package-info metadata across a large executable JAR. See gh-51827 Signed-off-by: sharanrenukeshbharmshetty <sbharmshetty@gmail.com>
This commit is contained in:
committed by
Phillip Webb
parent
b00a873c00
commit
986ad2da2b
+8
@@ -44,6 +44,14 @@ final class JarFileUrlKey {
|
||||
this.runtimeRef = "runtime".equals(url.getRef());
|
||||
}
|
||||
|
||||
JarFileUrlKey(String protocol, String host, int port, String file, boolean runtimeRef) {
|
||||
this.protocol = protocol;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.file = file;
|
||||
this.runtimeRef = runtimeRef;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
|
||||
+11
-5
@@ -337,13 +337,19 @@ final class JarUrlConnection extends java.net.JarURLConnection {
|
||||
int separator = spec.indexOf("!/");
|
||||
boolean specHasEntry = (separator != -1) && (separator + 2 != spec.length());
|
||||
if (specHasEntry) {
|
||||
URL jarFileUrl = new URL(spec.substring(0, separator));
|
||||
if ("runtime".equals(url.getRef())) {
|
||||
jarFileUrl = new URL(jarFileUrl, "#runtime");
|
||||
String jarFileSpec = spec.substring(0, separator);
|
||||
boolean runtimeRef = "runtime".equals(url.getRef());
|
||||
JarFileUrlKey urlKey = new JarFileUrlKey("jar", "", -1, jarFileSpec, runtimeRef);
|
||||
JarFile jarFile = jarFiles.getCached(urlKey);
|
||||
if (jarFile == null) {
|
||||
URL jarFileUrl = new URL(jarFileSpec);
|
||||
if (runtimeRef) {
|
||||
jarFileUrl = new URL(jarFileUrl, "#runtime");
|
||||
}
|
||||
jarFile = jarFiles.getOrCreate(true, jarFileUrl);
|
||||
jarFiles.cacheIfAbsent(true, jarFileUrl, jarFile);
|
||||
}
|
||||
String entryName = UrlDecoder.decode(spec.substring(separator + 2));
|
||||
JarFile jarFile = jarFiles.getOrCreate(true, jarFileUrl);
|
||||
jarFiles.cacheIfAbsent(true, jarFileUrl, jarFile);
|
||||
if (!hasEntry(jarFile, entryName)) {
|
||||
return notFoundConnection(jarFile.getName(), entryName);
|
||||
}
|
||||
|
||||
+18
-1
@@ -81,6 +81,15 @@ class UrlJarFiles {
|
||||
return this.cache.get(jarFileUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cached {@link JarFile} if available.
|
||||
* @param urlKey the jar file URL key
|
||||
* @return the cached jar or {@code null}
|
||||
*/
|
||||
JarFile getCached(JarFileUrlKey urlKey) {
|
||||
return this.cache.get(urlKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache the given {@link JarFile} if caching can be used and there is no existing
|
||||
* entry.
|
||||
@@ -154,7 +163,15 @@ class UrlJarFiles {
|
||||
* @return the cached {@link JarFile} or {@code null}
|
||||
*/
|
||||
JarFile get(URL jarFileUrl) {
|
||||
JarFileUrlKey urlKey = new JarFileUrlKey(jarFileUrl);
|
||||
return get(new JarFileUrlKey(jarFileUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a {@link JarFile} from the cache given a jar file URL key.
|
||||
* @param urlKey the jar file URL key
|
||||
* @return the cached {@link JarFile} or {@code null}
|
||||
*/
|
||||
JarFile get(JarFileUrlKey urlKey) {
|
||||
synchronized (this) {
|
||||
return this.jarFileUrlToJarFile.get(urlKey);
|
||||
}
|
||||
|
||||
+23
@@ -101,4 +101,27 @@ class JarFileUrlKeyTests {
|
||||
return new JarFileUrlKey(new URL(spec));
|
||||
}
|
||||
|
||||
@Test
|
||||
void directKeyEqualsUrlKey() throws Exception {
|
||||
JarFileUrlKey fromUrl = key("jar:nested:/my.jar/!mynested.jar!/my/path");
|
||||
JarFileUrlKey direct = new JarFileUrlKey("jar", "", -1, "nested:/my.jar/!mynested.jar!/my/path", false);
|
||||
assertThat(direct).isEqualTo(fromUrl);
|
||||
assertThat(direct.hashCode()).isEqualTo(fromUrl.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void directKeyWithRuntimeRefEqualsUrlKey() throws Exception {
|
||||
JarFileUrlKey fromUrl = key("jar:nested:/my.jar/!mynested.jar!/my/path#runtime");
|
||||
JarFileUrlKey direct = new JarFileUrlKey("jar", "", -1, "nested:/my.jar/!mynested.jar!/my/path", true);
|
||||
assertThat(direct).isEqualTo(fromUrl);
|
||||
assertThat(direct.hashCode()).isEqualTo(fromUrl.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void directKeyWithRuntimeRefNotEqualToKeyWithout() {
|
||||
JarFileUrlKey k1 = new JarFileUrlKey("jar", "", -1, "nested:/my.jar/!mynested.jar!/my/path", true);
|
||||
JarFileUrlKey k2 = new JarFileUrlKey("jar", "", -1, "nested:/my.jar/!mynested.jar!/my/path", false);
|
||||
assertThat(k1).isNotEqualTo(k2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user