8010282: sun.net.www.protocol.jar.JarFileFactory.close(JarFile) should be thread-safe
Reviewed-by: khazra, alanb
--- a/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java Wed Mar 20 13:21:53 2013 +0400
+++ b/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java Wed Mar 20 14:39:20 2013 +0000
@@ -51,7 +51,7 @@
/* 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;
--- a/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java Wed Mar 20 13:21:53 2013 +0400
+++ b/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java Wed Mar 20 14:39:20 2013 +0000
@@ -43,13 +43,24 @@
class JarFileFactory implements URLJarFile.URLJarFileCloseController {
/* the url to file cache */
- private static HashMap<String, JarFile> fileCache = new HashMap<String, JarFile>();
+ private static final HashMap<String, JarFile> fileCache = new HashMap<>();
/* the file to url cache */
- private static HashMap<JarFile, URL> urlCache = new HashMap<JarFile, URL>();
+ private static final HashMap<JarFile, URL> 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 @@
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 @@
* 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 */
--- a/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java Wed Mar 20 13:21:53 2013 +0400
+++ b/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java Wed Mar 20 14:39:20 2013 +0000
@@ -43,13 +43,24 @@
class JarFileFactory implements URLJarFile.URLJarFileCloseController {
/* the url to file cache */
- private static HashMap<String, JarFile> fileCache = new HashMap<String, JarFile>();
+ private static final HashMap<String, JarFile> fileCache = new HashMap<>();
/* the file to url cache */
- private static HashMap<JarFile, URL> urlCache = new HashMap<JarFile, URL>();
+ private static final HashMap<JarFile, URL> 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 @@
}
}
- 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 @@
* 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 */