diff options
Diffstat (limited to 'runtime/openjdkjvmti/events-inl.h')
| -rw-r--r-- | runtime/openjdkjvmti/events-inl.h | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/runtime/openjdkjvmti/events-inl.h b/runtime/openjdkjvmti/events-inl.h index 57abf3142d..cb7e6a9ad0 100644 --- a/runtime/openjdkjvmti/events-inl.h +++ b/runtime/openjdkjvmti/events-inl.h @@ -20,6 +20,7 @@ #include <array> #include "events.h" +#include "ScopedLocalRef.h" #include "art_jvmti.h" @@ -135,6 +136,8 @@ inline void EventHandler::DispatchClassFileLoadHookEvent(art::Thread* thread, continue; } if (ShouldDispatch<kEvent>(env, thread)) { + ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred()); + jnienv->ExceptionClear(); jint new_len = 0; unsigned char* new_data = nullptr; auto callback = impl::GetCallback<kEvent>(env); @@ -148,6 +151,9 @@ inline void EventHandler::DispatchClassFileLoadHookEvent(art::Thread* thread, current_class_data, &new_len, &new_data); + if (thr.get() != nullptr && !jnienv->ExceptionCheck()) { + jnienv->Throw(thr.get()); + } if (new_data != nullptr && new_data != current_class_data) { // Destroy the data the last transformer made. We skip this if the previous state was the // initial one since we don't know here which jvmtiEnv allocated it. @@ -180,6 +186,25 @@ inline void EventHandler::DispatchEvent(art::Thread* thread, Args... args) const } } +// Events with JNIEnvs need to stash pending exceptions since they can cause new ones to be thrown. +// In accordance with the JVMTI specification we allow exceptions originating from events to +// overwrite the current exception, including exceptions originating from earlier events. +// TODO It would be nice to add the overwritten exceptions to the suppressed exceptions list of the +// newest exception. +template <ArtJvmtiEvent kEvent, typename ...Args> +inline void EventHandler::DispatchEvent(art::Thread* thread, JNIEnv* jnienv, Args... args) const { + for (ArtJvmTiEnv* env : envs) { + if (env != nullptr) { + ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred()); + jnienv->ExceptionClear(); + DispatchEvent<kEvent, JNIEnv*, Args...>(env, thread, jnienv, args...); + if (thr.get() != nullptr && !jnienv->ExceptionCheck()) { + jnienv->Throw(thr.get()); + } + } + } +} + template <ArtJvmtiEvent kEvent, typename ...Args> inline void EventHandler::DispatchEvent(ArtJvmTiEnv* env, art::Thread* thread, Args... args) const { using FnType = void(jvmtiEnv*, Args...); |