8264048: Fix caching in Jar URL connections when an entry is missing

Co-authored-by: Daniel Fuchs <dfuchs@openjdk.org>
Reviewed-by: bchristi, dfuchs
This commit is contained in:
Aleksei Efimov 2021-04-06 10:43:59 +00:00
parent bf26a2558f
commit a611c462f9
6 changed files with 371 additions and 27 deletions

View file

@ -71,6 +71,75 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController {
return get(url, true);
}
/**
* Get or create a {@code JarFile} for the given {@code url}.
* If {@code useCaches} is true, this method attempts to find
* a jar file in the cache, and if so, returns it.
* If no jar file is found in the cache, or {@code useCaches}
* is false, the method creates a new jar file.
* If the URL points to a local file, the returned jar file
* will not be put in the cache yet.
* The caller should then call {@link #cacheIfAbsent(URL, JarFile)}
* with the returned jar file, if updating the cache is desired.
* @param url the jar file url
* @param useCaches whether the cache should be used
* @return a new or cached jar file.
* @throws IOException if the jar file couldn't be created
*/
JarFile getOrCreate(URL url, boolean useCaches) throws IOException {
if (useCaches == false) {
return get(url, false);
}
if (!URLJarFile.isFileURL(url)) {
// A temporary file will be created, we can prepopulate
// the cache in this case.
return get(url, useCaches);
}
// We have a local file. Do not prepopulate the cache.
JarFile result;
synchronized (instance) {
result = getCachedJarFile(url);
}
if (result == null) {
result = URLJarFile.getJarFile(url, this);
}
if (result == null)
throw new FileNotFoundException(url.toString());
return result;
}
/**
* Close the given jar file if it isn't present in the cache.
* Otherwise, does nothing.
* @param url the jar file URL
* @param jarFile the jar file to close
* @return true if the jar file has been closed, false otherwise.
* @throws IOException if an error occurs while closing the jar file.
*/
boolean closeIfNotCached(URL url, JarFile jarFile) throws IOException {
JarFile result;
synchronized (instance) {
result = getCachedJarFile(url);
}
if (result != jarFile) jarFile.close();
return result != jarFile;
}
boolean cacheIfAbsent(URL url, JarFile jarFile) {
JarFile cached;
synchronized (instance) {
String key = urlKey(url);
cached = fileCache.get(key);
if (cached == null) {
fileCache.put(key, jarFile);
urlCache.put(jarFile, url);
}
}
return cached == null || cached == jarFile;
}
JarFile get(URL url, boolean useCaches) throws IOException {
JarFile result;
@ -106,7 +175,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController {
/**
* Callback method of the URLJarFileCloseController to
* indicate that the JarFile is close. This way we can
* indicate that the JarFile is closed. This way we can
* remove the JarFile from the cache
*/
public void close(JarFile jarFile) {