Actually track the JNI MonitorEnter/MonitorExit calls.
Also log if we do end up having to clean up behind a detaching thread.
Also add a few missing "static"s.
Change-Id: I4ba1734b04b9a6dde112f3693a6dd171b42cd69c
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 00667ad..dba933a 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -2224,14 +2224,24 @@
static jint MonitorEnter(JNIEnv* env, jobject java_object) {
ScopedJniThreadState ts(env);
- Decode<Object*>(ts, java_object)->MonitorEnter(ts.Self());
- return ts.Self()->IsExceptionPending() ? JNI_ERR : JNI_OK;
+ Object* o = Decode<Object*>(ts, java_object);
+ o->MonitorEnter(ts.Self());
+ if (ts.Self()->IsExceptionPending()) {
+ return JNI_ERR;
+ }
+ ts.Env()->monitors.Add(o);
+ return JNI_OK;
}
static jint MonitorExit(JNIEnv* env, jobject java_object) {
ScopedJniThreadState ts(env);
- Decode<Object*>(ts, java_object)->MonitorExit(ts.Self());
- return ts.Self()->IsExceptionPending() ? JNI_ERR : JNI_OK;
+ Object* o = Decode<Object*>(ts, java_object);
+ o->MonitorExit(ts.Self());
+ if (ts.Self()->IsExceptionPending()) {
+ return JNI_ERR;
+ }
+ ts.Env()->monitors.Remove(o);
+ return JNI_OK;
}
static jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
diff --git a/src/thread.cc b/src/thread.cc
index 1f1952d..dea554f 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -314,7 +314,7 @@
return NULL;
}
-void SetVmData(Object* managed_thread, Thread* native_thread) {
+static void SetVmData(Object* managed_thread, Thread* native_thread) {
gThread_vmData->SetInt(managed_thread, reinterpret_cast<uintptr_t>(native_thread));
}
@@ -326,7 +326,7 @@
return FromManagedThread(Decode<Object*>(env, java_thread));
}
-size_t FixStackSize(size_t stack_size) {
+static size_t FixStackSize(size_t stack_size) {
// A stack size of zero means "use the default".
if (stack_size == 0) {
stack_size = Runtime::Current()->GetDefaultStackSize();
@@ -846,35 +846,28 @@
}
// TODO: make more accessible?
-Class* FindPrimitiveClassOrDie(ClassLinker* class_linker, char descriptor) {
- Class* c = class_linker->FindPrimitiveClass(descriptor);
- CHECK(c != NULL) << descriptor;
- return c;
-}
-
-// TODO: make more accessible?
-Class* FindClassOrDie(ClassLinker* class_linker, const char* descriptor) {
+static Class* FindClassOrDie(ClassLinker* class_linker, const char* descriptor) {
Class* c = class_linker->FindSystemClass(descriptor);
CHECK(c != NULL) << descriptor;
return c;
}
// TODO: make more accessible?
-Field* FindFieldOrDie(Class* c, const char* name, const char* descriptor) {
+static Field* FindFieldOrDie(Class* c, const char* name, const char* descriptor) {
Field* f = c->FindDeclaredInstanceField(name, descriptor);
CHECK(f != NULL) << PrettyClass(c) << " " << name << " " << descriptor;
return f;
}
// TODO: make more accessible?
-Method* FindMethodOrDie(Class* c, const char* name, const char* signature) {
+static Method* FindMethodOrDie(Class* c, const char* name, const char* signature) {
Method* m = c->FindVirtualMethod(name, signature);
CHECK(m != NULL) << PrettyClass(c) << " " << name << " " << signature;
return m;
}
// TODO: make more accessible?
-Field* FindStaticFieldOrDie(Class* c, const char* name, const char* descriptor) {
+static Field* FindStaticFieldOrDie(Class* c, const char* name, const char* descriptor) {
Field* f = c->FindDeclaredStaticField(name, descriptor);
CHECK(f != NULL) << PrettyClass(c) << " " << name << " " << descriptor;
return f;
@@ -974,8 +967,10 @@
memset(&held_mutexes_[0], 0, sizeof(held_mutexes_));
}
-void MonitorExitVisitor(const Object* object, void*) {
+static void MonitorExitVisitor(const Object* object, void*) {
Object* entered_monitor = const_cast<Object*>(object);
+ LOG(WARNING) << "Calling MonitorExit on object " << object << " (" << PrettyTypeOf(object) << ")"
+ << " left locked by native thread " << *Thread::Current() << " which is detaching";
entered_monitor->MonitorExit(Thread::Current());
}
@@ -1290,7 +1285,7 @@
};
// TODO: remove this.
-uintptr_t ManglePc(uintptr_t pc) {
+static uintptr_t ManglePc(uintptr_t pc) {
// Move the PC back 2 bytes as a call will frequently terminate the
// decoding of a particular instruction and we want to make sure we
// get the Dex PC of the instruction with the call and not the
@@ -1300,7 +1295,7 @@
}
// TODO: remove this.
-uintptr_t DemanglePc(uintptr_t pc) {
+static uintptr_t DemanglePc(uintptr_t pc) {
// Revert mangling for the case where we need the PC to return to the upcall
if (pc > 0) { pc += 2; }
return pc;
@@ -1873,7 +1868,7 @@
}
#if VERIFY_OBJECT_ENABLED
-void VerifyObject(const Object* obj, void*) {
+static void VerifyObject(const Object* obj, void*) {
Runtime::Current()->GetHeap()->VerifyObject(obj);
}