diff options
| -rw-r--r-- | runtime/openjdkjvmti/ti_method.cc | 7 | ||||
| -rw-r--r-- | test/ti-stress/stress.cc | 49 |
2 files changed, 54 insertions, 2 deletions
diff --git a/runtime/openjdkjvmti/ti_method.cc b/runtime/openjdkjvmti/ti_method.cc index 2adabbaff4..f7e53474aa 100644 --- a/runtime/openjdkjvmti/ti_method.cc +++ b/runtime/openjdkjvmti/ti_method.cc @@ -44,6 +44,7 @@ #include "ScopedLocalRef.h" #include "thread-inl.h" #include "thread_list.h" +#include "ti_phase.h" namespace openjdkjvmti { @@ -54,12 +55,14 @@ struct TiMethodCallback : public art::MethodCallback { OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) { if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kNativeMethodBind)) { art::Thread* thread = art::Thread::Current(); + art::JNIEnvExt* jnienv = thread->GetJniEnv(); ScopedLocalRef<jthread> thread_jni( - thread->GetJniEnv(), thread->GetJniEnv()->AddLocalReference<jthread>(thread->GetPeer())); + jnienv, PhaseUtil::IsLivePhase() ? jnienv->AddLocalReference<jthread>(thread->GetPeer()) + : nullptr); art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative); event_handler->DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>( thread, - static_cast<JNIEnv*>(thread->GetJniEnv()), + static_cast<JNIEnv*>(jnienv), thread_jni.get(), art::jni::EncodeArtMethod(method), const_cast<void*>(cur_method), diff --git a/test/ti-stress/stress.cc b/test/ti-stress/stress.cc index fa49a35a8e..e7d76ddd55 100644 --- a/test/ti-stress/stress.cc +++ b/test/ti-stress/stress.cc @@ -84,6 +84,48 @@ static bool DoExtractClassFromData(StressData* data, return ReadIntoBuffer(data->out_temp_dex, dex); } +static void doJvmtiMethodBind(jvmtiEnv* jvmtienv, + JNIEnv* env, + jthread thread, + jmethodID m, + void* address, + /*out*/void** out_address) { + *out_address = address; + jvmtiThreadInfo info; + if (thread == nullptr) { + info.name = const_cast<char*>("<NULLPTR>"); + } else if (jvmtienv->GetThreadInfo(thread, &info) != JVMTI_ERROR_NONE) { + LOG(ERROR) << "Unable to get thread info!"; + return; + } + char *fname, *fsig, *fgen; + char *cname, *cgen; + jclass klass = nullptr; + if (jvmtienv->GetMethodDeclaringClass(m, &klass) != JVMTI_ERROR_NONE) { + LOG(ERROR) << "Unable to get method declaring class!"; + return; + } + if (jvmtienv->GetMethodName(m, &fname, &fsig, &fgen) != JVMTI_ERROR_NONE) { + LOG(ERROR) << "Unable to get method name!"; + env->DeleteLocalRef(klass); + return; + } + if (jvmtienv->GetClassSignature(klass, &cname, &cgen) != JVMTI_ERROR_NONE) { + LOG(ERROR) << "Unable to get class name!"; + env->DeleteLocalRef(klass); + return; + } + LOG(INFO) << "Loading native method \"" << cname << "->" << fname << fsig << "\". Thread is " + << info.name; + jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(cname)); + jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(cgen)); + jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fname)); + jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fsig)); + jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fgen)); + env->DeleteLocalRef(klass); + return; +} + // The hook we are using. void JNICALL ClassFileLoadHookSecretNoOp(jvmtiEnv* jvmti, JNIEnv* jni_env ATTRIBUTE_UNUSED, @@ -187,12 +229,19 @@ extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, jvmtiEventCallbacks cb; memset(&cb, 0, sizeof(cb)); cb.ClassFileLoadHook = ClassFileLoadHookSecretNoOp; + cb.NativeMethodBind = doJvmtiMethodBind; cb.VMInit = EnsureVMClassloaderInitializedCB; if (jvmti->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) { LOG(ERROR) << "Unable to set class file load hook cb!"; return 1; } if (jvmti->SetEventNotificationMode(JVMTI_ENABLE, + JVMTI_EVENT_NATIVE_METHOD_BIND, + nullptr) != JVMTI_ERROR_NONE) { + LOG(ERROR) << "Unable to enable JVMTI_EVENT_NATIVE_METHOD_BIND event!"; + return 1; + } + if (jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, nullptr) != JVMTI_ERROR_NONE) { LOG(ERROR) << "Unable to enable JVMTI_EVENT_VM_INIT event!"; |