From 9df17fd446c8e9043734f21d2c7ada301a5b3358 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 20 Mar 2013 14:39:20 +0000 Subject: [PATCH] 8010282: sun.net.www.protocol.jar.JarFileFactory.close(JarFile) should be thread-safe Reviewed-by: khazra, alanb --- .../www/protocol/jar/JarURLConnection.java | 2 +- .../net/www/protocol/jar/JarFileFactory.java | 32 +++++++++++++------ .../net/www/protocol/jar/JarFileFactory.java | 31 ++++++++++++------ 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java index 7ea642764b3..4c5dc87bdea 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java @@ -51,7 +51,7 @@ public class JarURLConnection extends java.net.JarURLConnection { /* the Jar file factory. It handles both retrieval and caching. */ - private static JarFileFactory factory = new JarFileFactory(); + private static final JarFileFactory factory = JarFileFactory.getInstance(); /* the url for the Jar file */ private URL jarFileURL; diff --git a/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java index 2a001a7f381..ae86964155c 100644 --- a/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -43,13 +43,24 @@ import sun.net.util.URLUtil; class JarFileFactory implements URLJarFile.URLJarFileCloseController { /* the url to file cache */ - private static HashMap fileCache = new HashMap(); + private static final HashMap fileCache = new HashMap<>(); /* the file to url cache */ - private static HashMap urlCache = new HashMap(); + private static final HashMap urlCache = new HashMap<>(); + + private static final JarFileFactory instance = new JarFileFactory(); + + private JarFileFactory() { } + + public static JarFileFactory getInstance() { + return instance; + } URLConnection getConnection(JarFile jarFile) throws IOException { - URL u = urlCache.get(jarFile); + URL u; + synchronized (instance) { + u = urlCache.get(jarFile); + } if (u != null) return u.openConnection(); @@ -62,16 +73,16 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { JarFile get(URL url, boolean useCaches) throws IOException { - JarFile result = null; - JarFile local_result = null; + JarFile result; + JarFile local_result; if (useCaches) { - synchronized (this) { + synchronized (instance) { result = getCachedJarFile(url); } if (result == null) { local_result = URLJarFile.getJarFile(url, this); - synchronized (this) { + synchronized (instance) { result = getCachedJarFile(url); if (result == null) { fileCache.put(URLUtil.urlNoFragString(url), local_result); @@ -99,14 +110,15 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { * remove the JarFile from the cache */ public void close(JarFile jarFile) { - URL urlRemoved = urlCache.remove(jarFile); - if( urlRemoved != null) { + synchronized (instance) { + URL urlRemoved = urlCache.remove(jarFile); + if (urlRemoved != null) fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); } } - private JarFile getCachedJarFile(URL url) { + assert Thread.holdsLock(instance); JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); /* if the JAR file is cached, the permission will always be there */ diff --git a/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java index 80bd9d1a66a..3bc98eb45af 100644 --- a/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -43,13 +43,24 @@ import sun.net.util.URLUtil; class JarFileFactory implements URLJarFile.URLJarFileCloseController { /* the url to file cache */ - private static HashMap fileCache = new HashMap(); + private static final HashMap fileCache = new HashMap<>(); /* the file to url cache */ - private static HashMap urlCache = new HashMap(); + private static final HashMap urlCache = new HashMap<>(); + + private static final JarFileFactory instance = new JarFileFactory(); + + private JarFileFactory() { } + + public static JarFileFactory getInstance() { + return instance; + } URLConnection getConnection(JarFile jarFile) throws IOException { - URL u = urlCache.get(jarFile); + URL u; + synchronized (instance) { + u = urlCache.get(jarFile); + } if (u != null) return u.openConnection(); @@ -72,16 +83,16 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { } } - JarFile result = null; - JarFile local_result = null; + JarFile result; + JarFile local_result; if (useCaches) { - synchronized (this) { + synchronized (instance) { result = getCachedJarFile(url); } if (result == null) { local_result = URLJarFile.getJarFile(url, this); - synchronized (this) { + synchronized (instance) { result = getCachedJarFile(url); if (result == null) { fileCache.put(URLUtil.urlNoFragString(url), local_result); @@ -109,13 +120,15 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { * remove the JarFile from the cache */ public void close(JarFile jarFile) { - URL urlRemoved = urlCache.remove(jarFile); - if( urlRemoved != null) { + synchronized (instance) { + URL urlRemoved = urlCache.remove(jarFile); + if (urlRemoved != null) fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); } } private JarFile getCachedJarFile(URL url) { + assert Thread.holdsLock(instance); JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); /* if the JAR file is cached, the permission will always be there */