JDK-8194653 : Deadlock involving FileSystems.getDefault and System.loadLibrary call
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 8
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2018-01-04
  • Updated: 2023-10-02
  • Resolved: 2019-04-16
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 Other
8u212Fixed openjdk8u242Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description
See http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-January/050819.html

Thread A has called FileSystems.getDefault() which is doing <clinit> of DefaultFileSystemHolder, which in turn leads to Runtime.loadLibrary0 which needs to lock the Runtime instance.

Thread B is already doing a loadLibrary and holds the Runtime lock, the loadLibrary code then needs to do FileSystems.getDefault() which has to load and initialize DefaultFileSystemHolder, but that initialization is already in progress so internally the thread does a wait().

So Thread B is waiting for Thread A to finish initialization, but holds the monitor lock that Thread A needs to finish the initialization. Deadlock.

Comments
It doesn't look as if anyone has made a decision on the 9-na question. Indeed discussion on this issue seems to have come to a halt at the end of April. Is anyone looking at providing a patch for openjdk8u and, perhaps, openjdk11u or jdk repo?
06-06-2019

This issue is under discussion here: https://mail.openjdk.java.net/pipermail/core-libs-dev/2019-April/059811.html It's important to understand if this issue is possible with JDK 9 or newer. If not then it should be tagged as "9-na". Also it's unfortunate that this issue is marked as fixed in 8u231 of Oracle JDK. It seems the wrong bug number was used.
23-04-2019

Why is it necessary to fix this in the JVM? A library initialization order issue can and should be fixed at the library level.
23-04-2019

Verified on Ubuntu 18.04 that the reproducer test in the attached patch of 2018-11-29 fails without applying the hotspot changes in the patch and passes with applying the hotspot changes in the patch. The reproducer test also succeeds on Java 11 and 13-dev.
18-03-2019

We have had reports of this bug affecting Apache Tomcat users: https://bz.apache.org/bugzilla/show_bug.cgi?id=63251 We have added pre-loading as a work-around until this bug is fixed.
15-03-2019

From Ryan: For jdk10u/jdk11u/jdk the pattern is roughly the same. Whether it’s a bare class being loaded directly or a module, the call paths will basically end up at sun.nio.fs.DefaultFileSystemProvider which then leads to the referencing of the correct classes (which load “nio”). Bare classes in jdk/jdk (jdk10u and jdk11u are effectively the same) look like this: java.base/sun.nio.fs.UnixNativeDispatcher.<clinit>(UnixNativeDispatcher.java:610) java.base/sun.nio.fs.UnixFileSystem.<init>(UnixFileSystem.java:65) java.base/sun.nio.fs.LinuxFileSystem.<init>(LinuxFileSystem.java:39) java.base/sun.nio.fs.LinuxFileSystemProvider.newFileSystem(LinuxFileSystemProvider.java:46) java.base/sun.nio.fs.LinuxFileSystemProvider.newFileSystem(LinuxFileSystemProvider.java:39) java.base/sun.nio.fs.UnixFileSystemProvider.<init>(UnixFileSystemProvider.java:56) java.base/sun.nio.fs.LinuxFileSystemProvider.<init>(LinuxFileSystemProvider.java:41) java.base/sun.nio.fs.DefaultFileSystemProvider.<clinit>(DefaultFileSystemProvider.java:35) java.base/java.io.FilePermission.<clinit>(FilePermission.java:205) java.base/sun.net.www.protocol.file.FileURLConnection.getPermission(FileURLConnection.java:221) java.base/jdk.internal.loader.BuiltinClassLoader.getPermissions(BuiltinClassLoader.java:963) java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.getPermissions(ClassLoaders.java:183) java.base/java.security.SecureClassLoader$1.apply(SecureClassLoader.java:227) java.base/java.security.SecureClassLoader$1.apply(SecureClassLoader.java:223) java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705) java.base/java.security.SecureClassLoader.getProtectionDomain(SecureClassLoader.java:223) java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151) java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802) java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700) java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623) java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) java.base/java.lang.Class.forName0(Native Method) java.base/java.lang.Class.forName(Class.java:415) java.base/sun.launcher.LauncherHelper.loadMainClass(LauncherHelper.java:760) java.base/sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:655) And modules eventually hit the same path: java.base/sun.nio.fs.UnixNativeDispatcher.<clinit>(UnixNativeDispatcher.java:610) java.base/sun.nio.fs.UnixFileSystem.<init>(UnixFileSystem.java:65) java.base/sun.nio.fs.LinuxFileSystem.<init>(LinuxFileSystem.java:39) java.base/sun.nio.fs.LinuxFileSystemProvider.newFileSystem(LinuxFileSystemProvider.java:46) java.base/sun.nio.fs.LinuxFileSystemProvider.newFileSystem(LinuxFileSystemProvider.java:39) java.base/sun.nio.fs.UnixFileSystemProvider.<init>(UnixFileSystemProvider.java:56) java.base/sun.nio.fs.LinuxFileSystemProvider.<init>(LinuxFileSystemProvider.java:41) java.base/sun.nio.fs.DefaultFileSystemProvider.<clinit>(DefaultFileSystemProvider.java:35) java.base/java.nio.file.FileSystems.getDefault(FileSystems.java:185) java.base/java.nio.file.Path.of(Path.java:147) java.base/jdk.internal.module.ModuleBootstrap.finderFor(ModuleBootstrap.java:576) java.base/jdk.internal.module.ModuleBootstrap.boot(ModuleBootstrap.java:148) java.base/java.lang.System.initPhase2(System.java:2064) Again, the “fix” here is really a preload (which is extremely likely to happen anyways) to avoid the problem.
09-01-2019

