Revert "Revert "JVMTI Exception and ExceptionCatch events""

Fixed error where we were incorrectly not updating a ShadowFrame
dex_pc causing deoptimization errors.

Bug: 62821960
Bug: 65049545

Test: ./test.py --host -j50
Test: ./art/tools/run-libcore-tests.sh \
            --mode=host --variant-X32 --debug

This reverts commit 959742483885779f106e000df6dd422fc8657931.

Change-Id: I91ab2bc3e645ddf0359c189b19a59a3ecf0d8921
diff --git a/test/1927-exception-event/exception_event.cc b/test/1927-exception-event/exception_event.cc
new file mode 100644
index 0000000..3197bcd
--- /dev/null
+++ b/test/1927-exception-event/exception_event.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pthread.h>
+
+#include <cstdio>
+#include <iostream>
+#include <vector>
+
+#include "android-base/logging.h"
+#include "jni.h"
+#include "jvmti.h"
+
+#include "scoped_local_ref.h"
+#include "scoped_primitive_array.h"
+
+// Test infrastructure
+#include "jvmti_helper.h"
+#include "test_env.h"
+
+namespace art {
+namespace Test1927ExceptionEvent {
+
+static void ThrowNative(JNIEnv* env) {
+  ScopedLocalRef<jclass> exception(env, env->FindClass("art/Test1927$TestException"));
+  env->ThrowNew(exception.get(), "from native");
+}
+
+static void CallMethod(JNIEnv* env, jclass test, const char* name) {
+  jmethodID m = env->GetStaticMethodID(test, name, "()V");
+  env->CallStaticVoidMethod(test, m);
+}
+
+static void ClearAndPrintException(JNIEnv* env, jclass test) {
+  jthrowable e = env->ExceptionOccurred();
+  env->ExceptionClear();
+  jmethodID m = env->GetStaticMethodID(test, "printException", "(Ljava/lang/Throwable;)V");
+  env->CallStaticVoidMethod(test, m, e);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1927_terminal_1N(JNIEnv* env, jclass) {
+  ThrowNative(env);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1927_test_1N(JNIEnv* env, jclass test) {
+  ThrowNative(env);
+  ClearAndPrintException(env, test);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1927_test_1N_1J(JNIEnv* env, jclass test) {
+  CallMethod(env, test, "terminal_J");
+  ClearAndPrintException(env, test);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1927_test_1N_1N(JNIEnv* env, jclass test) {
+  CallMethod(env, test, "terminal_N");
+  ClearAndPrintException(env, test);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1927_intermediate_1N_1J(JNIEnv* env, jclass test) {
+  CallMethod(env, test, "terminal_J");
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1927_intermediate_1N_1N(JNIEnv* env, jclass test) {
+  CallMethod(env, test, "terminal_N");
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1927_test_1N_1J_1J(JNIEnv* env, jclass test) {
+  CallMethod(env, test, "intermediate_J_J");
+  ClearAndPrintException(env, test);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1927_test_1N_1J_1N(JNIEnv* env, jclass test) {
+  CallMethod(env, test, "intermediate_J_N");
+  ClearAndPrintException(env, test);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1927_test_1N_1N_1J(JNIEnv* env, jclass test) {
+  CallMethod(env, test, "intermediate_N_J");
+  ClearAndPrintException(env, test);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1927_test_1N_1N_1N(JNIEnv* env, jclass test) {
+  CallMethod(env, test, "intermediate_N_N");
+  ClearAndPrintException(env, test);
+}
+
+}  // namespace Test1927ExceptionEvent
+}  // namespace art
diff --git a/test/1927-exception-event/expected.txt b/test/1927-exception-event/expected.txt
new file mode 100644
index 0000000..be8f39c
--- /dev/null
+++ b/test/1927-exception-event/expected.txt
@@ -0,0 +1,278 @@
+class art.Test1927$TestException
+Running test_J
+main: public static void art.Test1927.test_J() @ line = 110 throws class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static void art.Test1927.test_J() @ line = 110
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 239
+	Will be caught by: public static void art.Test1927.test_J() @ line = 111
+main: public static void art.Test1927.test_J() @ line = 111 caught class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
+		public static void art.Test1927.test_J() @ line = 111
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 239
+Caught exception: art.Test1927$TestException: from java
+Running test_N()
+Caught exception: art.Test1927$TestException: from native
+Running test_J_J()
+main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static void art.Test1927.terminal_J() @ line = 103
+		public static void art.Test1927.test_J_J() @ line = 121
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 243
+	Will be caught by: public static void art.Test1927.test_J_J() @ line = 122
+main: public static void art.Test1927.test_J_J() @ line = 122 caught class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
+		public static void art.Test1927.test_J_J() @ line = 122
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 243
+Caught exception: art.Test1927$TestException: from java
+Running test_J_N()
+main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static native void art.Test1927.terminal_N() @ line = -1
+		public static void art.Test1927.test_J_N() @ line = 129
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 245
+	Will be caught by: public static void art.Test1927.test_J_N() @ line = 130
+main: public static void art.Test1927.test_J_N() @ line = 130 caught class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
+		public static void art.Test1927.test_J_N() @ line = 130
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 245
+Caught exception: art.Test1927$TestException: from native
+Running test_N_J()
+main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static void art.Test1927.terminal_J() @ line = 103
+		public static native void art.Test1927.test_N_J() @ line = -1
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 247
+	Will be caught by: <UNKNOWN>
+Caught exception: art.Test1927$TestException: from java
+Running test_N_N()
+main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static native void art.Test1927.terminal_N() @ line = -1
+		public static native void art.Test1927.test_N_N() @ line = -1
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 249
+	Will be caught by: <UNKNOWN>
+Caught exception: art.Test1927$TestException: from native
+Running test_J_J_J()
+main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static void art.Test1927.terminal_J() @ line = 103
+		public static void art.Test1927.intermediate_J_J() @ line = 138
+		public static void art.Test1927.test_J_J_J() @ line = 145
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 251
+	Will be caught by: public static void art.Test1927.test_J_J_J() @ line = 146
+main: public static void art.Test1927.test_J_J_J() @ line = 146 caught class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
+		public static void art.Test1927.test_J_J_J() @ line = 146
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 251
+Caught exception: art.Test1927$TestException: from java
+Running test_J_J_N()
+main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static native void art.Test1927.terminal_N() @ line = -1
+		public static void art.Test1927.intermediate_J_N() @ line = 139
+		public static void art.Test1927.test_J_J_N() @ line = 153
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 253
+	Will be caught by: public static void art.Test1927.test_J_J_N() @ line = 154
+main: public static void art.Test1927.test_J_J_N() @ line = 154 caught class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
+		public static void art.Test1927.test_J_J_N() @ line = 154
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 253
+Caught exception: art.Test1927$TestException: from native
+Running test_J_N_J()
+main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static void art.Test1927.terminal_J() @ line = 103
+		public static native void art.Test1927.intermediate_N_J() @ line = -1
+		public static void art.Test1927.test_J_N_J() @ line = 161
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 255
+	Will be caught by: public static void art.Test1927.test_J_N_J() @ line = 162
+main: public static void art.Test1927.test_J_N_J() @ line = 162 caught class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
+		public static void art.Test1927.test_J_N_J() @ line = 162
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 255
+Caught exception: art.Test1927$TestException: from java
+Running test_J_N_N()
+main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static native void art.Test1927.terminal_N() @ line = -1
+		public static native void art.Test1927.intermediate_N_N() @ line = -1
+		public static void art.Test1927.test_J_N_N() @ line = 169
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 257
+	Will be caught by: public static void art.Test1927.test_J_N_N() @ line = 170
+main: public static void art.Test1927.test_J_N_N() @ line = 170 caught class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
+		public static void art.Test1927.test_J_N_N() @ line = 170
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 257
+Caught exception: art.Test1927$TestException: from native
+Running test_N_J_J()
+main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static void art.Test1927.terminal_J() @ line = 103
+		public static void art.Test1927.intermediate_J_J() @ line = 138
+		public static native void art.Test1927.test_N_J_J() @ line = -1
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 259
+	Will be caught by: <UNKNOWN>
+Caught exception: art.Test1927$TestException: from java
+Running test_N_J_N()
+main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static native void art.Test1927.terminal_N() @ line = -1
+		public static void art.Test1927.intermediate_J_N() @ line = 139
+		public static native void art.Test1927.test_N_J_N() @ line = -1
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 261
+	Will be caught by: <UNKNOWN>
+Caught exception: art.Test1927$TestException: from native
+Running test_N_N_J()
+main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static void art.Test1927.terminal_J() @ line = 103
+		public static native void art.Test1927.intermediate_N_J() @ line = -1
+		public static native void art.Test1927.test_N_N_J() @ line = -1
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 263
+	Will be caught by: <UNKNOWN>
+Caught exception: art.Test1927$TestException: from java
+Running test_N_N_N()
+main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static native void art.Test1927.terminal_N() @ line = -1
+		public static native void art.Test1927.intermediate_N_N() @ line = -1
+		public static native void art.Test1927.test_N_N_N() @ line = -1
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 265
+	Will be caught by: <UNKNOWN>
+Caught exception: art.Test1927$TestException: from native
+Running test_extra_N_J_J()
+main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static void art.Test1927.terminal_J() @ line = 103
+		public static void art.Test1927.intermediate_J_J() @ line = 138
+		public static native void art.Test1927.test_N_J_J() @ line = -1
+		public static void art.Test1927.test_extra_N_J_J() @ line = 182
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 267
+	Will be caught by: public static void art.Test1927.test_extra_N_J_J() @ line = 183
+Caught exception: art.Test1927$TestException: from java
+Running test_extra_N_J_N()
+main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static native void art.Test1927.terminal_N() @ line = -1
+		public static void art.Test1927.intermediate_J_N() @ line = 139
+		public static native void art.Test1927.test_N_J_N() @ line = -1
+		public static void art.Test1927.test_extra_N_J_N() @ line = 189
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 269
+	Will be caught by: public static void art.Test1927.test_extra_N_J_N() @ line = 190
+Caught exception: art.Test1927$TestException: from native
+Running test_extra_N_N_J()
+main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static void art.Test1927.terminal_J() @ line = 103
+		public static native void art.Test1927.intermediate_N_J() @ line = -1
+		public static native void art.Test1927.test_N_N_J() @ line = -1
+		public static void art.Test1927.test_extra_N_N_J() @ line = 196
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 271
+	Will be caught by: public static void art.Test1927.test_extra_N_N_J() @ line = 197
+Caught exception: art.Test1927$TestException: from java
+Running test_extra_N_N_N()
+main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1927.PrintStack() @ line = 28
+		public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
+		public static native void art.Test1927.terminal_N() @ line = -1
+		public static native void art.Test1927.intermediate_N_N() @ line = -1
+		public static native void art.Test1927.test_N_N_N() @ line = -1
+		public static void art.Test1927.test_extra_N_N_N() @ line = 203
+		public static void art.Test1927.run() throws java.lang.Exception @ line = 273
+	Will be caught by: public static void art.Test1927.test_extra_N_N_N() @ line = 204
+Caught exception: art.Test1927$TestException: from native
diff --git a/test/1927-exception-event/info.txt b/test/1927-exception-event/info.txt
new file mode 100644
index 0000000..a74167f
--- /dev/null
+++ b/test/1927-exception-event/info.txt
@@ -0,0 +1,3 @@
+Test basic JVMTI exception event functionality
+
+Ensures that we can receive exception and exception catch events from JVMTI.
diff --git a/test/1927-exception-event/run b/test/1927-exception-event/run
new file mode 100755
index 0000000..51875a7
--- /dev/null
+++ b/test/1927-exception-event/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Ask for stack traces to be dumped to a file rather than to stdout.
+./default-run "$@" --jvmti
diff --git a/test/1927-exception-event/src/Main.java b/test/1927-exception-event/src/Main.java
new file mode 100644
index 0000000..5b9b31b
--- /dev/null
+++ b/test/1927-exception-event/src/Main.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+  public static void main(String[] args) throws Exception {
+    art.Test1927.run();
+  }
+}
diff --git a/test/1927-exception-event/src/art/Breakpoint.java b/test/1927-exception-event/src/art/Breakpoint.java
new file mode 100644
index 0000000..bbb89f7
--- /dev/null
+++ b/test/1927-exception-event/src/art/Breakpoint.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Executable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Objects;
+
+public class Breakpoint {
+  public static class Manager {
+    public static class BP {
+      public final Executable method;
+      public final long location;
+
+      public BP(Executable method) {
+        this(method, getStartLocation(method));
+      }
+
+      public BP(Executable method, long location) {
+        this.method = method;
+        this.location = location;
+      }
+
+      @Override
+      public boolean equals(Object other) {
+        return (other instanceof BP) &&
+            method.equals(((BP)other).method) &&
+            location == ((BP)other).location;
+      }
+
+      @Override
+      public String toString() {
+        return method.toString() + " @ " + getLine();
+      }
+
+      @Override
+      public int hashCode() {
+        return Objects.hash(method, location);
+      }
+
+      public int getLine() {
+        try {
+          LineNumber[] lines = getLineNumberTable(method);
+          int best = -1;
+          for (LineNumber l : lines) {
+            if (l.location > location) {
+              break;
+            } else {
+              best = l.line;
+            }
+          }
+          return best;
+        } catch (Exception e) {
+          return -1;
+        }
+      }
+    }
+
+    private Set<BP> breaks = new HashSet<>();
+
+    public void setBreakpoints(BP... bs) {
+      for (BP b : bs) {
+        if (breaks.add(b)) {
+          Breakpoint.setBreakpoint(b.method, b.location);
+        }
+      }
+    }
+    public void setBreakpoint(Executable method, long location) {
+      setBreakpoints(new BP(method, location));
+    }
+
+    public void clearBreakpoints(BP... bs) {
+      for (BP b : bs) {
+        if (breaks.remove(b)) {
+          Breakpoint.clearBreakpoint(b.method, b.location);
+        }
+      }
+    }
+    public void clearBreakpoint(Executable method, long location) {
+      clearBreakpoints(new BP(method, location));
+    }
+
+    public void clearAllBreakpoints() {
+      clearBreakpoints(breaks.toArray(new BP[0]));
+    }
+  }
+
+  public static void startBreakpointWatch(Class<?> methodClass,
+                                          Executable breakpointReached,
+                                          Thread thr) {
+    startBreakpointWatch(methodClass, breakpointReached, false, thr);
+  }
+
+  /**
+   * Enables the trapping of breakpoint events.
+   *
+   * If allowRecursive == true then breakpoints will be sent even if one is currently being handled.
+   */
+  public static native void startBreakpointWatch(Class<?> methodClass,
+                                                 Executable breakpointReached,
+                                                 boolean allowRecursive,
+                                                 Thread thr);
+  public static native void stopBreakpointWatch(Thread thr);
+
+  public static final class LineNumber implements Comparable<LineNumber> {
+    public final long location;
+    public final int line;
+
+    private LineNumber(long loc, int line) {
+      this.location = loc;
+      this.line = line;
+    }
+
+    public boolean equals(Object other) {
+      return other instanceof LineNumber && ((LineNumber)other).line == line &&
+          ((LineNumber)other).location == location;
+    }
+
+    public int compareTo(LineNumber other) {
+      int v = Integer.valueOf(line).compareTo(Integer.valueOf(other.line));
+      if (v != 0) {
+        return v;
+      } else {
+        return Long.valueOf(location).compareTo(Long.valueOf(other.location));
+      }
+    }
+  }
+
+  public static native void setBreakpoint(Executable m, long loc);
+  public static void setBreakpoint(Executable m, LineNumber l) {
+    setBreakpoint(m, l.location);
+  }
+
+  public static native void clearBreakpoint(Executable m, long loc);
+  public static void clearBreakpoint(Executable m, LineNumber l) {
+    clearBreakpoint(m, l.location);
+  }
+
+  private static native Object[] getLineNumberTableNative(Executable m);
+  public static LineNumber[] getLineNumberTable(Executable m) {
+    Object[] nativeTable = getLineNumberTableNative(m);
+    long[] location = (long[])(nativeTable[0]);
+    int[] lines = (int[])(nativeTable[1]);
+    if (lines.length != location.length) {
+      throw new Error("Lines and locations have different lengths!");
+    }
+    LineNumber[] out = new LineNumber[lines.length];
+    for (int i = 0; i < lines.length; i++) {
+      out[i] = new LineNumber(location[i], lines[i]);
+    }
+    return out;
+  }
+
+  public static native long getStartLocation(Executable m);
+
+  public static int locationToLine(Executable m, long location) {
+    try {
+      Breakpoint.LineNumber[] lines = Breakpoint.getLineNumberTable(m);
+      int best = -1;
+      for (Breakpoint.LineNumber l : lines) {
+        if (l.location > location) {
+          break;
+        } else {
+          best = l.line;
+        }
+      }
+      return best;
+    } catch (Exception e) {
+      return -1;
+    }
+  }
+
+  public static long lineToLocation(Executable m, int line) throws Exception {
+    try {
+      Breakpoint.LineNumber[] lines = Breakpoint.getLineNumberTable(m);
+      for (Breakpoint.LineNumber l : lines) {
+        if (l.line == line) {
+          return l.location;
+        }
+      }
+      throw new Exception("Unable to find line " + line + " in " + m);
+    } catch (Exception e) {
+      throw new Exception("Unable to get line number info for " + m, e);
+    }
+  }
+}
+
diff --git a/test/1927-exception-event/src/art/Exceptions.java b/test/1927-exception-event/src/art/Exceptions.java
new file mode 100644
index 0000000..2c959ec
--- /dev/null
+++ b/test/1927-exception-event/src/art/Exceptions.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class Exceptions {
+  public static native void setupExceptionTracing(
+      Class<?> methodClass,
+      Class<?> exceptionClass,
+      Method exceptionEventMethod,
+      Method exceptionCaughtEventMethod);
+
+  public static native void enableExceptionCatchEvent(Thread thr);
+  public static native void enableExceptionEvent(Thread thr);
+  public static native void disableExceptionCatchEvent(Thread thr);
+  public static native void disableExceptionEvent(Thread thr);
+}
diff --git a/test/1927-exception-event/src/art/StackTrace.java b/test/1927-exception-event/src/art/StackTrace.java
new file mode 100644
index 0000000..b12c3df
--- /dev/null
+++ b/test/1927-exception-event/src/art/StackTrace.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
+
+public class StackTrace {
+  public static class StackFrameData {
+    public final Thread thr;
+    public final Executable method;
+    public final long current_location;
+    public final int depth;
+
+    public StackFrameData(Thread thr, Executable e, long loc, int depth) {
+      this.thr = thr;
+      this.method = e;
+      this.current_location = loc;
+      this.depth = depth;
+    }
+    @Override
+    public String toString() {
+      return String.format(
+          "StackFrameData { thr: '%s', method: '%s', loc: %d, depth: %d }",
+          this.thr,
+          this.method,
+          this.current_location,
+          this.depth);
+    }
+  }
+
+  public static native int GetStackDepth(Thread thr);
+
+  private static native StackFrameData[] nativeGetStackTrace(Thread thr);
+
+  public static StackFrameData[] GetStackTrace(Thread thr) {
+    // The RI seems to give inconsistent (and sometimes nonsensical) results if the thread is not
+    // suspended. The spec says that not being suspended is fine but since we want this to be
+    // consistent we will suspend for the RI.
+    boolean suspend_thread =
+        !System.getProperty("java.vm.name").equals("Dalvik") &&
+        !thr.equals(Thread.currentThread());
+    if (suspend_thread) {
+      Suspension.suspend(thr);
+    }
+    StackFrameData[] out = nativeGetStackTrace(thr);
+    if (suspend_thread) {
+      Suspension.resume(thr);
+    }
+    return out;
+  }
+}
+
diff --git a/test/1927-exception-event/src/art/Suspension.java b/test/1927-exception-event/src/art/Suspension.java
new file mode 100644
index 0000000..16e62cc
--- /dev/null
+++ b/test/1927-exception-event/src/art/Suspension.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+public class Suspension {
+  // Suspends a thread using jvmti.
+  public native static void suspend(Thread thr);
+
+  // Resumes a thread using jvmti.
+  public native static void resume(Thread thr);
+
+  public native static boolean isSuspended(Thread thr);
+
+  public native static int[] suspendList(Thread... threads);
+  public native static int[] resumeList(Thread... threads);
+}
diff --git a/test/1927-exception-event/src/art/Test1927.java b/test/1927-exception-event/src/art/Test1927.java
new file mode 100644
index 0000000..c2d13bb
--- /dev/null
+++ b/test/1927-exception-event/src/art/Test1927.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+
+public class Test1927 {
+  private static boolean PRINT_FULL_EXCEPTION = false;
+  private static void PrintStack() {
+    System.out.println("\tCurrent Stack:");
+    for (StackTrace.StackFrameData e : StackTrace.GetStackTrace(Thread.currentThread())) {
+      if (Objects.equals(e.method.getDeclaringClass().getPackage(), Test1927.class.getPackage())) {
+        System.out.println("\t\t" + e.method + " @ line = " +
+            Breakpoint.locationToLine(e.method, e.current_location));
+      }
+    }
+  }
+
+  public static void ExceptionCatchEvent(Thread thr,
+                                         Executable catch_method,
+                                         long catch_location,
+                                         Throwable exception) {
+    System.out.println(thr.getName() + ": " + catch_method + " @ line = " +
+        Breakpoint.locationToLine(catch_method, catch_location) + " caught " +
+        exception.getClass() + ": " + exception.getMessage());
+    PrintStack();
+    if (PRINT_FULL_EXCEPTION) {
+      System.out.print("exception is: ");
+      exception.printStackTrace(System.out);
+    }
+  }
+
+  public static void ExceptionEvent(Thread thr,
+                                    Executable throw_method,
+                                    long throw_location,
+                                    Throwable exception,
+                                    Executable catch_method,
+                                    long catch_location) {
+    System.out.println(thr.getName() + ": " + throw_method + " @ line = " +
+        Breakpoint.locationToLine(throw_method, throw_location) + " throws " +
+        exception.getClass() + ": " + exception.getMessage());
+    String catch_message;
+    if (catch_method == null) {
+      catch_message = "<UNKNOWN>";
+    } else {
+      catch_message = catch_method.toString() + " @ line = " +
+          Breakpoint.locationToLine(catch_method, catch_location);
+    }
+    PrintStack();
+    System.out.println("\tWill be caught by: " + catch_message);
+    if (PRINT_FULL_EXCEPTION) {
+      System.out.print("exception is: ");
+      exception.printStackTrace(System.out);
+    }
+  }
+
+  public static class TestException extends Error {
+    public TestException(String s) { super(s); }
+    public TestException() { super("from java"); }
+  }
+
+  // Possibilities
+  // ( -> is a JNI/Java call.)
+  // Furthest left catches/clears the exception
+  // Furthest right throws it.
+  // J
+  // N
+  // J -> J
+  // J -> N
+  // N -> J
+  // N -> N
+  // J -> J -> J
+  // J -> J -> N
+  // J -> N -> J
+  // J -> N -> N
+  // N -> J -> J
+  // N -> J -> N
+  // N -> N -> J
+  // N -> N -> N
+  // extra -> N -> J -> J
+  // extra -> N -> J -> N
+  // extra -> N -> N -> J
+  // extra -> N -> N -> N
+
+  public static void terminal_J() {
+    throw new TestException();
+  }
+
+  public static native void terminal_N();
+
+  public static void test_J() {
+    try {
+      throw new TestException();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+
+  // Do test_J but native
+  public static native void test_N();
+
+  public static void test_J_J() {
+    try {
+      terminal_J();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+
+  public static void test_J_N() {
+    try {
+      terminal_N();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+
+  public static native void test_N_J();
+  public static native void test_N_N();
+
+  public static void intermediate_J_J() { terminal_J(); }
+  public static void intermediate_J_N() { terminal_N(); }
+  public static native void intermediate_N_J();
+  public static native void intermediate_N_N();
+
+  public static void test_J_J_J() {
+    try {
+      intermediate_J_J();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+
+  public static void test_J_J_N() {
+    try {
+      intermediate_J_N();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+
+  public static void test_J_N_J() {
+    try {
+      intermediate_N_J();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+
+  public static void test_J_N_N() {
+    try {
+      intermediate_N_N();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+
+  public static native void test_N_J_J();
+  public static native void test_N_J_N();
+  public static native void test_N_N_J();
+  public static native void test_N_N_N();
+
+  public static void test_extra_N_J_J() {
+    try {
+      test_N_J_J();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+  public static void test_extra_N_J_N() {
+    try {
+      test_N_J_N();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+  public static void test_extra_N_N_J() {
+    try {
+      test_N_N_J();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+  public static void test_extra_N_N_N() {
+    try {
+      test_N_N_N();
+    } catch (TestException e) {
+      printException(e);
+    }
+  }
+
+  public static void printException(Throwable e) {
+    System.out.println("Caught exception: " + e);
+    if (PRINT_FULL_EXCEPTION) {
+      e.printStackTrace(System.out);
+    }
+  }
+
+  public static void run() throws Exception {
+    // Make sure classes are loaded first.
+    System.out.println(TestException.class.toString());
+    Exceptions.setupExceptionTracing(
+        Test1927.class,
+        TestException.class,
+        Test1927.class.getDeclaredMethod(
+            "ExceptionEvent",
+            Thread.class,
+            Executable.class,
+            Long.TYPE,
+            Throwable.class,
+            Executable.class,
+            Long.TYPE),
+        Test1927.class.getDeclaredMethod(
+            "ExceptionCatchEvent",
+            Thread.class,
+            Executable.class,
+            Long.TYPE,
+            Throwable.class));
+    Exceptions.enableExceptionEvent(Thread.currentThread());
+    Exceptions.enableExceptionCatchEvent(Thread.currentThread());
+    System.out.println("Running test_J");
+    test_J();
+    System.out.println("Running test_N()");
+    test_N();
+    System.out.println("Running test_J_J()");
+    test_J_J();
+    System.out.println("Running test_J_N()");
+    test_J_N();
+    System.out.println("Running test_N_J()");
+    test_N_J();
+    System.out.println("Running test_N_N()");
+    test_N_N();
+    System.out.println("Running test_J_J_J()");
+    test_J_J_J();
+    System.out.println("Running test_J_J_N()");
+    test_J_J_N();
+    System.out.println("Running test_J_N_J()");
+    test_J_N_J();
+    System.out.println("Running test_J_N_N()");
+    test_J_N_N();
+    System.out.println("Running test_N_J_J()");
+    test_N_J_J();
+    System.out.println("Running test_N_J_N()");
+    test_N_J_N();
+    System.out.println("Running test_N_N_J()");
+    test_N_N_J();
+    System.out.println("Running test_N_N_N()");
+    test_N_N_N();
+    System.out.println("Running test_extra_N_J_J()");
+    test_extra_N_J_J();
+    System.out.println("Running test_extra_N_J_N()");
+    test_extra_N_J_N();
+    System.out.println("Running test_extra_N_N_J()");
+    test_extra_N_N_J();
+    System.out.println("Running test_extra_N_N_N()");
+    test_extra_N_N_N();
+    Exceptions.disableExceptionCatchEvent(Thread.currentThread());
+    Exceptions.disableExceptionEvent(Thread.currentThread());
+  }
+}
diff --git a/test/1928-exception-event-exception/expected.txt b/test/1928-exception-event-exception/expected.txt
new file mode 100644
index 0000000..1692d04
--- /dev/null
+++ b/test/1928-exception-event-exception/expected.txt
@@ -0,0 +1,236 @@
+Test "art.Test1928$DoThrowClass": Running with handler "art.Test1928$DoNothingHandler"
+main: public static void art.Test1928.doThrow() @ line = 110 throws class art.Test1928$TestException: doThrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1928.PrintStack() @ line = 35
+		public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
+		public static void art.Test1928.doThrow() @ line = 110
+		public void art.Test1928$DoThrowClass.run() @ line = 114
+		public static void art.Test1928.run() throws java.lang.Exception @ line = 196
+	Will be caught by: public static void art.Test1928.run() throws java.lang.Exception @ line = 199
+exception is: art.Test1928$TestException: doThrow
+	at art.Test1928.doThrow(Test1928.java:110)
+	at art.Test1928$DoThrowClass.run(Test1928.java:114)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+	Doing nothing!
+Test "art.Test1928$DoThrowClass": Caught error art.Test1928$TestException:"doThrow" with handler "art.Test1928$DoNothingHandler"
+art.Test1928$TestException: doThrow
+	at art.Test1928.doThrow(Test1928.java:110)
+	at art.Test1928$DoThrowClass.run(Test1928.java:114)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Test "art.Test1928$DoThrowClass": Finished running with handler "art.Test1928$DoNothingHandler"
+Test "art.Test1928$DoThrowCatchBaseTestException": Running with handler "art.Test1928$DoNothingHandler"
+main: public static void art.Test1928.throwCatchBaseTestException() @ line = 119 throws class art.Test1928$TestException: throwCatchBaseTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1928.PrintStack() @ line = 35
+		public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
+		public static void art.Test1928.throwCatchBaseTestException() @ line = 119
+		public void art.Test1928$DoThrowCatchBaseTestException.run() @ line = 129
+		public static void art.Test1928.run() throws java.lang.Exception @ line = 196
+	Will be caught by: public static void art.Test1928.throwCatchBaseTestException() @ line = 120
+exception is: art.Test1928$TestException: throwCatchBaseTestException
+	at art.Test1928.throwCatchBaseTestException(Test1928.java:119)
+	at art.Test1928$DoThrowCatchBaseTestException.run(Test1928.java:129)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+	Doing nothing!
+Caught art.Test1928$TestException: "throwCatchBaseTestException"
+art.Test1928$TestException: throwCatchBaseTestException
+	at art.Test1928.throwCatchBaseTestException(Test1928.java:119)
+	at art.Test1928$DoThrowCatchBaseTestException.run(Test1928.java:129)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Test "art.Test1928$DoThrowCatchBaseTestException": No error caught with handler "art.Test1928$DoNothingHandler"
+Test "art.Test1928$DoThrowCatchBaseTestException": Finished running with handler "art.Test1928$DoNothingHandler"
+Test "art.Test1928$DoThrowCatchTestException": Running with handler "art.Test1928$DoNothingHandler"
+main: public static void art.Test1928.throwCatchTestException() @ line = 134 throws class art.Test1928$TestException: throwCatchTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1928.PrintStack() @ line = 35
+		public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
+		public static void art.Test1928.throwCatchTestException() @ line = 134
+		public void art.Test1928$DoThrowCatchTestException.run() @ line = 144
+		public static void art.Test1928.run() throws java.lang.Exception @ line = 196
+	Will be caught by: public static void art.Test1928.throwCatchTestException() @ line = 135
+exception is: art.Test1928$TestException: throwCatchTestException
+	at art.Test1928.throwCatchTestException(Test1928.java:134)
+	at art.Test1928$DoThrowCatchTestException.run(Test1928.java:144)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+	Doing nothing!
+Caught art.Test1928$TestException: "throwCatchTestException"
+art.Test1928$TestException: throwCatchTestException
+	at art.Test1928.throwCatchTestException(Test1928.java:134)
+	at art.Test1928$DoThrowCatchTestException.run(Test1928.java:144)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Test "art.Test1928$DoThrowCatchTestException": No error caught with handler "art.Test1928$DoNothingHandler"
+Test "art.Test1928$DoThrowCatchTestException": Finished running with handler "art.Test1928$DoNothingHandler"
+Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Running with handler "art.Test1928$DoNothingHandler"
+main: public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149 throws class art.Test1928$TestException: throwCatchTestExceptionNoRethrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1928.PrintStack() @ line = 35
+		public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
+		public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149
+		public void art.Test1928$DoThrowCatchTestExceptionNoRethrow.run() @ line = 159
+		public static void art.Test1928.run() throws java.lang.Exception @ line = 196
+	Will be caught by: public static void art.Test1928.run() throws java.lang.Exception @ line = 199
+exception is: art.Test1928$TestException: throwCatchTestExceptionNoRethrow
+	at art.Test1928.throwCatchTestExceptionNoRethrow(Test1928.java:149)
+	at art.Test1928$DoThrowCatchTestExceptionNoRethrow.run(Test1928.java:159)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+	Doing nothing!
+Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1928$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1928$DoNothingHandler"
+art.Test1928$TestException: throwCatchTestExceptionNoRethrow
+	at art.Test1928.throwCatchTestExceptionNoRethrow(Test1928.java:149)
+	at art.Test1928$DoThrowCatchTestExceptionNoRethrow.run(Test1928.java:159)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1928$DoNothingHandler"
+Test "art.Test1928$DoThrowClass": Running with handler "art.Test1928$ThrowCatchBase"
+main: public static void art.Test1928.doThrow() @ line = 110 throws class art.Test1928$TestException: doThrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1928.PrintStack() @ line = 35
+		public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
+		public static void art.Test1928.doThrow() @ line = 110
+		public void art.Test1928$DoThrowClass.run() @ line = 114
+		public static void art.Test1928.run() throws java.lang.Exception @ line = 196
+	Will be caught by: public static void art.Test1928.run() throws java.lang.Exception @ line = 199
+exception is: art.Test1928$TestException: doThrow
+	at art.Test1928.doThrow(Test1928.java:110)
+	at art.Test1928$DoThrowClass.run(Test1928.java:114)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+	Throwing BaseTestException and catching it!
+Caught art.Test1928$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1928.doThrow() @ line = 110"
+art.Test1928$BaseTestException: ThrowBaseHandler during throw from public static void art.Test1928.doThrow() @ line = 110
+	at art.Test1928$ThrowCatchBase.exceptionOccurred(Test1928.java:99)
+	at art.Test1928.ExceptionEvent(Test1928.java:66)
+	at art.Test1928.doThrow(Test1928.java:110)
+	at art.Test1928$DoThrowClass.run(Test1928.java:114)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Caused by: art.Test1928$TestException: doThrow
+	... 4 more
+Test "art.Test1928$DoThrowClass": Caught error art.Test1928$TestException:"doThrow" with handler "art.Test1928$ThrowCatchBase"
+art.Test1928$TestException: doThrow
+	at art.Test1928.doThrow(Test1928.java:110)
+	at art.Test1928$DoThrowClass.run(Test1928.java:114)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Test "art.Test1928$DoThrowClass": Finished running with handler "art.Test1928$ThrowCatchBase"
+Test "art.Test1928$DoThrowCatchBaseTestException": Running with handler "art.Test1928$ThrowCatchBase"
+main: public static void art.Test1928.throwCatchBaseTestException() @ line = 119 throws class art.Test1928$TestException: throwCatchBaseTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1928.PrintStack() @ line = 35
+		public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
+		public static void art.Test1928.throwCatchBaseTestException() @ line = 119
+		public void art.Test1928$DoThrowCatchBaseTestException.run() @ line = 129
+		public static void art.Test1928.run() throws java.lang.Exception @ line = 196
+	Will be caught by: public static void art.Test1928.throwCatchBaseTestException() @ line = 120
+exception is: art.Test1928$TestException: throwCatchBaseTestException
+	at art.Test1928.throwCatchBaseTestException(Test1928.java:119)
+	at art.Test1928$DoThrowCatchBaseTestException.run(Test1928.java:129)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+	Throwing BaseTestException and catching it!
+Caught art.Test1928$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1928.throwCatchBaseTestException() @ line = 119"
+art.Test1928$BaseTestException: ThrowBaseHandler during throw from public static void art.Test1928.throwCatchBaseTestException() @ line = 119
+	at art.Test1928$ThrowCatchBase.exceptionOccurred(Test1928.java:99)
+	at art.Test1928.ExceptionEvent(Test1928.java:66)
+	at art.Test1928.throwCatchBaseTestException(Test1928.java:119)
+	at art.Test1928$DoThrowCatchBaseTestException.run(Test1928.java:129)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Caused by: art.Test1928$TestException: throwCatchBaseTestException
+	... 4 more
+Caught art.Test1928$TestException: "throwCatchBaseTestException"
+art.Test1928$TestException: throwCatchBaseTestException
+	at art.Test1928.throwCatchBaseTestException(Test1928.java:119)
+	at art.Test1928$DoThrowCatchBaseTestException.run(Test1928.java:129)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Test "art.Test1928$DoThrowCatchBaseTestException": No error caught with handler "art.Test1928$ThrowCatchBase"
+Test "art.Test1928$DoThrowCatchBaseTestException": Finished running with handler "art.Test1928$ThrowCatchBase"
+Test "art.Test1928$DoThrowCatchTestException": Running with handler "art.Test1928$ThrowCatchBase"
+main: public static void art.Test1928.throwCatchTestException() @ line = 134 throws class art.Test1928$TestException: throwCatchTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1928.PrintStack() @ line = 35
+		public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
+		public static void art.Test1928.throwCatchTestException() @ line = 134
+		public void art.Test1928$DoThrowCatchTestException.run() @ line = 144
+		public static void art.Test1928.run() throws java.lang.Exception @ line = 196
+	Will be caught by: public static void art.Test1928.throwCatchTestException() @ line = 135
+exception is: art.Test1928$TestException: throwCatchTestException
+	at art.Test1928.throwCatchTestException(Test1928.java:134)
+	at art.Test1928$DoThrowCatchTestException.run(Test1928.java:144)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+	Throwing BaseTestException and catching it!
+Caught art.Test1928$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1928.throwCatchTestException() @ line = 134"
+art.Test1928$BaseTestException: ThrowBaseHandler during throw from public static void art.Test1928.throwCatchTestException() @ line = 134
+	at art.Test1928$ThrowCatchBase.exceptionOccurred(Test1928.java:99)
+	at art.Test1928.ExceptionEvent(Test1928.java:66)
+	at art.Test1928.throwCatchTestException(Test1928.java:134)
+	at art.Test1928$DoThrowCatchTestException.run(Test1928.java:144)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Caused by: art.Test1928$TestException: throwCatchTestException
+	... 4 more
+Caught art.Test1928$TestException: "throwCatchTestException"
+art.Test1928$TestException: throwCatchTestException
+	at art.Test1928.throwCatchTestException(Test1928.java:134)
+	at art.Test1928$DoThrowCatchTestException.run(Test1928.java:144)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Test "art.Test1928$DoThrowCatchTestException": No error caught with handler "art.Test1928$ThrowCatchBase"
+Test "art.Test1928$DoThrowCatchTestException": Finished running with handler "art.Test1928$ThrowCatchBase"
+Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Running with handler "art.Test1928$ThrowCatchBase"
+main: public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149 throws class art.Test1928$TestException: throwCatchTestExceptionNoRethrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1928.PrintStack() @ line = 35
+		public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
+		public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149
+		public void art.Test1928$DoThrowCatchTestExceptionNoRethrow.run() @ line = 159
+		public static void art.Test1928.run() throws java.lang.Exception @ line = 196
+	Will be caught by: public static void art.Test1928.run() throws java.lang.Exception @ line = 199
+exception is: art.Test1928$TestException: throwCatchTestExceptionNoRethrow
+	at art.Test1928.throwCatchTestExceptionNoRethrow(Test1928.java:149)
+	at art.Test1928$DoThrowCatchTestExceptionNoRethrow.run(Test1928.java:159)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+	Throwing BaseTestException and catching it!
+Caught art.Test1928$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149"
+art.Test1928$BaseTestException: ThrowBaseHandler during throw from public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149
+	at art.Test1928$ThrowCatchBase.exceptionOccurred(Test1928.java:99)
+	at art.Test1928.ExceptionEvent(Test1928.java:66)
+	at art.Test1928.throwCatchTestExceptionNoRethrow(Test1928.java:149)
+	at art.Test1928$DoThrowCatchTestExceptionNoRethrow.run(Test1928.java:159)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Caused by: art.Test1928$TestException: throwCatchTestExceptionNoRethrow
+	... 4 more
+Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1928$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1928$ThrowCatchBase"
+art.Test1928$TestException: throwCatchTestExceptionNoRethrow
+	at art.Test1928.throwCatchTestExceptionNoRethrow(Test1928.java:149)
+	at art.Test1928$DoThrowCatchTestExceptionNoRethrow.run(Test1928.java:159)
+	at art.Test1928.run(Test1928.java:196)
+	at Main.main(Main.java:19)
+Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1928$ThrowCatchBase"
diff --git a/test/1928-exception-event-exception/info.txt b/test/1928-exception-event-exception/info.txt
new file mode 100644
index 0000000..ef84746
--- /dev/null
+++ b/test/1928-exception-event-exception/info.txt
@@ -0,0 +1,5 @@
+Test basic JVMTI exception event functionality.
+
+Ensures we can throw exceptions during the exception event without causing
+problems. Note that we do not allow exceptions to propogate past the event,
+matching RI behavior. See b/65049545.
diff --git a/test/1928-exception-event-exception/run b/test/1928-exception-event-exception/run
new file mode 100755
index 0000000..51875a7
--- /dev/null
+++ b/test/1928-exception-event-exception/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Ask for stack traces to be dumped to a file rather than to stdout.
+./default-run "$@" --jvmti
diff --git a/test/1928-exception-event-exception/src/Main.java b/test/1928-exception-event-exception/src/Main.java
new file mode 100644
index 0000000..11cc773
--- /dev/null
+++ b/test/1928-exception-event-exception/src/Main.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+  public static void main(String[] args) throws Exception {
+    art.Test1928.run();
+  }
+}
diff --git a/test/1928-exception-event-exception/src/art/Breakpoint.java b/test/1928-exception-event-exception/src/art/Breakpoint.java
new file mode 100644
index 0000000..bbb89f7
--- /dev/null
+++ b/test/1928-exception-event-exception/src/art/Breakpoint.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Executable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Objects;
+
+public class Breakpoint {
+  public static class Manager {
+    public static class BP {
+      public final Executable method;
+      public final long location;
+
+      public BP(Executable method) {
+        this(method, getStartLocation(method));
+      }
+
+      public BP(Executable method, long location) {
+        this.method = method;
+        this.location = location;
+      }
+
+      @Override
+      public boolean equals(Object other) {
+        return (other instanceof BP) &&
+            method.equals(((BP)other).method) &&
+            location == ((BP)other).location;
+      }
+
+      @Override
+      public String toString() {
+        return method.toString() + " @ " + getLine();
+      }
+
+      @Override
+      public int hashCode() {
+        return Objects.hash(method, location);
+      }
+
+      public int getLine() {
+        try {
+          LineNumber[] lines = getLineNumberTable(method);
+          int best = -1;
+          for (LineNumber l : lines) {
+            if (l.location > location) {
+              break;
+            } else {
+              best = l.line;
+            }
+          }
+          return best;
+        } catch (Exception e) {
+          return -1;
+        }
+      }
+    }
+
+    private Set<BP> breaks = new HashSet<>();
+
+    public void setBreakpoints(BP... bs) {
+      for (BP b : bs) {
+        if (breaks.add(b)) {
+          Breakpoint.setBreakpoint(b.method, b.location);
+        }
+      }
+    }
+    public void setBreakpoint(Executable method, long location) {
+      setBreakpoints(new BP(method, location));
+    }
+
+    public void clearBreakpoints(BP... bs) {
+      for (BP b : bs) {
+        if (breaks.remove(b)) {
+          Breakpoint.clearBreakpoint(b.method, b.location);
+        }
+      }
+    }
+    public void clearBreakpoint(Executable method, long location) {
+      clearBreakpoints(new BP(method, location));
+    }
+
+    public void clearAllBreakpoints() {
+      clearBreakpoints(breaks.toArray(new BP[0]));
+    }
+  }
+
+  public static void startBreakpointWatch(Class<?> methodClass,
+                                          Executable breakpointReached,
+                                          Thread thr) {
+    startBreakpointWatch(methodClass, breakpointReached, false, thr);
+  }
+
+  /**
+   * Enables the trapping of breakpoint events.
+   *
+   * If allowRecursive == true then breakpoints will be sent even if one is currently being handled.
+   */
+  public static native void startBreakpointWatch(Class<?> methodClass,
+                                                 Executable breakpointReached,
+                                                 boolean allowRecursive,
+                                                 Thread thr);
+  public static native void stopBreakpointWatch(Thread thr);
+
+  public static final class LineNumber implements Comparable<LineNumber> {
+    public final long location;
+    public final int line;
+
+    private LineNumber(long loc, int line) {
+      this.location = loc;
+      this.line = line;
+    }
+
+    public boolean equals(Object other) {
+      return other instanceof LineNumber && ((LineNumber)other).line == line &&
+          ((LineNumber)other).location == location;
+    }
+
+    public int compareTo(LineNumber other) {
+      int v = Integer.valueOf(line).compareTo(Integer.valueOf(other.line));
+      if (v != 0) {
+        return v;
+      } else {
+        return Long.valueOf(location).compareTo(Long.valueOf(other.location));
+      }
+    }
+  }
+
+  public static native void setBreakpoint(Executable m, long loc);
+  public static void setBreakpoint(Executable m, LineNumber l) {
+    setBreakpoint(m, l.location);
+  }
+
+  public static native void clearBreakpoint(Executable m, long loc);
+  public static void clearBreakpoint(Executable m, LineNumber l) {
+    clearBreakpoint(m, l.location);
+  }
+
+  private static native Object[] getLineNumberTableNative(Executable m);
+  public static LineNumber[] getLineNumberTable(Executable m) {
+    Object[] nativeTable = getLineNumberTableNative(m);
+    long[] location = (long[])(nativeTable[0]);
+    int[] lines = (int[])(nativeTable[1]);
+    if (lines.length != location.length) {
+      throw new Error("Lines and locations have different lengths!");
+    }
+    LineNumber[] out = new LineNumber[lines.length];
+    for (int i = 0; i < lines.length; i++) {
+      out[i] = new LineNumber(location[i], lines[i]);
+    }
+    return out;
+  }
+
+  public static native long getStartLocation(Executable m);
+
+  public static int locationToLine(Executable m, long location) {
+    try {
+      Breakpoint.LineNumber[] lines = Breakpoint.getLineNumberTable(m);
+      int best = -1;
+      for (Breakpoint.LineNumber l : lines) {
+        if (l.location > location) {
+          break;
+        } else {
+          best = l.line;
+        }
+      }
+      return best;
+    } catch (Exception e) {
+      return -1;
+    }
+  }
+
+  public static long lineToLocation(Executable m, int line) throws Exception {
+    try {
+      Breakpoint.LineNumber[] lines = Breakpoint.getLineNumberTable(m);
+      for (Breakpoint.LineNumber l : lines) {
+        if (l.line == line) {
+          return l.location;
+        }
+      }
+      throw new Exception("Unable to find line " + line + " in " + m);
+    } catch (Exception e) {
+      throw new Exception("Unable to get line number info for " + m, e);
+    }
+  }
+}
+
diff --git a/test/1928-exception-event-exception/src/art/Exceptions.java b/test/1928-exception-event-exception/src/art/Exceptions.java
new file mode 100644
index 0000000..2c959ec
--- /dev/null
+++ b/test/1928-exception-event-exception/src/art/Exceptions.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class Exceptions {
+  public static native void setupExceptionTracing(
+      Class<?> methodClass,
+      Class<?> exceptionClass,
+      Method exceptionEventMethod,
+      Method exceptionCaughtEventMethod);
+
+  public static native void enableExceptionCatchEvent(Thread thr);
+  public static native void enableExceptionEvent(Thread thr);
+  public static native void disableExceptionCatchEvent(Thread thr);
+  public static native void disableExceptionEvent(Thread thr);
+}
diff --git a/test/1928-exception-event-exception/src/art/StackTrace.java b/test/1928-exception-event-exception/src/art/StackTrace.java
new file mode 100644
index 0000000..b12c3df
--- /dev/null
+++ b/test/1928-exception-event-exception/src/art/StackTrace.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
+
+public class StackTrace {
+  public static class StackFrameData {
+    public final Thread thr;
+    public final Executable method;
+    public final long current_location;
+    public final int depth;
+
+    public StackFrameData(Thread thr, Executable e, long loc, int depth) {
+      this.thr = thr;
+      this.method = e;
+      this.current_location = loc;
+      this.depth = depth;
+    }
+    @Override
+    public String toString() {
+      return String.format(
+          "StackFrameData { thr: '%s', method: '%s', loc: %d, depth: %d }",
+          this.thr,
+          this.method,
+          this.current_location,
+          this.depth);
+    }
+  }
+
+  public static native int GetStackDepth(Thread thr);
+
+  private static native StackFrameData[] nativeGetStackTrace(Thread thr);
+
+  public static StackFrameData[] GetStackTrace(Thread thr) {
+    // The RI seems to give inconsistent (and sometimes nonsensical) results if the thread is not
+    // suspended. The spec says that not being suspended is fine but since we want this to be
+    // consistent we will suspend for the RI.
+    boolean suspend_thread =
+        !System.getProperty("java.vm.name").equals("Dalvik") &&
+        !thr.equals(Thread.currentThread());
+    if (suspend_thread) {
+      Suspension.suspend(thr);
+    }
+    StackFrameData[] out = nativeGetStackTrace(thr);
+    if (suspend_thread) {
+      Suspension.resume(thr);
+    }
+    return out;
+  }
+}
+
diff --git a/test/1928-exception-event-exception/src/art/Suspension.java b/test/1928-exception-event-exception/src/art/Suspension.java
new file mode 100644
index 0000000..16e62cc
--- /dev/null
+++ b/test/1928-exception-event-exception/src/art/Suspension.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+public class Suspension {
+  // Suspends a thread using jvmti.
+  public native static void suspend(Thread thr);
+
+  // Resumes a thread using jvmti.
+  public native static void resume(Thread thr);
+
+  public native static boolean isSuspended(Thread thr);
+
+  public native static int[] suspendList(Thread... threads);
+  public native static int[] resumeList(Thread... threads);
+}
diff --git a/test/1928-exception-event-exception/src/art/Test1928.java b/test/1928-exception-event-exception/src/art/Test1928.java
new file mode 100644
index 0000000..aec88a4
--- /dev/null
+++ b/test/1928-exception-event-exception/src/art/Test1928.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+
+public class Test1928 {
+  public static boolean PRINT_FULL_EXCEPTION = true;
+  public static ExceptionHandler HANDLER = null;
+
+  public static interface ExceptionHandler {
+    public void exceptionOccurred(
+        Executable m, long loc, Throwable exception, Executable catch_m, long catch_l);
+  }
+
+  private static void PrintStack() {
+    System.out.println("\tCurrent Stack:");
+    for (StackTrace.StackFrameData e : StackTrace.GetStackTrace(Thread.currentThread())) {
+      if (Objects.equals(e.method.getDeclaringClass().getPackage(), Test1928.class.getPackage())) {
+        System.out.println("\t\t" + e.method + " @ line = " +
+            Breakpoint.locationToLine(e.method, e.current_location));
+      }
+    }
+  }
+
+  public static void ExceptionEvent(Thread thr,
+                                    Executable throw_method,
+                                    long throw_location,
+                                    Throwable exception,
+                                    Executable catch_method,
+                                    long catch_location) {
+    System.out.println(thr.getName() + ": " + throw_method + " @ line = " +
+        Breakpoint.locationToLine(throw_method, throw_location) + " throws " +
+        exception.getClass() + ": " + exception.getMessage());
+    String catch_message;
+    if (catch_method == null) {
+      catch_message = "<UNKNOWN>";
+    } else {
+      catch_message = catch_method.toString() + " @ line = " +
+          Breakpoint.locationToLine(catch_method, catch_location);
+    }
+    PrintStack();
+    System.out.println("\tWill be caught by: " + catch_message);
+    if (PRINT_FULL_EXCEPTION) {
+      System.out.print("exception is: ");
+      exception.printStackTrace(System.out);
+    }
+    if (HANDLER != null) {
+      HANDLER.exceptionOccurred(
+          throw_method, throw_location, exception, catch_method, catch_location);
+    }
+  }
+
+  public static class BaseTestException extends Error {
+    public BaseTestException(String e) { super(e); }
+    public BaseTestException(String e, Throwable t) { super(e, t); }
+  }
+  public static class TestException extends BaseTestException {
+    public TestException(String e) { super(e); }
+    public TestException(String e, Throwable t) { super(e, t); }
+  }
+
+  public static class TestExceptionNoRethrow extends TestException {
+    public TestExceptionNoRethrow(String e) { super(e); }
+    public TestExceptionNoRethrow(String e, Throwable t) { super(e, t); }
+  }
+
+  public static class DoNothingHandler implements ExceptionHandler {
+    public void exceptionOccurred(
+        Executable m, long loc, Throwable exception, Executable catch_m, long catch_l) {
+      System.out.println("\tDoing nothing!");
+      return;
+    }
+  }
+
+  public static class ThrowCatchBase implements ExceptionHandler {
+    public void exceptionOccurred(
+        Executable m, long loc, Throwable exception, Executable catch_m, long catch_l) {
+      System.out.println("\tThrowing BaseTestException and catching it!");
+      try {
+        throw new BaseTestException("ThrowBaseHandler during throw from " + m + " @ line = " +
+            Breakpoint.locationToLine(m, loc), exception);
+      } catch (BaseTestException t) {
+        System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+        if (PRINT_FULL_EXCEPTION) {
+          t.printStackTrace(System.out);
+        }
+      }
+    }
+  }
+
+  public static void doThrow() {
+    throw new TestException("doThrow");
+  }
+
+  public static class DoThrowClass implements Runnable {
+    public void run() { doThrow(); }
+  }
+
+  public static void throwCatchBaseTestException() {
+    try {
+      throw new TestException("throwCatchBaseTestException");
+    } catch (BaseTestException t) {
+      System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+      if (PRINT_FULL_EXCEPTION) {
+        t.printStackTrace(System.out);
+      }
+    }
+  }
+
+  public static class DoThrowCatchBaseTestException implements Runnable {
+    public void run() { throwCatchBaseTestException(); }
+  }
+
+  public static void throwCatchTestException() {
+    try {
+      throw new TestException("throwCatchTestException");
+    } catch (TestException t) {
+      System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+      if (PRINT_FULL_EXCEPTION) {
+        t.printStackTrace(System.out);
+      }
+    }
+  }
+
+  public static class DoThrowCatchTestException implements Runnable {
+    public void run() { throwCatchTestException(); }
+  }
+
+  public static void throwCatchTestExceptionNoRethrow() {
+    try {
+      throw new TestException("throwCatchTestExceptionNoRethrow");
+    } catch (TestExceptionNoRethrow t) {
+      System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+      if (PRINT_FULL_EXCEPTION) {
+        t.printStackTrace(System.out);
+      }
+    }
+  }
+
+  public static class DoThrowCatchTestExceptionNoRethrow implements Runnable {
+    public void run() { throwCatchTestExceptionNoRethrow(); }
+  }
+
+  public static void run() throws Exception {
+    // Set up
+    Exceptions.setupExceptionTracing(
+        Test1928.class,
+        TestException.class,
+        Test1928.class.getDeclaredMethod(
+            "ExceptionEvent",
+            Thread.class,
+            Executable.class,
+            Long.TYPE,
+            Throwable.class,
+            Executable.class,
+            Long.TYPE),
+        null);
+    Exceptions.enableExceptionEvent(Thread.currentThread());
+
+    ExceptionHandler[] handlers = new ExceptionHandler[] {
+      new DoNothingHandler(),
+      new ThrowCatchBase(),
+    };
+
+    Runnable[] tests = new Runnable[] {
+      new DoThrowClass(),
+      new DoThrowCatchBaseTestException(),
+      new DoThrowCatchTestException(),
+      new DoThrowCatchTestExceptionNoRethrow(),
+    };
+
+    for (ExceptionHandler handler : handlers) {
+      for (Runnable test : tests) {
+        try {
+          HANDLER = handler;
+          System.out.printf("Test \"%s\": Running with handler \"%s\"\n",
+              test.getClass().getName(), handler.getClass().getName());
+          test.run();
+          System.out.printf("Test \"%s\": No error caught with handler \"%s\"\n",
+              test.getClass().getName(), handler.getClass().getName());
+        } catch (Throwable e) {
+          System.out.printf("Test \"%s\": Caught error %s:\"%s\" with handler \"%s\"\n",
+              test.getClass().getName(),
+              e.getClass().getName(),
+              e.getMessage(),
+              handler.getClass().getName());
+          if (PRINT_FULL_EXCEPTION) {
+            e.printStackTrace(System.out);
+          }
+        }
+        System.out.printf("Test \"%s\": Finished running with handler \"%s\"\n",
+            test.getClass().getName(), handler.getClass().getName());
+        HANDLER = null;
+      }
+    }
+    Exceptions.disableExceptionEvent(Thread.currentThread());
+  }
+}
diff --git a/test/1929-exception-catch-exception/expected.txt b/test/1929-exception-catch-exception/expected.txt
new file mode 100644
index 0000000..7c23a31
--- /dev/null
+++ b/test/1929-exception-catch-exception/expected.txt
@@ -0,0 +1,302 @@
+Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$DoNothingHandler"
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+Test "art.Test1929$DoThrowClass": Caught error art.Test1929$TestException:"doThrow" with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowClass": Finished running with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handler "art.Test1929$DoNothingHandler"
+main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140 caught class art.Test1929$TestException: throwCatchBaseTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.throwCatchBaseTestException() @ line = 140
+		public void art.Test1929$DoThrowCatchBaseTestException.run() @ line = 149
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+	Doing nothing!
+Caught art.Test1929$TestException: "throwCatchBaseTestException"
+Test "art.Test1929$DoThrowCatchBaseTestException": No error caught with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowCatchBaseTestException": Finished running with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with handler "art.Test1929$DoNothingHandler"
+main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
+		public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 197
+		public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 201
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+Caught art.Test1929$TestException: "throwCatchBaseTestExceptionTwice"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": No error caught with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Finished running with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "art.Test1929$DoNothingHandler"
+main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.throwCatchTestException() @ line = 207
+		public void art.Test1929$DoThrowCatchTestException.run() @ line = 216
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+	Doing nothing!
+Caught art.Test1929$TestException: "throwCatchTestException"
+Test "art.Test1929$DoThrowCatchTestException": No error caught with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowCatchTestException": Finished running with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with handler "art.Test1929$DoNothingHandler"
+main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
+		public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 222
+		public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 226
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+Caught art.Test1929$TestException: "throwCatchTestExceptionTwice"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": No error caught with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": Finished running with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with handler "art.Test1929$DoNothingHandler"
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1929$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1929$DoNothingHandler"
+Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+Test "art.Test1929$DoThrowClass": Caught error art.Test1929$TestException:"doThrow" with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowClass": Finished running with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
+main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140 caught class art.Test1929$TestException: throwCatchBaseTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.throwCatchBaseTestException() @ line = 140
+		public void art.Test1929$DoThrowCatchBaseTestException.run() @ line = 149
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+	Throwing BaseTestException and catching it!
+Caught art.Test1929$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1929.throwCatchBaseTestException() @ line = 140"
+Caught art.Test1929$TestException: "throwCatchBaseTestException"
+Test "art.Test1929$DoThrowCatchBaseTestException": No error caught with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowCatchBaseTestException": Finished running with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
+main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
+		public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 197
+		public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 201
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+Caught art.Test1929$TestException: "throwCatchBaseTestExceptionTwice"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": No error caught with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Finished running with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
+main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.throwCatchTestException() @ line = 207
+		public void art.Test1929$DoThrowCatchTestException.run() @ line = 216
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+	Throwing BaseTestException and catching it!
+Caught art.Test1929$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1929.throwCatchTestException() @ line = 207"
+Caught art.Test1929$TestException: "throwCatchTestException"
+Test "art.Test1929$DoThrowCatchTestException": No error caught with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowCatchTestException": Finished running with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
+main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
+		public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 222
+		public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 226
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+Caught art.Test1929$TestException: "throwCatchTestExceptionTwice"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": No error caught with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": Finished running with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1929$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1929$ThrowCatchBase"
+Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+Test "art.Test1929$DoThrowClass": Caught error art.Test1929$TestException:"doThrow" with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowClass": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140 caught class art.Test1929$TestException: throwCatchBaseTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.throwCatchBaseTestException() @ line = 140
+		public void art.Test1929$DoThrowCatchBaseTestException.run() @ line = 149
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+	Throwing BaseTestException!
+Test "art.Test1929$DoThrowCatchBaseTestException": Caught error art.Test1929$BaseTestException:"ThrowBaseHandler during throw from public static void art.Test1929.throwCatchBaseTestException() @ line = 140" with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchBaseTestException": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
+		public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 197
+		public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 201
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+Caught art.Test1929$TestException: "throwCatchBaseTestExceptionTwice"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": No error caught with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.throwCatchTestException() @ line = 207
+		public void art.Test1929$DoThrowCatchTestException.run() @ line = 216
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+	Throwing BaseTestException!
+Test "art.Test1929$DoThrowCatchTestException": Caught error art.Test1929$BaseTestException:"ThrowBaseHandler during throw from public static void art.Test1929.throwCatchTestException() @ line = 207" with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchTestException": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
+		public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 222
+		public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 226
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+Caught art.Test1929$TestException: "throwCatchTestExceptionTwice"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": No error caught with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1929$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+Test "art.Test1929$DoThrowClass": Caught error art.Test1929$TestException:"doThrow" with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowClass": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140 caught class art.Test1929$TestException: throwCatchBaseTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.throwCatchBaseTestException() @ line = 140
+		public void art.Test1929$DoThrowCatchBaseTestException.run() @ line = 149
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+	Throwing TestExceptionNoRethrow!
+Test "art.Test1929$DoThrowCatchBaseTestException": Caught error art.Test1929$TestExceptionNoRethrow:"ThrowTestExceptionNoRethrowHandler during throw from public static void art.Test1929.throwCatchBaseTestException() @ line = 140" with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchBaseTestException": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
+		public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 197
+		public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 201
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+Caught art.Test1929$TestException: "throwCatchBaseTestExceptionTwice"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": No error caught with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.throwCatchTestException() @ line = 207
+		public void art.Test1929$DoThrowCatchTestException.run() @ line = 216
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+	Throwing TestExceptionNoRethrow!
+Test "art.Test1929$DoThrowCatchTestException": Caught error art.Test1929$TestExceptionNoRethrow:"ThrowTestExceptionNoRethrowHandler during throw from public static void art.Test1929.throwCatchTestException() @ line = 207" with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchTestException": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
+		public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 222
+		public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 226
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+Caught art.Test1929$TestException: "throwCatchTestExceptionTwice"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": No error caught with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionTwice": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
+	Current Stack:
+		private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
+		public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+		private static void art.Test1929.PrintStack() @ line = 52
+		public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
+		public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1929$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
diff --git a/test/1929-exception-catch-exception/info.txt b/test/1929-exception-catch-exception/info.txt
new file mode 100644
index 0000000..2d9b3a0
--- /dev/null
+++ b/test/1929-exception-catch-exception/info.txt
@@ -0,0 +1 @@
+Test JVMTI behavior when throwing exceptions during the Exception catch Event.
diff --git a/test/1929-exception-catch-exception/run b/test/1929-exception-catch-exception/run
new file mode 100755
index 0000000..51875a7
--- /dev/null
+++ b/test/1929-exception-catch-exception/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Ask for stack traces to be dumped to a file rather than to stdout.
+./default-run "$@" --jvmti
diff --git a/test/1929-exception-catch-exception/smali/art/Test1929$Impl.smali b/test/1929-exception-catch-exception/smali/art/Test1929$Impl.smali
new file mode 100644
index 0000000..4edd56f
--- /dev/null
+++ b/test/1929-exception-catch-exception/smali/art/Test1929$Impl.smali
@@ -0,0 +1,363 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# The standard dx/jack/d8 all would leave the move-exception instructions outside of either catch
+# block. This is different from the RI which will leave the corresponding aload.
+#
+# See b/65203529 for more information.
+
+.class public final Lart/Test1929$Impl;
+.super Ljava/lang/Object;
+.source "Test1929.java"
+
+
+# annotations
+.annotation system Ldalvik/annotation/EnclosingClass;
+    value = Lart/Test1929;
+.end annotation
+
+.annotation system Ldalvik/annotation/InnerClass;
+    accessFlags = 0x19
+    name = "Impl"
+.end annotation
+
+
+# direct methods
+.method private constructor <init>()V
+    .registers 1
+
+    .prologue
+    .line 152
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+    return-void
+.end method
+
+.method public static throwCatchBaseTestExceptionTwiceImpl()V
+    .registers 4
+
+    .prologue
+    .line 156
+    :try_start_0
+    new-instance v1, Lart/Test1929$TestException;
+
+    const-string v2, "throwCatchBaseTestExceptionTwice"
+
+    invoke-direct {v1, v2}, Lart/Test1929$TestException;-><init>(Ljava/lang/String;)V
+
+    throw v1
+    :try_end_8
+    .catch Lart/Test1929$BaseTestException; {:try_start_0 .. :try_end_8} :catch_8
+
+    .line 157
+    :catch_8
+    # This try needs to include the move-exception
+    :try_start_9
+    move-exception v0
+
+    .line 158
+    .local v0, "t":Lart/Test1929$BaseTestException;
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+    new-instance v2, Ljava/lang/StringBuilder;
+
+    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V
+
+    const-string v3, "Caught "
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
+
+    move-result-object v3
+
+    invoke-virtual {v3}, Ljava/lang/Class;->getName()Ljava/lang/String;
+
+    move-result-object v3
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    const-string v3, ": \""
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v0}, Lart/Test1929$BaseTestException;->getMessage()Ljava/lang/String;
+
+    move-result-object v3
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    const-string v3, "\""
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
+
+    move-result-object v2
+
+    invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
+
+    .line 159
+    sget-boolean v1, Lart/Test1929;->PRINT_FULL_EXCEPTION:Z
+
+    if-eqz v1, :cond_46
+
+    .line 160
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+    invoke-virtual {v0, v1}, Lart/Test1929$BaseTestException;->printStackTrace(Ljava/io/PrintStream;)V
+    :try_end_46
+    .catch Lart/Test1929$BaseTestException; {:try_start_9 .. :try_end_46} :catch_47
+
+    .line 169
+    :cond_46
+    :goto_46
+    return-void
+
+    .line 163
+    :catch_47
+    move-exception v0
+
+    .line 164
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+    new-instance v2, Ljava/lang/StringBuilder;
+
+    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V
+
+    const-string v3, "2nd Caught "
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
+
+    move-result-object v3
+
+    invoke-virtual {v3}, Ljava/lang/Class;->getName()Ljava/lang/String;
+
+    move-result-object v3
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    const-string v3, ": \""
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v0}, Lart/Test1929$BaseTestException;->getMessage()Ljava/lang/String;
+
+    move-result-object v3
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    const-string v3, "\""
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
+
+    move-result-object v2
+
+    invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
+
+    .line 165
+    sget-boolean v1, Lart/Test1929;->PRINT_FULL_EXCEPTION:Z
+
+    if-eqz v1, :cond_46
+
+    .line 166
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+    invoke-virtual {v0, v1}, Lart/Test1929$BaseTestException;->printStackTrace(Ljava/io/PrintStream;)V
+
+    goto :goto_46
+.end method
+
+.method public static throwCatchTestExceptionTwiceImpl()V
+    .registers 4
+
+    .prologue
+    .line 174
+    :try_start_0
+    new-instance v1, Lart/Test1929$TestException;
+
+    const-string v2, "throwCatchTestExceptionTwice"
+
+    invoke-direct {v1, v2}, Lart/Test1929$TestException;-><init>(Ljava/lang/String;)V
+
+    throw v1
+    :try_end_8
+    .catch Lart/Test1929$TestException; {:try_start_0 .. :try_end_8} :catch_8
+
+    .line 175
+    :catch_8
+    # This try needs to include the move-exception
+    :try_start_9
+    move-exception v0
+
+    .line 176
+    .local v0, "t":Lart/Test1929$TestException;
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+    new-instance v2, Ljava/lang/StringBuilder;
+
+    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V
+
+    const-string v3, "Caught "
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
+
+    move-result-object v3
+
+    invoke-virtual {v3}, Ljava/lang/Class;->getName()Ljava/lang/String;
+
+    move-result-object v3
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    const-string v3, ": \""
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v0}, Lart/Test1929$TestException;->getMessage()Ljava/lang/String;
+
+    move-result-object v3
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    const-string v3, "\""
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
+
+    move-result-object v2
+
+    invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
+
+    .line 177
+    sget-boolean v1, Lart/Test1929;->PRINT_FULL_EXCEPTION:Z
+
+    if-eqz v1, :cond_46
+
+    .line 178
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+    invoke-virtual {v0, v1}, Lart/Test1929$TestException;->printStackTrace(Ljava/io/PrintStream;)V
+    :try_end_46
+    .catch Lart/Test1929$TestException; {:try_start_9 .. :try_end_46} :catch_47
+
+    .line 187
+    :cond_46
+    :goto_46
+    return-void
+
+    .line 181
+    :catch_47
+    move-exception v0
+
+    .line 182
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+    new-instance v2, Ljava/lang/StringBuilder;
+
+    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V
+
+    const-string v3, "2nd Caught "
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
+
+    move-result-object v3
+
+    invoke-virtual {v3}, Ljava/lang/Class;->getName()Ljava/lang/String;
+
+    move-result-object v3
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    const-string v3, ": \""
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v0}, Lart/Test1929$TestException;->getMessage()Ljava/lang/String;
+
+    move-result-object v3
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    const-string v3, "\""
+
+    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+    move-result-object v2
+
+    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
+
+    move-result-object v2
+
+    invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
+
+    .line 183
+    sget-boolean v1, Lart/Test1929;->PRINT_FULL_EXCEPTION:Z
+
+    if-eqz v1, :cond_46
+
+    .line 184
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+    invoke-virtual {v0, v1}, Lart/Test1929$TestException;->printStackTrace(Ljava/io/PrintStream;)V
+
+    goto :goto_46
+.end method
diff --git a/test/1929-exception-catch-exception/src/Main.java b/test/1929-exception-catch-exception/src/Main.java
new file mode 100644
index 0000000..4651bac
--- /dev/null
+++ b/test/1929-exception-catch-exception/src/Main.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+  public static void main(String[] args) throws Exception {
+    art.Test1929.run();
+  }
+}
diff --git a/test/1929-exception-catch-exception/src/art/Breakpoint.java b/test/1929-exception-catch-exception/src/art/Breakpoint.java
new file mode 100644
index 0000000..bbb89f7
--- /dev/null
+++ b/test/1929-exception-catch-exception/src/art/Breakpoint.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Executable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Objects;
+
+public class Breakpoint {
+  public static class Manager {
+    public static class BP {
+      public final Executable method;
+      public final long location;
+
+      public BP(Executable method) {
+        this(method, getStartLocation(method));
+      }
+
+      public BP(Executable method, long location) {
+        this.method = method;
+        this.location = location;
+      }
+
+      @Override
+      public boolean equals(Object other) {
+        return (other instanceof BP) &&
+            method.equals(((BP)other).method) &&
+            location == ((BP)other).location;
+      }
+
+      @Override
+      public String toString() {
+        return method.toString() + " @ " + getLine();
+      }
+
+      @Override
+      public int hashCode() {
+        return Objects.hash(method, location);
+      }
+
+      public int getLine() {
+        try {
+          LineNumber[] lines = getLineNumberTable(method);
+          int best = -1;
+          for (LineNumber l : lines) {
+            if (l.location > location) {
+              break;
+            } else {
+              best = l.line;
+            }
+          }
+          return best;
+        } catch (Exception e) {
+          return -1;
+        }
+      }
+    }
+
+    private Set<BP> breaks = new HashSet<>();
+
+    public void setBreakpoints(BP... bs) {
+      for (BP b : bs) {
+        if (breaks.add(b)) {
+          Breakpoint.setBreakpoint(b.method, b.location);
+        }
+      }
+    }
+    public void setBreakpoint(Executable method, long location) {
+      setBreakpoints(new BP(method, location));
+    }
+
+    public void clearBreakpoints(BP... bs) {
+      for (BP b : bs) {
+        if (breaks.remove(b)) {
+          Breakpoint.clearBreakpoint(b.method, b.location);
+        }
+      }
+    }
+    public void clearBreakpoint(Executable method, long location) {
+      clearBreakpoints(new BP(method, location));
+    }
+
+    public void clearAllBreakpoints() {
+      clearBreakpoints(breaks.toArray(new BP[0]));
+    }
+  }
+
+  public static void startBreakpointWatch(Class<?> methodClass,
+                                          Executable breakpointReached,
+                                          Thread thr) {
+    startBreakpointWatch(methodClass, breakpointReached, false, thr);
+  }
+
+  /**
+   * Enables the trapping of breakpoint events.
+   *
+   * If allowRecursive == true then breakpoints will be sent even if one is currently being handled.
+   */
+  public static native void startBreakpointWatch(Class<?> methodClass,
+                                                 Executable breakpointReached,
+                                                 boolean allowRecursive,
+                                                 Thread thr);
+  public static native void stopBreakpointWatch(Thread thr);
+
+  public static final class LineNumber implements Comparable<LineNumber> {
+    public final long location;
+    public final int line;
+
+    private LineNumber(long loc, int line) {
+      this.location = loc;
+      this.line = line;
+    }
+
+    public boolean equals(Object other) {
+      return other instanceof LineNumber && ((LineNumber)other).line == line &&
+          ((LineNumber)other).location == location;
+    }
+
+    public int compareTo(LineNumber other) {
+      int v = Integer.valueOf(line).compareTo(Integer.valueOf(other.line));
+      if (v != 0) {
+        return v;
+      } else {
+        return Long.valueOf(location).compareTo(Long.valueOf(other.location));
+      }
+    }
+  }
+
+  public static native void setBreakpoint(Executable m, long loc);
+  public static void setBreakpoint(Executable m, LineNumber l) {
+    setBreakpoint(m, l.location);
+  }
+
+  public static native void clearBreakpoint(Executable m, long loc);
+  public static void clearBreakpoint(Executable m, LineNumber l) {
+    clearBreakpoint(m, l.location);
+  }
+
+  private static native Object[] getLineNumberTableNative(Executable m);
+  public static LineNumber[] getLineNumberTable(Executable m) {
+    Object[] nativeTable = getLineNumberTableNative(m);
+    long[] location = (long[])(nativeTable[0]);
+    int[] lines = (int[])(nativeTable[1]);
+    if (lines.length != location.length) {
+      throw new Error("Lines and locations have different lengths!");
+    }
+    LineNumber[] out = new LineNumber[lines.length];
+    for (int i = 0; i < lines.length; i++) {
+      out[i] = new LineNumber(location[i], lines[i]);
+    }
+    return out;
+  }
+
+  public static native long getStartLocation(Executable m);
+
+  public static int locationToLine(Executable m, long location) {
+    try {
+      Breakpoint.LineNumber[] lines = Breakpoint.getLineNumberTable(m);
+      int best = -1;
+      for (Breakpoint.LineNumber l : lines) {
+        if (l.location > location) {
+          break;
+        } else {
+          best = l.line;
+        }
+      }
+      return best;
+    } catch (Exception e) {
+      return -1;
+    }
+  }
+
+  public static long lineToLocation(Executable m, int line) throws Exception {
+    try {
+      Breakpoint.LineNumber[] lines = Breakpoint.getLineNumberTable(m);
+      for (Breakpoint.LineNumber l : lines) {
+        if (l.line == line) {
+          return l.location;
+        }
+      }
+      throw new Exception("Unable to find line " + line + " in " + m);
+    } catch (Exception e) {
+      throw new Exception("Unable to get line number info for " + m, e);
+    }
+  }
+}
+
diff --git a/test/1929-exception-catch-exception/src/art/Exceptions.java b/test/1929-exception-catch-exception/src/art/Exceptions.java
new file mode 100644
index 0000000..2c959ec
--- /dev/null
+++ b/test/1929-exception-catch-exception/src/art/Exceptions.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class Exceptions {
+  public static native void setupExceptionTracing(
+      Class<?> methodClass,
+      Class<?> exceptionClass,
+      Method exceptionEventMethod,
+      Method exceptionCaughtEventMethod);
+
+  public static native void enableExceptionCatchEvent(Thread thr);
+  public static native void enableExceptionEvent(Thread thr);
+  public static native void disableExceptionCatchEvent(Thread thr);
+  public static native void disableExceptionEvent(Thread thr);
+}
diff --git a/test/1929-exception-catch-exception/src/art/StackTrace.java b/test/1929-exception-catch-exception/src/art/StackTrace.java
new file mode 100644
index 0000000..b12c3df
--- /dev/null
+++ b/test/1929-exception-catch-exception/src/art/StackTrace.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
+
+public class StackTrace {
+  public static class StackFrameData {
+    public final Thread thr;
+    public final Executable method;
+    public final long current_location;
+    public final int depth;
+
+    public StackFrameData(Thread thr, Executable e, long loc, int depth) {
+      this.thr = thr;
+      this.method = e;
+      this.current_location = loc;
+      this.depth = depth;
+    }
+    @Override
+    public String toString() {
+      return String.format(
+          "StackFrameData { thr: '%s', method: '%s', loc: %d, depth: %d }",
+          this.thr,
+          this.method,
+          this.current_location,
+          this.depth);
+    }
+  }
+
+  public static native int GetStackDepth(Thread thr);
+
+  private static native StackFrameData[] nativeGetStackTrace(Thread thr);
+
+  public static StackFrameData[] GetStackTrace(Thread thr) {
+    // The RI seems to give inconsistent (and sometimes nonsensical) results if the thread is not
+    // suspended. The spec says that not being suspended is fine but since we want this to be
+    // consistent we will suspend for the RI.
+    boolean suspend_thread =
+        !System.getProperty("java.vm.name").equals("Dalvik") &&
+        !thr.equals(Thread.currentThread());
+    if (suspend_thread) {
+      Suspension.suspend(thr);
+    }
+    StackFrameData[] out = nativeGetStackTrace(thr);
+    if (suspend_thread) {
+      Suspension.resume(thr);
+    }
+    return out;
+  }
+}
+
diff --git a/test/1929-exception-catch-exception/src/art/Suspension.java b/test/1929-exception-catch-exception/src/art/Suspension.java
new file mode 100644
index 0000000..16e62cc
--- /dev/null
+++ b/test/1929-exception-catch-exception/src/art/Suspension.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+public class Suspension {
+  // Suspends a thread using jvmti.
+  public native static void suspend(Thread thr);
+
+  // Resumes a thread using jvmti.
+  public native static void resume(Thread thr);
+
+  public native static boolean isSuspended(Thread thr);
+
+  public native static int[] suspendList(Thread... threads);
+  public native static int[] resumeList(Thread... threads);
+}
diff --git a/test/1929-exception-catch-exception/src/art/Test1929.java b/test/1929-exception-catch-exception/src/art/Test1929.java
new file mode 100644
index 0000000..07d2087
--- /dev/null
+++ b/test/1929-exception-catch-exception/src/art/Test1929.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Objects;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+
+public class Test1929 {
+  public static boolean PRINT_FULL_EXCEPTION = false;
+  public static ExceptionHandler HANDLER = null;
+  public static Collection<Executable> TEST_METHODS;
+
+  public static void doNothing() {};
+  static {
+    try {
+      TEST_METHODS = Arrays.asList(
+        Test1929.class.getDeclaredMethod("doThrow"),
+        Test1929.class.getDeclaredMethod("throwCatchBaseTestException"),
+        Test1929.class.getDeclaredMethod("throwCatchBaseTestExceptionTwice"),
+        Test1929.class.getDeclaredMethod("throwCatchTestException"),
+        Test1929.class.getDeclaredMethod("throwCatchTestExceptionTwice"),
+        Test1929.class.getDeclaredMethod("throwCatchTestExceptionNoRethrow"));
+    } catch (Exception e) {
+      throw new Error("Unable to list test methods!", e);
+    }
+  }
+
+  public static interface ExceptionHandler {
+    public void exceptionOccurred(
+        Executable m, long loc, Throwable exception);
+  }
+
+  private static void PrintStack() {
+    System.out.println("\tCurrent Stack:");
+    for (StackTrace.StackFrameData e : StackTrace.GetStackTrace(Thread.currentThread())) {
+      if (Objects.equals(e.method.getDeclaringClass().getPackage(), Test1929.class.getPackage())) {
+        System.out.println("\t\t" + e.method + " @ line = " +
+            Breakpoint.locationToLine(e.method, e.current_location));
+      }
+    }
+  }
+
+  public static void ExceptionCatchEvent(
+      Thread thr, Executable method, long location, Throwable exception) {
+    System.out.println(thr.getName() + ": " + method + " @ line = " +
+        Breakpoint.locationToLine(method, location) + " caught " +
+        exception.getClass() + ": " + exception.getMessage());
+    PrintStack();
+    if (PRINT_FULL_EXCEPTION) {
+      System.out.print("exception is: ");
+      exception.printStackTrace(System.out);
+    }
+    if (HANDLER != null && TEST_METHODS.contains(method)) {
+      HANDLER.exceptionOccurred(method, location, exception);
+    }
+  }
+
+  public static class BaseTestException extends Error {
+    public BaseTestException(String e) { super(e); }
+    public BaseTestException(String e, Throwable t) { super(e, t); }
+  }
+  public static class TestException extends BaseTestException {
+    public TestException(String e) { super(e); }
+    public TestException(String e, Throwable t) { super(e, t); }
+  }
+
+  public static class TestExceptionNoRethrow extends TestException {
+    public TestExceptionNoRethrow(String e) { super(e); }
+    public TestExceptionNoRethrow(String e, Throwable t) { super(e, t); }
+  }
+
+  public static class DoNothingHandler implements ExceptionHandler {
+    public void exceptionOccurred(Executable m, long loc, Throwable exception) {
+      System.out.println("\tDoing nothing!");
+      return;
+    }
+  }
+
+  public static class ThrowCatchBase implements ExceptionHandler {
+    public void exceptionOccurred(Executable m, long loc, Throwable exception) {
+      System.out.println("\tThrowing BaseTestException and catching it!");
+      try {
+        throw new BaseTestException("ThrowBaseHandler during throw from " + m + " @ line = " +
+            Breakpoint.locationToLine(m, loc), exception);
+      } catch (BaseTestException t) {
+        System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+        if (PRINT_FULL_EXCEPTION) {
+          t.printStackTrace(System.out);
+        }
+      }
+    }
+  }
+  public static class ThrowBaseTestExceptionHandler implements ExceptionHandler {
+    public void exceptionOccurred(Executable m, long loc, Throwable exception) {
+      System.out.println("\tThrowing BaseTestException!");
+      throw new BaseTestException("ThrowBaseHandler during throw from " + m + " @ line = " +
+          Breakpoint.locationToLine(m, loc), exception);
+    }
+  }
+
+  public static class ThrowTestExceptionNoRethrowHandler implements ExceptionHandler {
+    public void exceptionOccurred(Executable m, long loc, Throwable exception) {
+      if (exception instanceof TestExceptionNoRethrow) {
+        System.out.println("\tInstance of TestExceptionNoRethrow was thrown. Not throwing again.");
+      } else {
+        System.out.println("\tThrowing TestExceptionNoRethrow!");
+        throw new TestExceptionNoRethrow("ThrowTestExceptionNoRethrowHandler during throw from " +
+            m + " @ line = " + Breakpoint.locationToLine(m, loc), exception);
+      }
+    }
+  }
+  public static void doThrow() {
+    throw new TestException("doThrow");
+  }
+
+  public static class DoThrowClass implements Runnable {
+    public void run() { doThrow(); }
+  }
+
+  public static void throwCatchBaseTestException() {
+    try {
+      throw new TestException("throwCatchBaseTestException");
+    } catch (BaseTestException t) {
+      System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+      if (PRINT_FULL_EXCEPTION) {
+        t.printStackTrace(System.out);
+      }
+    }
+  }
+
+  public static class DoThrowCatchBaseTestException implements Runnable {
+    public void run() { throwCatchBaseTestException(); }
+  }
+
+  // dx/d8/jack all do an optimization around catch blocks that (while legal) breaks assumptions
+  // this test relies on so we have the actual implementation be corrected smali. This does work
+  // for RI however.
+  public static final class Impl {
+    private Impl() {}
+    public static void throwCatchBaseTestExceptionTwiceImpl() {
+      try {
+        try {
+          throw new TestException("throwCatchBaseTestExceptionTwice");
+        } catch (BaseTestException t) {
+          System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+          if (PRINT_FULL_EXCEPTION) {
+            t.printStackTrace(System.out);
+          }
+        }
+      } catch (BaseTestException t) {
+        System.out.println("2nd Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+        if (PRINT_FULL_EXCEPTION) {
+          t.printStackTrace(System.out);
+        }
+      }
+    }
+
+    public static void throwCatchTestExceptionTwiceImpl() {
+      try {
+        try {
+          throw new TestException("throwCatchTestExceptionTwice");
+        } catch (TestException t) {
+          System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+          if (PRINT_FULL_EXCEPTION) {
+            t.printStackTrace(System.out);
+          }
+        }
+      } catch (TestException t) {
+        System.out.println("2nd Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+        if (PRINT_FULL_EXCEPTION) {
+          t.printStackTrace(System.out);
+        }
+      }
+    }
+  }
+
+  public static void throwCatchBaseTestExceptionTwice() {
+    // The implementation of this has to change depending upon the runtime slightly due to compiler
+    // optimizations present in DX/D8/Jack.
+    Impl.throwCatchBaseTestExceptionTwiceImpl();
+  }
+
+  public static class DoThrowCatchBaseTestExceptionTwice implements Runnable {
+    public void run() { throwCatchBaseTestExceptionTwice(); }
+  }
+
+  public static void throwCatchTestException() {
+    try {
+      throw new TestException("throwCatchTestException");
+    } catch (TestException t) {
+      System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+      if (PRINT_FULL_EXCEPTION) {
+        t.printStackTrace(System.out);
+      }
+    }
+  }
+
+  public static class DoThrowCatchTestException implements Runnable {
+    public void run() { throwCatchTestException(); }
+  }
+
+  public static void throwCatchTestExceptionTwice() {
+    // The implementation of this has to change depending upon the runtime slightly due to compiler
+    // optimizations present in DX/D8/Jack.
+    Impl.throwCatchTestExceptionTwiceImpl();
+  }
+
+  public static class DoThrowCatchTestExceptionTwice implements Runnable {
+    public void run() { throwCatchTestExceptionTwice(); }
+  }
+
+  public static void throwCatchTestExceptionNoRethrow() {
+    try {
+      throw new TestException("throwCatchTestExceptionNoRethrow");
+    } catch (TestExceptionNoRethrow t) {
+      System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+      if (PRINT_FULL_EXCEPTION) {
+        t.printStackTrace(System.out);
+      }
+    }
+  }
+
+  public static class DoThrowCatchTestExceptionNoRethrow implements Runnable {
+    public void run() { throwCatchTestExceptionNoRethrow(); }
+  }
+
+  public static void run() throws Exception {
+    // Set up breakpoints
+    Exceptions.setupExceptionTracing(
+        Test1929.class,
+        TestException.class,
+        null,
+        Test1929.class.getDeclaredMethod(
+            "ExceptionCatchEvent",
+            Thread.class,
+            Executable.class,
+            Long.TYPE,
+            Throwable.class));
+    Exceptions.enableExceptionCatchEvent(Thread.currentThread());
+
+    ExceptionHandler[] handlers = new ExceptionHandler[] {
+      new DoNothingHandler(),
+      new ThrowCatchBase(),
+      new ThrowBaseTestExceptionHandler(),
+      new ThrowTestExceptionNoRethrowHandler(),
+    };
+
+    Runnable[] tests = new Runnable[] {
+      new DoThrowClass(),
+      new DoThrowCatchBaseTestException(),
+      new DoThrowCatchBaseTestExceptionTwice(),
+      new DoThrowCatchTestException(),
+      new DoThrowCatchTestExceptionTwice(),
+      new DoThrowCatchTestExceptionNoRethrow(),
+    };
+
+    for (ExceptionHandler handler : handlers) {
+      for (Runnable test : tests) {
+        try {
+          HANDLER = handler;
+          System.out.printf("Test \"%s\": Running breakpoint with handler \"%s\"\n",
+              test.getClass().getName(), handler.getClass().getName());
+          test.run();
+          System.out.printf("Test \"%s\": No error caught with handler \"%s\"\n",
+              test.getClass().getName(), handler.getClass().getName());
+        } catch (Throwable e) {
+          System.out.printf("Test \"%s\": Caught error %s:\"%s\" with handler \"%s\"\n",
+              test.getClass().getName(),
+              e.getClass().getName(),
+              e.getMessage(),
+              handler.getClass().getName());
+          if (PRINT_FULL_EXCEPTION) {
+            e.printStackTrace(System.out);
+          }
+        }
+        System.out.printf("Test \"%s\": Finished running with handler \"%s\"\n",
+            test.getClass().getName(), handler.getClass().getName());
+        HANDLER = null;
+      }
+    }
+    Exceptions.disableExceptionCatchEvent(Thread.currentThread());
+  }
+}
diff --git a/test/Android.bp b/test/Android.bp
index 2aed50c..2a88af1 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -254,6 +254,7 @@
         "ti-agent/suspension_helper.cc",
         "ti-agent/stack_trace_helper.cc",
         "ti-agent/trace_helper.cc",
+        "ti-agent/exceptions_helper.cc",
         // This is the list of non-special OnLoad things and excludes BCI and anything that depends
         // on ART internals.
         "903-hello-tagging/tagging.cc",
@@ -298,6 +299,7 @@
         "1922-owned-monitors-info/owned_monitors.cc",
         "1924-frame-pop-toggle/frame_pop_toggle.cc",
         "1926-missed-frame-pop/frame_pop_missed.cc",
+        "1927-exception-event/exception_event.cc"
     ],
     shared_libs: [
         "libbase",
diff --git a/test/ti-agent/exceptions_helper.cc b/test/ti-agent/exceptions_helper.cc
new file mode 100644
index 0000000..74f7ecc
--- /dev/null
+++ b/test/ti-agent/exceptions_helper.cc
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_helper.h"
+
+#include "jni.h"
+#include "jvmti.h"
+
+#include "jvmti_helper.h"
+#include "scoped_local_ref.h"
+#include "test_env.h"
+
+namespace art {
+
+namespace common_exceptions {
+
+struct ExceptionsData {
+  jclass test_klass;
+  jclass exception_klass;
+  jmethodID exception_event;
+  jmethodID exception_catch_event;
+};
+
+static void exceptionCB(jvmtiEnv* jvmti,
+                        JNIEnv* jnienv,
+                        jthread thread,
+                        jmethodID throw_method,
+                        jlocation throw_location,
+                        jobject throwable,
+                        jmethodID catch_method,
+                        jlocation catch_location) {
+  ExceptionsData* data = nullptr;
+  if (JvmtiErrorToException(jnienv, jvmti,
+                            jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) {
+    return;
+  }
+  DCHECK(throwable != nullptr);
+  if (!jnienv->IsInstanceOf(throwable, data->exception_klass)) {
+    return;
+  }
+  jthrowable e = jnienv->ExceptionOccurred();
+  jnienv->ExceptionClear();
+  CHECK(data->exception_event != nullptr);
+  jobject throw_method_arg = GetJavaMethod(jvmti, jnienv, throw_method);
+  jobject catch_method_arg =
+      catch_method != nullptr ? GetJavaMethod(jvmti, jnienv, catch_method) : nullptr;
+  jnienv->CallStaticVoidMethod(data->test_klass,
+                               data->exception_event,
+                               thread,
+                               throw_method_arg,
+                               static_cast<jlong>(throw_location),
+                               throwable,
+                               catch_method_arg,
+                               static_cast<jlong>(catch_location));
+  jnienv->DeleteLocalRef(throw_method_arg);
+  if (catch_method_arg != nullptr) {
+    jnienv->DeleteLocalRef(catch_method_arg);
+  }
+  if (e != nullptr) {
+    jnienv->Throw(e);
+  }
+}
+
+
+static void exceptionCatchCB(jvmtiEnv* jvmti,
+                             JNIEnv* jnienv,
+                             jthread thread,
+                             jmethodID catch_method,
+                             jlocation catch_location,
+                             jobject throwable) {
+  ExceptionsData* data = nullptr;
+  if (JvmtiErrorToException(jnienv, jvmti,
+                            jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) {
+    return;
+  }
+  if (!jnienv->IsSameObject(data->exception_klass, jnienv->GetObjectClass(throwable))) {
+    return;
+  }
+  jthrowable e = jnienv->ExceptionOccurred();
+  jnienv->ExceptionClear();
+  CHECK(data->exception_catch_event != nullptr);
+  jobject catch_method_arg = GetJavaMethod(jvmti, jnienv, catch_method);
+  jnienv->CallStaticVoidMethod(data->test_klass,
+                               data->exception_catch_event,
+                               thread,
+                               catch_method_arg,
+                               static_cast<jlong>(catch_location),
+                               throwable);
+  jnienv->DeleteLocalRef(catch_method_arg);
+  if (e != nullptr) {
+    jnienv->Throw(e);
+  }
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Exceptions_setupExceptionTracing(
+    JNIEnv* env,
+    jclass exception ATTRIBUTE_UNUSED,
+    jclass klass,
+    jclass except,
+    jobject exception_event,
+    jobject exception_catch_event) {
+  ExceptionsData* data = nullptr;
+  if (JvmtiErrorToException(env,
+                            jvmti_env,
+                            jvmti_env->Allocate(sizeof(ExceptionsData),
+                                                reinterpret_cast<unsigned char**>(&data)))) {
+    return;
+  }
+  jvmtiCapabilities caps;
+  memset(&caps, 0, sizeof(caps));
+  caps.can_generate_exception_events = 1;
+  if (JvmtiErrorToException(env, jvmti_env, jvmti_env->AddCapabilities(&caps))) {
+    return;
+  }
+  memset(data, 0, sizeof(ExceptionsData));
+  data->test_klass = reinterpret_cast<jclass>(env->NewGlobalRef(klass));
+  data->exception_klass = reinterpret_cast<jclass>(env->NewGlobalRef(except));
+  data->exception_event =
+      exception_event != nullptr ?  env->FromReflectedMethod(exception_event) : nullptr;
+  data->exception_catch_event =
+      exception_catch_event != nullptr ? env->FromReflectedMethod(exception_catch_event) : nullptr;
+
+  ExceptionsData* old_data = nullptr;
+  if (JvmtiErrorToException(env, jvmti_env,
+                            jvmti_env->GetEnvironmentLocalStorage(
+                                reinterpret_cast<void**>(&old_data)))) {
+    return;
+  } else if (old_data != nullptr && old_data->test_klass != nullptr) {
+    ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException"));
+    env->ThrowNew(rt_exception.get(), "Environment already has local storage set!");
+    return;
+  }
+  if (JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEnvironmentLocalStorage(data))) {
+    return;
+  }
+
+  jvmtiEventCallbacks cb;
+  memset(&cb, 0, sizeof(cb));
+  cb.Exception = exceptionCB;
+  cb.ExceptionCatch = exceptionCatchCB;
+  if (JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb)))) {
+    return;
+  }
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Exceptions_enableExceptionCatchEvent(
+    JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thr) {
+  JvmtiErrorToException(env,
+                        jvmti_env,
+                        jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
+                                                            JVMTI_EVENT_EXCEPTION_CATCH,
+                                                            thr));
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Exceptions_enableExceptionEvent(
+    JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thr) {
+  JvmtiErrorToException(env,
+                        jvmti_env,
+                        jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
+                                                            JVMTI_EVENT_EXCEPTION,
+                                                            thr));
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Exceptions_disableExceptionCatchEvent(
+    JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thr) {
+  JvmtiErrorToException(env,
+                        jvmti_env,
+                        jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
+                                                            JVMTI_EVENT_EXCEPTION_CATCH,
+                                                            thr));
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Exceptions_disableExceptionEvent(
+    JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thr) {
+  JvmtiErrorToException(env,
+                        jvmti_env,
+                        jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
+                                                            JVMTI_EVENT_EXCEPTION,
+                                                            thr));
+}
+
+}  // namespace common_exceptions
+
+
+}  // namespace art