ART: Add CheckJNI lock checking
JNI MonitorEnter and MonitorExit have similar rules to structured
locking. Count locks in CheckJNI mode.
Bug: 23502994
Change-Id: Ie3f53d3aa669a6bd0c7153c50c168116b43764d9
diff --git a/runtime/jni_env_ext.h b/runtime/jni_env_ext.h
index 9b55536..3828ff0 100644
--- a/runtime/jni_env_ext.h
+++ b/runtime/jni_env_ext.h
@@ -43,8 +43,8 @@
void SetCheckJniEnabled(bool enabled);
- void PushFrame(int capacity);
- void PopFrame();
+ void PushFrame(int capacity) SHARED_REQUIRES(Locks::mutator_lock_);
+ void PopFrame() SHARED_REQUIRES(Locks::mutator_lock_);
template<typename T>
T AddLocalReference(mirror::Object* obj)
@@ -89,10 +89,27 @@
// Used by -Xcheck:jni.
const JNINativeInterface* unchecked_functions;
+ // Functions to keep track of monitor lock and unlock operations. Used to ensure proper locking
+ // rules in CheckJNI mode.
+
+ // Record locking of a monitor.
+ void RecordMonitorEnter(jobject obj) SHARED_REQUIRES(Locks::mutator_lock_);
+
+ // Check the release, that is, that the release is performed in the same JNI "segment."
+ void CheckMonitorRelease(jobject obj) SHARED_REQUIRES(Locks::mutator_lock_);
+
+ // Check that no monitors are held that have been acquired in this JNI "segment."
+ void CheckNoHeldMonitors() SHARED_REQUIRES(Locks::mutator_lock_);
+
private:
// The constructor should not be called directly. It may leave the object in an erronuous state,
// and the result needs to be checked.
JNIEnvExt(Thread* self, JavaVMExt* vm);
+
+ // All locked objects, with the (Java caller) stack frame that locked them. Used in CheckJNI
+ // to ensure that only monitors locked in this native frame are being unlocked, and that at
+ // the end all are unlocked.
+ std::vector<std::pair<uintptr_t, jobject>> locked_objects_;
};
// Used to save and restore the JNIEnvExt state when not going through code created by the JNI