8010282: sun.net.www.protocol.jar.JarFileFactory.close(JarFile) should be thread-safe
authorchegar
Wed, 20 Mar 2013 14:39:20 +0000
changeset 16491 272ad530ce3a
parent 16490 43315ae7fa96
child 16494 a686fd3546f7
8010282: sun.net.www.protocol.jar.JarFileFactory.close(JarFile) should be thread-safe Reviewed-by: khazra, alanb
jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java
jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java
jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java
--- 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 */