summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2014-12-10 22:22:14 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2014-12-10 22:22:15 +0000
commit2cd6142727f1d9e5b71e942ea4c56e3c3810f8d0 (patch)
tree053c34eca63eea760c1a6dd2b71bc80aa1e647b5
parent2387a59bf0e5bcc8f3aad8195eb1eea63d00939b (diff)
parentcef50f0487929f72183623bc2a5819cf3a63bff6 (diff)
Merge "Stop daemon threads in runtime shutdown"
-rw-r--r--runtime/base/mutex.cc8
-rw-r--r--runtime/runtime.cc17
-rw-r--r--runtime/well_known_classes.cc2
-rw-r--r--runtime/well_known_classes.h1
4 files changed, 26 insertions, 2 deletions
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index aa2aefc318..da78082f85 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -327,8 +327,12 @@ Mutex::~Mutex() {
LOG(shutting_down ? WARNING : FATAL) << "destroying mutex with owner: " << exclusive_owner_;
} else {
CHECK_EQ(exclusive_owner_, 0U) << "unexpectedly found an owner on unlocked mutex " << name_;
- CHECK_EQ(num_contenders_.LoadSequentiallyConsistent(), 0)
- << "unexpectedly found a contender on mutex " << name_;
+ if (level_ != kMonitorLock) {
+ // Only check the lock level for non monitor locks since we may still have java threads
+ // waiting on monitors.
+ CHECK_EQ(num_contenders_.LoadSequentiallyConsistent(), 0)
+ << "unexpectedly found a contender on mutex " << name_;
+ }
}
#else
// We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 078e7d24e1..32d787aeca 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -190,6 +190,13 @@ Runtime::~Runtime() {
}
Thread* self = Thread::Current();
+ if (self == nullptr) {
+ CHECK(AttachCurrentThread("Shutdown thread", false, nullptr, false));
+ self = Thread::Current();
+ } else {
+ LOG(WARNING) << "Current thread not detached in Runtime shutdown";
+ }
+
{
MutexLock mu(self, *Locks::runtime_shutdown_lock_);
shutting_down_started_ = true;
@@ -198,6 +205,16 @@ Runtime::~Runtime() {
}
shutting_down_ = true;
}
+ // Shutdown and wait for the daemons.
+ CHECK(self != nullptr);
+ if (IsFinishedStarting()) {
+ self->ClearException();
+ self->GetJniEnv()->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons,
+ WellKnownClasses::java_lang_Daemons_stop);
+ }
+ DetachCurrentThread();
+ self = nullptr;
+
// Shut down background profiler before the runtime exits.
if (profiler_started_) {
BackgroundMethodSamplingProfiler::Shutdown();
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 16338c476d..80bed23b77 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -69,6 +69,7 @@ jmethodID WellKnownClasses::java_lang_ClassNotFoundException_init;
jmethodID WellKnownClasses::java_lang_Daemons_requestGC;
jmethodID WellKnownClasses::java_lang_Daemons_requestHeapTrim;
jmethodID WellKnownClasses::java_lang_Daemons_start;
+jmethodID WellKnownClasses::java_lang_Daemons_stop;
jmethodID WellKnownClasses::java_lang_Double_valueOf;
jmethodID WellKnownClasses::java_lang_Float_valueOf;
jmethodID WellKnownClasses::java_lang_Integer_valueOf;
@@ -207,6 +208,7 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_Daemons_requestGC = CacheMethod(env, java_lang_Daemons, true, "requestGC", "()V");
java_lang_Daemons_requestHeapTrim = CacheMethod(env, java_lang_Daemons, true, "requestHeapTrim", "()V");
java_lang_Daemons_start = CacheMethod(env, java_lang_Daemons, true, "start", "()V");
+ java_lang_Daemons_stop = CacheMethod(env, java_lang_Daemons, true, "stop", "()V");
ScopedLocalRef<jclass> java_lang_ref_FinalizerReference(env, env->FindClass("java/lang/ref/FinalizerReference"));
java_lang_ref_FinalizerReference_add = CacheMethod(env, java_lang_ref_FinalizerReference.get(), true, "add", "(Ljava/lang/Object;)V");
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index d651b90c07..cb75e6ed7d 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -80,6 +80,7 @@ struct WellKnownClasses {
static jmethodID java_lang_Daemons_requestGC;
static jmethodID java_lang_Daemons_requestHeapTrim;
static jmethodID java_lang_Daemons_start;
+ static jmethodID java_lang_Daemons_stop;
static jmethodID java_lang_Double_valueOf;
static jmethodID java_lang_Float_valueOf;
static jmethodID java_lang_Integer_valueOf;