8012326: Deadlock occurs when Charset.availableCharsets() is called by several threads at the same time
authorsherman
Tue, 14 May 2013 14:09:18 -0700
changeset 17470 b65cf2b5983b
parent 17469 e00a02431a8b
child 17471 c2adb7330c84
8012326: Deadlock occurs when Charset.availableCharsets() is called by several threads at the same time Summary: removed the race condition risk from ExtendedCahrset access code Reviewed-by: mchung, alanb
jdk/make/sun/nio/cs/Makefile
jdk/makefiles/CreateJars.gmk
jdk/src/share/classes/java/nio/charset/Charset.java
jdk/src/share/classes/sun/nio/cs/ext/ISO2022_JP_2.java
jdk/src/share/classes/sun/nio/cs/ext/META-INF/services/java.nio.charset.spi.CharsetProvider
jdk/src/share/classes/sun/nio/cs/ext/MSISO2022JP.java
--- a/jdk/make/sun/nio/cs/Makefile	Tue May 14 12:01:38 2013 -0700
+++ b/jdk/make/sun/nio/cs/Makefile	Tue May 14 14:09:18 2013 -0700
@@ -87,9 +87,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
@@ -118,10 +115,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
@@ -129,10 +122,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/jdk/makefiles/CreateJars.gmk	Tue May 14 12:01:38 2013 -0700
+++ b/jdk/makefiles/CreateJars.gmk	Tue May 14 14:09:18 2013 -0700
@@ -201,7 +201,6 @@
 	META-INF/services/com.sun.jdi.connect.spi.TransportService \
 	META-INF/services/com.sun.tools.attach.spi.AttachProvider \
 	META-INF/services/com.sun.tools.xjc.Plugin \
-	META-INF/services/java.nio.charset.spi.CharsetProvider \
 	META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor \
 	org/relaxng/datatype \
 	sun/awt/HKSCS.class \
@@ -428,8 +427,7 @@
 		SUFFIXES:=.class .dat,\
 		INCLUDES:=sun/nio/cs/ext,\
 		EXTRA_FILES := sun/awt/HKSCS.class \
-			       $(CHARSETS_EXTRA_FILES) \
-                               META-INF/services/java.nio.charset.spi.CharsetProvider, \
+			       $(CHARSETS_EXTRA_FILES), \
 		JAR:=$(IMAGES_OUTPUTDIR)/lib/charsets.jar, \
 		SKIP_METAINF := true, \
                 CHECK_COMPRESS_JAR:=true))
--- a/jdk/src/share/classes/java/nio/charset/Charset.java	Tue May 14 12:01:38 2013 -0700
+++ b/jdk/src/share/classes/java/nio/charset/Charset.java	Tue May 14 14:09:18 2013 -0700
@@ -427,46 +427,38 @@
     }
 
     /* 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;
     }
 
     private static Charset lookup(String charsetName) {
         if (charsetName == null)
             throw new IllegalArgumentException("Null charset name");
-
         Object[] a;
         if ((a = cache1) != null && charsetName.equals(a[0]))
             return (Charset)a[1];
@@ -483,7 +475,6 @@
             cache1 = a;
             return (Charset)a[1];
         }
-
         Charset cs;
         if ((cs = standardProvider.charsetForName(charsetName)) != null ||
             (cs = lookupExtendedCharset(charsetName))           != null ||
@@ -589,6 +580,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<CharsetProvider> i = providers(); i.hasNext();) {
                         CharsetProvider cp = i.next();
                         put(cp.charsets(), m);
--- a/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_JP_2.java	Tue May 14 12:01:38 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_JP_2.java	Tue May 14 14:09:18 2013 -0700
@@ -47,17 +47,17 @@
     }
 
     public CharsetDecoder newDecoder() {
-        return new Decoder(this, Decoder.DEC0208, DEC0212);
+        return new Decoder(this, Decoder.DEC0208, CoderHolder.DEC0212);
     }
 
     public CharsetEncoder newEncoder() {
-        return new Encoder(this, Encoder.ENC0208, ENC0212, true);
+        return new Encoder(this, Encoder.ENC0208, CoderHolder.ENC0212, true);
     }
 
-    private final static DoubleByte.Decoder DEC0212 =
-        (DoubleByte.Decoder)new JIS_X_0212().newDecoder();
-
-    private final static DoubleByte.Encoder ENC0212 =
-        (DoubleByte.Encoder)new JIS_X_0212().newEncoder();
-
+    private static class CoderHolder {
+        final static DoubleByte.Decoder DEC0212 =
+            (DoubleByte.Decoder)new JIS_X_0212().newDecoder();
+        final static DoubleByte.Encoder ENC0212 =
+            (DoubleByte.Encoder)new JIS_X_0212().newEncoder();
+    }
 }
--- a/jdk/src/share/classes/sun/nio/cs/ext/META-INF/services/java.nio.charset.spi.CharsetProvider	Tue May 14 12:01:38 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
--- a/jdk/src/share/classes/sun/nio/cs/ext/MSISO2022JP.java	Tue May 14 12:01:38 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/MSISO2022JP.java	Tue May 14 14:09:18 2013 -0700
@@ -46,16 +46,17 @@
     }
 
     public CharsetDecoder newDecoder() {
-        return new Decoder(this, DEC0208, null);
+        return new Decoder(this, CoderHolder.DEC0208, null);
     }
 
     public CharsetEncoder newEncoder() {
-        return new Encoder(this, ENC0208, null, true);
+        return new Encoder(this, CoderHolder.ENC0208, null, true);
     }
 
-    private final static DoubleByte.Decoder DEC0208 =
-        (DoubleByte.Decoder)new JIS_X_0208_MS932().newDecoder();
-
-    private final static DoubleByte.Encoder ENC0208 =
-        (DoubleByte.Encoder)new JIS_X_0208_MS932().newEncoder();
+    private static class CoderHolder {
+        final static DoubleByte.Decoder DEC0208 =
+            (DoubleByte.Decoder)new JIS_X_0208_MS932().newDecoder();
+        final static DoubleByte.Encoder ENC0208 =
+            (DoubleByte.Encoder)new JIS_X_0208_MS932().newEncoder();
+    }
 }