Implement JVMTI GetCurrentContendedMonitor
Adds the JVMTI can_get_current_contended_monitor capability and
implements all associated functions and behaviors.
Test: ./test.py --host -j50
Bug: 62821960
Bug: 34415266
Change-Id: Ia3f19f0fbb21125bc85fb71f55e52ec61141c4ec
diff --git a/openjdkjvmti/OpenjdkJvmTi.cc b/openjdkjvmti/OpenjdkJvmTi.cc
index 277f611..4339b2b 100644
--- a/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/openjdkjvmti/OpenjdkJvmTi.cc
@@ -207,11 +207,11 @@
}
static jvmtiError GetCurrentContendedMonitor(jvmtiEnv* env,
- jthread thread ATTRIBUTE_UNUSED,
- jobject* monitor_ptr ATTRIBUTE_UNUSED) {
+ jthread thread,
+ jobject* monitor_ptr) {
ENSURE_VALID_ENV(env);
ENSURE_HAS_CAP(env, can_get_current_contended_monitor);
- return ERR(NOT_IMPLEMENTED);
+ return MonitorUtil::GetCurrentContendedMonitor(env, thread, monitor_ptr);
}
static jvmtiError RunAgentThread(jvmtiEnv* env,
diff --git a/openjdkjvmti/art_jvmti.h b/openjdkjvmti/art_jvmti.h
index 8e3cf21..10ddfc1 100644
--- a/openjdkjvmti/art_jvmti.h
+++ b/openjdkjvmti/art_jvmti.h
@@ -225,7 +225,7 @@
.can_get_bytecodes = 1,
.can_get_synthetic_attribute = 1,
.can_get_owned_monitor_info = 1,
- .can_get_current_contended_monitor = 0,
+ .can_get_current_contended_monitor = 1,
.can_get_monitor_info = 1,
.can_pop_frame = 0,
.can_redefine_classes = 1,
diff --git a/openjdkjvmti/ti_monitor.cc b/openjdkjvmti/ti_monitor.cc
index adaa48c..f92d81e 100644
--- a/openjdkjvmti/ti_monitor.cc
+++ b/openjdkjvmti/ti_monitor.cc
@@ -37,10 +37,13 @@
#include <mutex>
#include "art_jvmti.h"
+#include "monitor.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
#include "ti_thread.h"
+#include "thread.h"
+#include "thread_pool.h"
namespace openjdkjvmti {
@@ -323,4 +326,77 @@
return ERR(NONE);
}
+jvmtiError MonitorUtil::GetCurrentContendedMonitor(jvmtiEnv* env ATTRIBUTE_UNUSED,
+ jthread thread,
+ jobject* monitor) {
+ if (monitor == nullptr) {
+ return ERR(NULL_POINTER);
+ }
+ art::Thread* self = art::Thread::Current();
+ art::ScopedObjectAccess soa(self);
+ art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+ art::Thread* target = ThreadUtil::GetNativeThread(thread, soa);
+ if (target == nullptr && thread == nullptr) {
+ return ERR(INVALID_THREAD);
+ }
+ if (target == nullptr) {
+ return ERR(THREAD_NOT_ALIVE);
+ }
+ struct GetContendedMonitorClosure : public art::Closure {
+ public:
+ explicit GetContendedMonitorClosure(art::Thread* current, jobject* out)
+ : result_thread_(current), out_(out) {}
+
+ void Run(art::Thread* target_thread) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ switch (target_thread->GetState()) {
+ // These three we are actually currently waiting on a monitor and have sent the appropriate
+ // events (if anyone is listening).
+ case art::kBlocked:
+ case art::kTimedWaiting:
+ case art::kWaiting: {
+ art::mirror::Object* mon = art::Monitor::GetContendedMonitor(target_thread);
+ *out_ = (mon == nullptr) ? nullptr
+ : result_thread_->GetJniEnv()->AddLocalReference<jobject>(mon);
+ return;
+ }
+ case art::kTerminated:
+ case art::kRunnable:
+ case art::kSleeping:
+ case art::kWaitingForLockInflation:
+ case art::kWaitingForTaskProcessor:
+ case art::kWaitingForGcToComplete:
+ case art::kWaitingForCheckPointsToRun:
+ case art::kWaitingPerformingGc:
+ case art::kWaitingForDebuggerSend:
+ case art::kWaitingForDebuggerToAttach:
+ case art::kWaitingInMainDebuggerLoop:
+ case art::kWaitingForDebuggerSuspension:
+ case art::kWaitingForJniOnLoad:
+ case art::kWaitingForSignalCatcherOutput:
+ case art::kWaitingInMainSignalCatcherLoop:
+ case art::kWaitingForDeoptimization:
+ case art::kWaitingForMethodTracingStart:
+ case art::kWaitingForVisitObjects:
+ case art::kWaitingForGetObjectsAllocated:
+ case art::kWaitingWeakGcRootRead:
+ case art::kWaitingForGcThreadFlip:
+ case art::kStarting:
+ case art::kNative:
+ case art::kSuspended: {
+ // We aren't currently (explicitly) waiting for a monitor anything so just return null.
+ *out_ = nullptr;
+ return;
+ }
+ }
+ }
+
+ private:
+ art::Thread* result_thread_;
+ jobject* out_;
+ };
+ GetContendedMonitorClosure closure(self, monitor);
+ target->RequestSynchronousCheckpoint(&closure);
+ return OK;
+}
+
} // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_monitor.h b/openjdkjvmti/ti_monitor.h
index add089c..e0a865b 100644
--- a/openjdkjvmti/ti_monitor.h
+++ b/openjdkjvmti/ti_monitor.h
@@ -52,6 +52,8 @@
static jvmtiError RawMonitorNotify(jvmtiEnv* env, jrawMonitorID monitor);
static jvmtiError RawMonitorNotifyAll(jvmtiEnv* env, jrawMonitorID monitor);
+
+ static jvmtiError GetCurrentContendedMonitor(jvmtiEnv* env, jthread thr, jobject* monitor);
};
} // namespace openjdkjvmti