changeset 6619:6126a0662727

8012326: Deadlock occurs when Charset.availableCharsets() is called by several threads at the same time Summary: removed the race condition risk from ExtendedCharset access code Reviewed-by: sherman
author coffeys
date Wed, 16 Oct 2013 05:49:30 +0100
parents cfd96c6d47c6
children c421ade4c566
files make/sun/nio/cs/Makefile src/share/classes/java/nio/charset/Charset.java src/share/classes/sun/nio/cs/ext/META-INF/services/java.nio.charset.spi.CharsetProvider
diffstat 3 files changed, 27 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/make/sun/nio/cs/Makefile	Tue Oct 15 12:55:39 2013 -0700
+++ b/make/sun/nio/cs/Makefile	Wed Oct 16 05:49:30 2013 +0100
@@ -85,9 +85,6 @@
 #
 # Extra rules to build character converters.
 
-SERVICE_DESCRIPTION = java.nio.charset.spi.CharsetProvider
-SERVICE_DESCRIPTION_PATH = META-INF/services/$(SERVICE_DESCRIPTION)
-
 GENCSDATASRC = $(BUILDDIR)/tools/CharsetMapping
 GENCSSRCDIR = $(BUILDDIR)/tools/src/build/tools/charsetmapping
 GENCSEXT = $(GENSRCDIR)/sun/nio/cs/ext
@@ -116,10 +113,6 @@
 		$(GENCSSRCDIR)/HKSCS.java
 	$(BOOT_JAVA_CMD) -jar $(CHARSETMAPPING_JARFILE) $(GENCSDATASRC) $(GENCSEXT) dbcs
 
-$(CLASSDESTDIR)/$(SERVICE_DESCRIPTION_PATH): \
-  $(SHARE_SRC)/classes/sun/nio/cs/ext/$(SERVICE_DESCRIPTION_PATH)
-	$(install-file)
-
 # no compression unless requested
 ifndef COMPRESS_JARS
   CREATE_JAR_OPTS_NOMANIFEST = cf0
@@ -127,10 +120,9 @@
   CREATE_JAR_OPTS_NOMANIFEST = cf
 endif
 
-$(CHARSETS_JAR): $(FILES_class) $(CLASSDESTDIR)/$(SERVICE_DESCRIPTION_PATH) $(FILES_DAT)
+$(CHARSETS_JAR): $(FILES_class) $(FILES_DAT)
 	$(BOOT_JAR_CMD) $(CREATE_JAR_OPTS_NOMANIFEST) $(CHARSETS_JAR) \
 	      -C $(CLASSDESTDIR) sun \
-	      -C $(CLASSDESTDIR) $(SERVICE_DESCRIPTION_PATH)  \
 	      $(BOOT_JAR_JFLAGS)
 	@$(java-vm-cleanup)
 
--- a/src/share/classes/java/nio/charset/Charset.java	Tue Oct 15 12:55:39 2013 -0700
+++ b/src/share/classes/java/nio/charset/Charset.java	Wed Oct 16 05:49:30 2013 +0100
@@ -426,39 +426,32 @@
     }
 
     /* The extended set of charsets */
-    private static Object extendedProviderLock = new Object();
-    private static boolean extendedProviderProbed = false;
-    private static CharsetProvider extendedProvider = null;
-
-    private static void probeExtendedProvider() {
-        AccessController.doPrivileged(new PrivilegedAction<Object>() {
-                public Object run() {
-                    try {
-                        Class epc
-                            = Class.forName("sun.nio.cs.ext.ExtendedCharsets");
-                        extendedProvider = (CharsetProvider)epc.newInstance();
-                    } catch (ClassNotFoundException x) {
-                        // Extended charsets not available
-                        // (charsets.jar not present)
-                    } catch (InstantiationException x) {
-                        throw new Error(x);
-                    } catch (IllegalAccessException x) {
-                        throw new Error(x);
-                    }
-                    return null;
-                }
-            });
+    private static class ExtendedProviderHolder {
+        static final CharsetProvider extendedProvider = extendedProvider();
+        // returns ExtendedProvider, if installed
+        private static CharsetProvider extendedProvider() {
+            return AccessController.doPrivileged(
+                       new PrivilegedAction<CharsetProvider>() {
+                           public CharsetProvider run() {
+                                try {
+                                    Class<?> epc
+                                        = Class.forName("sun.nio.cs.ext.ExtendedCharsets");
+                                    return (CharsetProvider)epc.newInstance();
+                                } catch (ClassNotFoundException x) {
+                                    // Extended charsets not available
+                                    // (charsets.jar not present)
+                                } catch (InstantiationException |
+                                         IllegalAccessException x) {
+                                  throw new Error(x);
+                                }
+                                return null;
+                            }
+                        });
+        }
     }
 
     private static Charset lookupExtendedCharset(String charsetName) {
-        CharsetProvider ecp = null;
-        synchronized (extendedProviderLock) {
-            if (!extendedProviderProbed) {
-                probeExtendedProvider();
-                extendedProviderProbed = true;
-            }
-            ecp = extendedProvider;
-        }
+        CharsetProvider ecp = ExtendedProviderHolder.extendedProvider;
         return (ecp != null) ? ecp.charsetForName(charsetName) : null;
     }
 
@@ -588,6 +581,9 @@
                         new TreeMap<String,Charset>(
                             ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
                     put(standardProvider.charsets(), m);
+                    CharsetProvider ecp = ExtendedProviderHolder.extendedProvider;
+                    if (ecp != null)
+                        put(ecp.charsets(), m);
                     for (Iterator i = providers(); i.hasNext();) {
                         CharsetProvider cp = (CharsetProvider)i.next();
                         put(cp.charsets(), m);
--- a/src/share/classes/sun/nio/cs/ext/META-INF/services/java.nio.charset.spi.CharsetProvider	Tue Oct 15 12:55:39 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-# NIO charset SPI extended charset provider
-sun.nio.cs.ext.ExtendedCharsets