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/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