Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8265065

Deadlock between JarFileFactory and ExtendedCharsets

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      OS: Red Hat Enterprise Linux
      System Locale: ja_JP.eucjp
      Java Runtime: Java SE 8 Update 281

      A DESCRIPTION OF THE PROBLEM :
      When the openStream() method of an URL representing a resource in a jar file (such as jar:file:///example.jar!/com/example/Example.class) and the Charset.availableCharsets() method are called at the same time, a deadlock happens between sun.net.www.protocol.jar.JarFileFactory and sun.nio.cs.ext.ExtendedCharsets.

      Maybe this bug is a duplicate of JDK-8143609, but JDK-8143609 is closed with Incomplete.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      (Use the source code for an executable test case)
      $ javac DeadlockSample.java
      $ for i in $(seq 1000); do LANG=ja_JP.eucjp java DeadlockSample; done


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      All commands are complete and nothing to print.
      ACTUAL -
      A command is not complete and print "!!!!! found deadlock !!!!!"

      $ for i in $(seq 1000); do LANG=ja_JP.eucjp java DeadlockSample; done
      !!!!! found deadlock !!!!!
      ^Z (Ctrl+Z)
      [1]+ Stopped LANG=ja_JP.eucjp java DeadlockSample
      $ bg
      [1]+ LANG=ja_JP.eucjp java DeadlockSample &
      $ jps
      73652 Jps
      73638 DeadlockSample
      $ jstack 73638
      2021-04-12 10:52:16
      Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.281-b09 mixed mode):

      "Attach Listener" #10 daemon prio=9 os_prio=0 tid=0x00007fe6fc001000 nid=0x11fcd waiting on condition [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

      "Thread-openJarURLConnectionStream" #9 prio=5 os_prio=0 tid=0x00007fe7300fd800 nid=0x11fb3 waiting for monitor entry [0x00007fe7175ff000]
         java.lang.Thread.State: BLOCKED (on object monitor)
      at sun.nio.cs.AbstractCharsetProvider.charsetForName(AbstractCharsetProvider.java:160)
      - waiting to lock <0x00000000eb816a98> (a sun.nio.cs.ext.ExtendedCharsets)
      at java.nio.charset.Charset.lookupExtendedCharset(Charset.java:452)
      at java.nio.charset.Charset.lookup2(Charset.java:476)
      at java.nio.charset.Charset.lookup(Charset.java:464)
      at java.nio.charset.Charset.isSupported(Charset.java:505)
      at java.lang.StringCoding.lookupCharset(StringCoding.java:99)
      at java.lang.StringCoding.encode(StringCoding.java:336)
      at java.lang.String.getBytes(String.java:918)
      at java.io.UnixFileSystem.canonicalize0(Native Method)
      at java.io.UnixFileSystem.canonicalize(UnixFileSystem.java:172)
      at java.io.File.getCanonicalPath(File.java:618)
      at java.io.FilePermission$1.run(FilePermission.java:224)
      at java.io.FilePermission$1.run(FilePermission.java:212)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.io.FilePermission.init(FilePermission.java:212)
      at java.io.FilePermission.<init>(FilePermission.java:299)
      at sun.net.www.protocol.file.FileURLConnection.getPermission(FileURLConnection.java:225)
      at sun.net.www.protocol.jar.JarFileFactory.getPermission(JarFileFactory.java:225)
      at sun.net.www.protocol.jar.JarFileFactory.getCachedJarFile(JarFileFactory.java:195)
      at sun.net.www.protocol.jar.JarFileFactory.getOrCreate(JarFileFactory.java:103)
      - locked <0x00000000eb8a9390> (a sun.net.www.protocol.jar.JarFileFactory)
      at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:129)
      at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:172)
      at java.net.URL.openStream(URL.java:1067)
      at DeadlockSample.openJarURLConnectionStream(DeadlockSample.java:55)
      at DeadlockSample.access$100(DeadlockSample.java:6)
      at DeadlockSample$2.run(DeadlockSample.java:25)
      at java.lang.Thread.run(Thread.java:748)

      "Thread-availableCharsets" #8 prio=5 os_prio=0 tid=0x00007fe7300fc000 nid=0x11fb2 waiting for monitor entry [0x00007fe717700000]
         java.lang.Thread.State: BLOCKED (on object monitor)
      at sun.net.www.protocol.jar.JarFileFactory.getOrCreate(JarFileFactory.java:103)
      - waiting to lock <0x00000000eb8a9390> (a sun.net.www.protocol.jar.JarFileFactory)
      at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:129)
      at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:172)
      at java.net.URL.openStream(URL.java:1067)
      at java.lang.ClassLoader.getSystemResourceAsStream(ClassLoader.java:1324)
      at java.lang.Class.getResourceAsStream(Class.java:2221)
      at sun.nio.cs.ext.SJIS_0213$1.run(SJIS_0213.java:81)
      at sun.nio.cs.ext.SJIS_0213$1.run(SJIS_0213.java:79)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.nio.cs.ext.SJIS_0213.<clinit>(SJIS_0213.java:78)
      at java.lang.Class.forName0(Native Method)
      at java.lang.Class.forName(Class.java:348)
      at sun.nio.cs.AbstractCharsetProvider.lookup(AbstractCharsetProvider.java:142)
      at sun.nio.cs.AbstractCharsetProvider.access$000(AbstractCharsetProvider.java:45)
      at sun.nio.cs.AbstractCharsetProvider$1.next(AbstractCharsetProvider.java:183)
      - locked <0x00000000eb816a98> (a sun.nio.cs.ext.ExtendedCharsets)
      at sun.nio.cs.AbstractCharsetProvider$1.next(AbstractCharsetProvider.java:173)
      at java.nio.charset.Charset.put(Charset.java:539)
      at java.nio.charset.Charset.access$200(Charset.java:271)
      at java.nio.charset.Charset$3.run(Charset.java:581)
      at java.nio.charset.Charset$3.run(Charset.java:573)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.nio.charset.Charset.availableCharsets(Charset.java:572)
      at DeadlockSample.availableCharsets(DeadlockSample.java:47)
      at DeadlockSample.access$000(DeadlockSample.java:6)
      at DeadlockSample$1.run(DeadlockSample.java:19)
      at java.lang.Thread.run(Thread.java:748)

      "Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007fe7300df800 nid=0x11fb0 runnable [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

      "C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007fe7300da800 nid=0x11faf waiting on condition [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

      "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007fe7300d8000 nid=0x11fae waiting on condition [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

      "Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007fe7300cc800 nid=0x11fad runnable [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

      "Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007fe730082800 nid=0x11fac in Object.wait() [0x00007fe717dfc000]
         java.lang.Thread.State: WAITING (on object monitor)
      at java.lang.Object.wait(Native Method)
      - waiting on <0x00000000eb808ee0> (a java.lang.ref.ReferenceQueue$Lock)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
      - locked <0x00000000eb808ee0> (a java.lang.ref.ReferenceQueue$Lock)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
      at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

      "Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007fe73007e000 nid=0x11fab in Object.wait() [0x00007fe717efd000]
         java.lang.Thread.State: WAITING (on object monitor)
      at java.lang.Object.wait(Native Method)
      - waiting on <0x00000000eb806c00> (a java.lang.ref.Reference$Lock)
      at java.lang.Object.wait(Object.java:502)
      at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
      - locked <0x00000000eb806c00> (a java.lang.ref.Reference$Lock)
      at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

      "main" #1 prio=5 os_prio=0 tid=0x00007fe73000a800 nid=0x11fa7 in Object.wait() [0x00007fe7360ac000]
         java.lang.Thread.State: WAITING (on object monitor)
      at java.lang.Object.wait(Native Method)
      - waiting on <0x00000000eb8fcb18> (a java.lang.Thread)
      at java.lang.Thread.join(Thread.java:1252)
      - locked <0x00000000eb8fcb18> (a java.lang.Thread)
      at java.lang.Thread.join(Thread.java:1326)
      at DeadlockSample.main(DeadlockSample.java:40)

      "VM Thread" os_prio=0 tid=0x00007fe730074000 nid=0x11faa runnable

      "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007fe73001f800 nid=0x11fa8 runnable

      "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007fe730021800 nid=0x11fa9 runnable

      "VM Periodic Task Thread" os_prio=0 tid=0x00007fe7300e2000 nid=0x11fb1 waiting on condition

      JNI global references: 5


      Found one Java-level deadlock:
      =============================
      "Thread-openJarURLConnectionStream":
        waiting to lock monitor 0x00007fe704006568 (object 0x00000000eb816a98, a sun.nio.cs.ext.ExtendedCharsets),
        which is held by "Thread-availableCharsets"
      "Thread-availableCharsets":
        waiting to lock monitor 0x00007fe6f00d8ba8 (object 0x00000000eb8a9390, a sun.net.www.protocol.jar.JarFileFactory),
        which is held by "Thread-openJarURLConnectionStream"

      Java stack information for the threads listed above:
      ===================================================
      "Thread-openJarURLConnectionStream":
      at sun.nio.cs.AbstractCharsetProvider.charsetForName(AbstractCharsetProvider.java:160)
      - waiting to lock <0x00000000eb816a98> (a sun.nio.cs.ext.ExtendedCharsets)
      at java.nio.charset.Charset.lookupExtendedCharset(Charset.java:452)
      at java.nio.charset.Charset.lookup2(Charset.java:476)
      at java.nio.charset.Charset.lookup(Charset.java:464)
      at java.nio.charset.Charset.isSupported(Charset.java:505)
      at java.lang.StringCoding.lookupCharset(StringCoding.java:99)
      at java.lang.StringCoding.encode(StringCoding.java:336)
      at java.lang.String.getBytes(String.java:918)
      at java.io.UnixFileSystem.canonicalize0(Native Method)
      at java.io.UnixFileSystem.canonicalize(UnixFileSystem.java:172)
      at java.io.File.getCanonicalPath(File.java:618)
      at java.io.FilePermission$1.run(FilePermission.java:224)
      at java.io.FilePermission$1.run(FilePermission.java:212)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.io.FilePermission.init(FilePermission.java:212)
      at java.io.FilePermission.<init>(FilePermission.java:299)
      at sun.net.www.protocol.file.FileURLConnection.getPermission(FileURLConnection.java:225)
      at sun.net.www.protocol.jar.JarFileFactory.getPermission(JarFileFactory.java:225)
      at sun.net.www.protocol.jar.JarFileFactory.getCachedJarFile(JarFileFactory.java:195)
      at sun.net.www.protocol.jar.JarFileFactory.getOrCreate(JarFileFactory.java:103)
      - locked <0x00000000eb8a9390> (a sun.net.www.protocol.jar.JarFileFactory)
      at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:129)
      at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:172)
      at java.net.URL.openStream(URL.java:1067)
      at DeadlockSample.openJarURLConnectionStream(DeadlockSample.java:55)
      at DeadlockSample.access$100(DeadlockSample.java:6)
      at DeadlockSample$2.run(DeadlockSample.java:25)
      at java.lang.Thread.run(Thread.java:748)
      "Thread-availableCharsets":
      at sun.net.www.protocol.jar.JarFileFactory.getOrCreate(JarFileFactory.java:103)
      - waiting to lock <0x00000000eb8a9390> (a sun.net.www.protocol.jar.JarFileFactory)
      at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:129)
      at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:172)
      at java.net.URL.openStream(URL.java:1067)
      at java.lang.ClassLoader.getSystemResourceAsStream(ClassLoader.java:1324)
      at java.lang.Class.getResourceAsStream(Class.java:2221)
      at sun.nio.cs.ext.SJIS_0213$1.run(SJIS_0213.java:81)
      at sun.nio.cs.ext.SJIS_0213$1.run(SJIS_0213.java:79)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.nio.cs.ext.SJIS_0213.<clinit>(SJIS_0213.java:78)
      at java.lang.Class.forName0(Native Method)
      at java.lang.Class.forName(Class.java:348)
      at sun.nio.cs.AbstractCharsetProvider.lookup(AbstractCharsetProvider.java:142)
      at sun.nio.cs.AbstractCharsetProvider.access$000(AbstractCharsetProvider.java:45)
      at sun.nio.cs.AbstractCharsetProvider$1.next(AbstractCharsetProvider.java:183)
      - locked <0x00000000eb816a98> (a sun.nio.cs.ext.ExtendedCharsets)
      at sun.nio.cs.AbstractCharsetProvider$1.next(AbstractCharsetProvider.java:173)
      at java.nio.charset.Charset.put(Charset.java:539)
      at java.nio.charset.Charset.access$200(Charset.java:271)
      at java.nio.charset.Charset$3.run(Charset.java:581)
      at java.nio.charset.Charset$3.run(Charset.java:573)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.nio.charset.Charset.availableCharsets(Charset.java:572)
      at DeadlockSample.availableCharsets(DeadlockSample.java:47)
      at DeadlockSample.access$000(DeadlockSample.java:6)
      at DeadlockSample$1.run(DeadlockSample.java:19)
      at java.lang.Thread.run(Thread.java:748)

      Found 1 deadlock.


      ---------- BEGIN SOURCE ----------
      import java.io.File;
      import java.lang.management.ManagementFactory;
      import java.net.URL;
      import java.nio.charset.Charset;

      public class DeadlockSample {
          public static void main(String[] args) throws Exception {
              File jarFile = new File(System.getProperty("java.home") + File.separator + "lib" + File.separator + "jsse.jar");
              String resourceInJarFile = "sun/security/provider/Sun.class";

              final URL url = new URL("jar:" + jarFile.toURI().toURL() + "!/" + resourceInJarFile);
              //System.out.println(url);

              // put entry in JarFileFactory.fileCache
              url.openStream().close();

              Thread t1 = new Thread(new Runnable() {
                  public void run() {
                      availableCharsets();
                  }
              }, "Thread-availableCharsets");

              Thread t2 = new Thread(new Runnable() {
                  public void run() {
                      openJarURLConnectionStream(url);
                  }
              }, "Thread-openJarURLConnectionStream");

              t1.start();
              t2.start();

              t1.join(2000L);
              t2.join(2000L);

              if (t1.isAlive() && t2.isAlive()) {
                  long[] deadlockedThreads = ManagementFactory.getThreadMXBean().findDeadlockedThreads();
                  if (deadlockedThreads != null && deadlockedThreads.length > 0) {
                      System.err.println("!!!!! found deadlock !!!!!");
                  }
                  t1.join();
                  t2.join();
              }
          }

          private static void availableCharsets() {
              try {
                  Charset.availableCharsets();
              } catch (Exception ex) {
                  ex.printStackTrace();
              }
          }

          private static void openJarURLConnectionStream(URL url) {
              try {
                 url.openStream();
              } catch (Exception ex) {
                  ex.printStackTrace();
              }
          }
      }

      ---------- END SOURCE ----------

      FREQUENCY : occasionally


        1. Foo.jar
          0.8 kB
        2. deadlocktest.policy
          0.1 kB
        3. DeadlockSampleModified.java
          2 kB
        4. DeadlockSample.java
          2 kB

            coffeys Sean Coffey
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            9 Start watching this issue

              Created:
              Updated:
              Resolved: