summaryrefslogtreecommitdiff
path: root/runtime/openjdkjvmti/events-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/openjdkjvmti/events-inl.h')
-rw-r--r--runtime/openjdkjvmti/events-inl.h25
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...);