src/share/vm/runtime/thread.cpp

Print this page
rev 8963 : 8194653: Deadlock involving FileSystems.getDefault and System.loadLibrary call
Preload classes in the j.n.f.FileSystems.getDefault() path to avoid a potential
deadlock between class loading and native library loading.

@@ -986,13 +986,19 @@
 bool Thread::set_as_starting_thread() {
  // NOTE: this must be called inside the main thread.
   return os::create_main_thread((JavaThread*)this);
 }
 
+// Helper to initialize_class for callers that need the klass result
+static Klass *initialize_class_and_return(Symbol* class_name, TRAPS) {
+  Klass* klass = SystemDictionary::resolve_or_fail(class_name, true, CHECK_NULL);
+  InstanceKlass::cast(klass)->initialize(CHECK_NULL);
+  return klass;
+}
+
 static void initialize_class(Symbol* class_name, TRAPS) {
-  Klass* klass = SystemDictionary::resolve_or_fail(class_name, true, CHECK);
-  InstanceKlass::cast(klass)->initialize(CHECK);
+  (void)initialize_class_and_return(class_name, CHECK);
 }
 
 
 // Creates the initial ThreadGroup
 static Handle create_initial_thread_group(TRAPS) {

@@ -3658,10 +3664,30 @@
     initialize_class(vmSymbols::java_lang_invoke_MethodHandle(), CHECK_0);
     initialize_class(vmSymbols::java_lang_invoke_MemberName(), CHECK_0);
     initialize_class(vmSymbols::java_lang_invoke_MethodHandleNatives(), CHECK_0);
   }
 
+  // See        : bugid 8194653
+  // Background : Deadlock as described by https://bugs.openjdk.java.net/browse/JDK-8194653
+  // Mitigation : Eliminates a race condition on call to
+  //              java.nio.file.FileSystems::getDefault() where two threads (one inside
+  //              a loadLibrary() call) could cause a deadlock if they both referenced this
+  //              code path.  Priming the code path during startup eliminates the deadlock
+  //              (<clinit> and loadLibrary0 are single threaded).
+  //              Note the JVM is at the end of initialization and the getDefault() call
+  //              is safe to make.
+  // Future Fix : OpenJDK 9 beyond address the issue with a different (fixed) startup
+  //              sequence.  For OpenJDK 8 this should be sufficient.
+  {
+    Klass* k = initialize_class_and_return(vmSymbols::java_nio_file_FileSystems(), CHECK_0);
+    instanceKlassHandle klass (THREAD, k);
+    JavaValue result(T_OBJECT);
+
+    JavaCalls::call_static(&result, klass, vmSymbols::getDefault_name(),
+                                           vmSymbols::getDefault_signature(), CHECK_0);
+  }
+
 #if INCLUDE_MANAGEMENT
   Management::initialize(THREAD);
 #endif // INCLUDE_MANAGEMENT
 
   if (HAS_PENDING_EXCEPTION) {