Yes, this is a general issue but I'd like to understand this one a bit more with jdk/jdk. The comment from Ryan looks correct for JDK 9 but the startup changed in JDK 10 so there is no usage of the new file system API during startup (ignoring exploded builds as that is different again). There are further changes in jdk/jdk for JDK 12 that also change how the default file system provider is initialized.
06-12-2018

From Ryan: For both jdk9 and jdk tip, it's not an issue because java.nio.file.FileSystems::getDefault() ends up being called as part of the general startup process. In jdk9, the path is triggered during JVM startup through java.lang.module.ModuleFinder::privilegedOfSystem(), which in turn uses java.nio.file.Paths::get(), and finally FileSystems::getDefault() is called. In jdk/jdk, java.nio.file.FileSystems path is triggered through jdk.internal.module.SystemModuleFinders::ofSystem(), which in turn uses java.nio.file.Path::get(), and finally FileSystems::getDefault() is called. Note that this is really part of a general race problem between class initialization and classes loading native libraries under a global lock.
05-12-2018

I think we need to establish if this is an issue in jdk/jdk or not as the change is changed significantly from both JDK 8 and JDK 9.
29-11-2018

I've attached a patch by Ryan Sciampacone (sci@amazon.com).
29-11-2018

I think it might be better handled by someone familiar with the initialization phase.
11-01-2018

Brian, should this be yours? Not sure who the right owner is.
11-01-2018

The file system is loaded early in JDK 9 so I don't think this deadlock can occur. JDK 10 is different again but the first use of FilePermission or JarFile will likely trigger the loading of the default file system provider before other code executes.
05-01-2018

default = builtin except in the corner case that the system property java.nio.file.spi.DefaultFileSystemProvider is set to use an alternative implementation (which I don't think this is the case in the bug report).
05-01-2018

Are both filesystems initialized early? public static FileSystem getDefault() { if (jdk.internal.misc.VM.isBooted()) { return DefaultFileSystemHolder.defaultFileSystem; } else { return BuiltinFileSystemHolder.builtinFileSystem; } }
05-01-2018