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
--- 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();
+ }
}