From 7dbf20abe99eb6c1d9c137e592c2025af725fa06 Mon Sep 17 00:00:00 2001 From: Alex Light Date: Wed, 8 Jun 2016 23:12:45 +0000 Subject: [PATCH] Revert "Revert "Revert "Revert "Revert some flaky unloading"""" Fugu is still unhappy Bug: 28406866 This reverts commit 340f486aa0126facb67494449b5c2ee46a1a75e6. Change-Id: I45fc77f924d991669d27b99c1458b2def8692664 --- runtime/common_runtime_test.cc | 20 ++++++++++++++ runtime/java_vm_ext.cc | 31 ++++++++++------------ .../136-daemon-jni-shutdown/daemon_jni_shutdown.cc | 14 ---------- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index 5bdb36caf..f58af5a8d 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -418,6 +418,26 @@ void CommonRuntimeTestImpl::TearDown() { (*icu_cleanup_fn)(); Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test + + // Manually closing the JNI libraries. + // Runtime does not support repeatedly doing JNI->CreateVM, thus we need to manually clean up the + // dynamic linking loader so that gtests would not fail. + // Bug: 25785594 + if (runtime_->IsStarted()) { + { + // We retrieve the handle by calling dlopen on the library. To close it, we need to call + // dlclose twice, the first time to undo our dlopen and the second time to actually unload it. + // See man dlopen. + void* handle = dlopen("libjavacore.so", RTLD_LAZY); + dlclose(handle); + CHECK_EQ(0, dlclose(handle)); + } + { + void* handle = dlopen("libopenjdkd.so", RTLD_LAZY); + dlclose(handle); + CHECK_EQ(0, dlclose(handle)); + } + } } static std::string GetDexFileName(const std::string& jar_prefix, bool host) { diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index c2164126e..d983a9fa1 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -74,10 +74,6 @@ class SharedLibrary { if (self != nullptr) { self->GetJniEnv()->DeleteWeakGlobalRef(class_loader_); } - - if (!needs_native_bridge_) { - android::CloseNativeLibrary(handle_); - } } jweak GetClassLoader() const { @@ -275,7 +271,8 @@ class Libraries { REQUIRES(!Locks::jni_libraries_lock_) SHARED_REQUIRES(Locks::mutator_lock_) { ScopedObjectAccessUnchecked soa(Thread::Current()); - std::vector unload_libraries; + typedef void (*JNI_OnUnloadFn)(JavaVM*, void*); + std::vector unload_functions; { MutexLock mu(soa.Self(), *Locks::jni_libraries_lock_); for (auto it = libraries_.begin(); it != libraries_.end(); ) { @@ -286,7 +283,15 @@ class Libraries { // the native libraries of the boot class loader. if (class_loader != nullptr && soa.Self()->IsJWeakCleared(class_loader)) { - unload_libraries.push_back(library); + void* const sym = library->FindSymbol("JNI_OnUnload", nullptr); + if (sym == nullptr) { + VLOG(jni) << "[No JNI_OnUnload found in \"" << library->GetPath() << "\"]"; + } else { + VLOG(jni) << "[JNI_OnUnload found for \"" << library->GetPath() << "\"]"; + JNI_OnUnloadFn jni_on_unload = reinterpret_cast(sym); + unload_functions.push_back(jni_on_unload); + } + delete library; it = libraries_.erase(it); } else { ++it; @@ -294,17 +299,9 @@ class Libraries { } } // Do this without holding the jni libraries lock to prevent possible deadlocks. - typedef void (*JNI_OnUnloadFn)(JavaVM*, void*); - for (auto library : unload_libraries) { - void* const sym = library->FindSymbol("JNI_OnUnload", nullptr); - if (sym == nullptr) { - VLOG(jni) << "[No JNI_OnUnload found in \"" << library->GetPath() << "\"]"; - } else { - VLOG(jni) << "[JNI_OnUnload found for \"" << library->GetPath() << "\"]: Calling..."; - JNI_OnUnloadFn jni_on_unload = reinterpret_cast(sym); - jni_on_unload(soa.Vm(), nullptr); - } - delete library; + for (JNI_OnUnloadFn fn : unload_functions) { + VLOG(jni) << "Calling JNI_OnUnload"; + (*fn)(soa.Vm(), nullptr); } } diff --git a/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc b/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc index b7293015c..c9110a905 100644 --- a/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc +++ b/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc @@ -27,20 +27,8 @@ namespace art { namespace { static volatile std::atomic vm_was_shutdown(false); -static const int kThreadCount = 4; - -static std::atomic barrier_count(kThreadCount + 1); - -static void JniThreadBarrierWait() { - barrier_count--; - while (barrier_count.load() != 0) { - usleep(1000); - } -} extern "C" JNIEXPORT void JNICALL Java_Main_waitAndCallIntoJniEnv(JNIEnv* env, jclass) { - // Wait for all threads to enter JNI together. - JniThreadBarrierWait(); // Wait until the runtime is shutdown. while (!vm_was_shutdown.load()) { usleep(1000); @@ -52,8 +40,6 @@ extern "C" JNIEXPORT void JNICALL Java_Main_waitAndCallIntoJniEnv(JNIEnv* env, j // NO_RETURN does not work with extern "C" for target builds. extern "C" JNIEXPORT void JNICALL Java_Main_destroyJavaVMAndExit(JNIEnv* env, jclass) { - // Wait for all threads to enter JNI together. - JniThreadBarrierWait(); // Fake up the managed stack so we can detach. Thread* const self = Thread::Current(); self->SetTopOfStack(nullptr); -- 2.11.0