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) {