diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp
new file mode 100644
index 0000000..b6b1b56
--- /dev/null
+++ b/openjdkjvmti/Android.bp
@@ -0,0 +1,77 @@
+//
+// Copyright (C) 2016 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.
+
+cc_library_headers {
+    name: "libopenjdkjvmti_headers",
+    host_supported: true,
+    export_include_dirs: ["include"],
+}
+
+cc_defaults {
+    name: "libopenjdkjvmti_defaults",
+    defaults: ["art_defaults"],
+    host_supported: true,
+    srcs: ["events.cc",
+           "fixed_up_dex_file.cc",
+           "object_tagging.cc",
+           "OpenjdkJvmTi.cc",
+           "ti_allocator.cc",
+           "ti_breakpoint.cc",
+           "ti_class.cc",
+           "ti_class_definition.cc",
+           "ti_class_loader.cc",
+           "ti_dump.cc",
+           "ti_field.cc",
+           "ti_heap.cc",
+           "ti_jni.cc",
+           "ti_method.cc",
+           "ti_monitor.cc",
+           "ti_object.cc",
+           "ti_phase.cc",
+           "ti_properties.cc",
+           "ti_search.cc",
+           "ti_stack.cc",
+           "ti_redefine.cc",
+           "ti_thread.cc",
+           "ti_threadgroup.cc",
+           "ti_timers.cc",
+           "transform.cc"],
+    header_libs: ["libopenjdkjvmti_headers"],
+    shared_libs: [
+        "libbase",
+        "libnativehelper",
+    ],
+}
+
+art_cc_library {
+    name: "libopenjdkjvmti",
+    defaults: ["libopenjdkjvmti_defaults"],
+    shared_libs: [
+        "libart",
+        "libart-compiler",
+    ],
+}
+
+art_cc_library {
+    name: "libopenjdkjvmtid",
+    defaults: [
+        "art_debug_defaults",
+        "libopenjdkjvmti_defaults",
+    ],
+    shared_libs: [
+        "libartd",
+        "libartd-compiler",
+    ],
+}
diff --git a/openjdkjvmti/MODULE_LICENSE_GPL_WITH_CLASSPATH_EXCEPTION b/openjdkjvmti/MODULE_LICENSE_GPL_WITH_CLASSPATH_EXCEPTION
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/openjdkjvmti/MODULE_LICENSE_GPL_WITH_CLASSPATH_EXCEPTION
diff --git a/openjdkjvmti/NOTICE b/openjdkjvmti/NOTICE
new file mode 100644
index 0000000..6ec62cd
--- /dev/null
+++ b/openjdkjvmti/NOTICE
@@ -0,0 +1,29 @@
+Copyright (C) 2016 The Android Open Source Project
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This file implements interfaces from the file jvmti.h. This implementation
+is licensed under the same terms as the file jvmti.h.  The
+copyright and license information for the file jvmti.h follows.
+
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
diff --git a/openjdkjvmti/OpenjdkJvmTi.cc b/openjdkjvmti/OpenjdkJvmTi.cc
new file mode 100644
index 0000000..af77072
--- /dev/null
+++ b/openjdkjvmti/OpenjdkJvmTi.cc
@@ -0,0 +1,1903 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include <jni.h>
+
+#include "jvmti.h"
+
+#include "art_jvmti.h"
+#include "base/logging.h"
+#include "base/mutex.h"
+#include "events-inl.h"
+#include "jni_env_ext-inl.h"
+#include "obj_ptr-inl.h"
+#include "object_tagging.h"
+#include "runtime.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+#include "thread_list.h"
+#include "ti_allocator.h"
+#include "ti_breakpoint.h"
+#include "ti_class.h"
+#include "ti_dump.h"
+#include "ti_field.h"
+#include "ti_heap.h"
+#include "ti_jni.h"
+#include "ti_method.h"
+#include "ti_monitor.h"
+#include "ti_object.h"
+#include "ti_phase.h"
+#include "ti_properties.h"
+#include "ti_redefine.h"
+#include "ti_search.h"
+#include "ti_stack.h"
+#include "ti_thread.h"
+#include "ti_threadgroup.h"
+#include "ti_timers.h"
+#include "transform.h"
+
+namespace openjdkjvmti {
+
+EventHandler gEventHandler;
+
+#define ENSURE_NON_NULL(n)      \
+  do {                          \
+    if ((n) == nullptr) {       \
+      return ERR(NULL_POINTER); \
+    }                           \
+  } while (false)
+
+class JvmtiFunctions {
+ private:
+  static jvmtiError getEnvironmentError(jvmtiEnv* env) {
+    if (env == nullptr) {
+      return ERR(INVALID_ENVIRONMENT);
+    } else if (art::Thread::Current() == nullptr) {
+      return ERR(UNATTACHED_THREAD);
+    } else {
+      return OK;
+    }
+  }
+
+#define ENSURE_VALID_ENV(env)                                            \
+  do {                                                                   \
+    jvmtiError ensure_valid_env_ ## __LINE__ = getEnvironmentError(env); \
+    if (ensure_valid_env_ ## __LINE__ != OK) {                           \
+      return ensure_valid_env_ ## __LINE__ ;                             \
+    }                                                                    \
+  } while (false)
+
+#define ENSURE_HAS_CAP(env, cap) \
+  do { \
+    if (ArtJvmTiEnv::AsArtJvmTiEnv(env)->capabilities.cap != 1) { \
+      return ERR(MUST_POSSESS_CAPABILITY); \
+    } \
+  } while (false)
+
+ public:
+  static jvmtiError Allocate(jvmtiEnv* env, jlong size, unsigned char** mem_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_NON_NULL(mem_ptr);
+    return AllocUtil::Allocate(env, size, mem_ptr);
+  }
+
+  static jvmtiError Deallocate(jvmtiEnv* env, unsigned char* mem) {
+    ENSURE_VALID_ENV(env);
+    return AllocUtil::Deallocate(env, mem);
+  }
+
+  static jvmtiError GetThreadState(jvmtiEnv* env, jthread thread, jint* thread_state_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ThreadUtil::GetThreadState(env, thread, thread_state_ptr);
+  }
+
+  static jvmtiError GetCurrentThread(jvmtiEnv* env, jthread* thread_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ThreadUtil::GetCurrentThread(env, thread_ptr);
+  }
+
+  static jvmtiError GetAllThreads(jvmtiEnv* env, jint* threads_count_ptr, jthread** threads_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ThreadUtil::GetAllThreads(env, threads_count_ptr, threads_ptr);
+  }
+
+  static jvmtiError SuspendThread(jvmtiEnv* env, jthread thread) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_suspend);
+    return ThreadUtil::SuspendThread(env, thread);
+  }
+
+  static jvmtiError SuspendThreadList(jvmtiEnv* env,
+                                      jint request_count,
+                                      const jthread* request_list,
+                                      jvmtiError* results) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_suspend);
+    return ThreadUtil::SuspendThreadList(env, request_count, request_list, results);
+  }
+
+  static jvmtiError ResumeThread(jvmtiEnv* env, jthread thread) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_suspend);
+    return ThreadUtil::ResumeThread(env, thread);
+  }
+
+  static jvmtiError ResumeThreadList(jvmtiEnv* env,
+                                     jint request_count,
+                                     const jthread* request_list,
+                                     jvmtiError* results) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_suspend);
+    return ThreadUtil::ResumeThreadList(env, request_count, request_list, results);
+  }
+
+  static jvmtiError StopThread(jvmtiEnv* env,
+                               jthread thread ATTRIBUTE_UNUSED,
+                               jobject exception ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_signal_thread);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError InterruptThread(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_signal_thread);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ThreadUtil::GetThreadInfo(env, thread, info_ptr);
+  }
+
+  static jvmtiError GetOwnedMonitorInfo(jvmtiEnv* env,
+                                        jthread thread ATTRIBUTE_UNUSED,
+                                        jint* owned_monitor_count_ptr ATTRIBUTE_UNUSED,
+                                        jobject** owned_monitors_ptr ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_owned_monitor_info);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError GetOwnedMonitorStackDepthInfo(
+      jvmtiEnv* env,
+      jthread thread ATTRIBUTE_UNUSED,
+      jint* monitor_info_count_ptr ATTRIBUTE_UNUSED,
+      jvmtiMonitorStackDepthInfo** monitor_info_ptr ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_owned_monitor_stack_depth_info);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError GetCurrentContendedMonitor(jvmtiEnv* env,
+                                               jthread thread ATTRIBUTE_UNUSED,
+                                               jobject* monitor_ptr ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_current_contended_monitor);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError RunAgentThread(jvmtiEnv* env,
+                                   jthread thread,
+                                   jvmtiStartFunction proc,
+                                   const void* arg,
+                                   jint priority) {
+    ENSURE_VALID_ENV(env);
+    return ThreadUtil::RunAgentThread(env, thread, proc, arg, priority);
+  }
+
+  static jvmtiError SetThreadLocalStorage(jvmtiEnv* env, jthread thread, const void* data) {
+    ENSURE_VALID_ENV(env);
+    return ThreadUtil::SetThreadLocalStorage(env, thread, data);
+  }
+
+  static jvmtiError GetThreadLocalStorage(jvmtiEnv* env, jthread thread, void** data_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ThreadUtil::GetThreadLocalStorage(env, thread, data_ptr);
+  }
+
+  static jvmtiError GetTopThreadGroups(jvmtiEnv* env,
+                                       jint* group_count_ptr,
+                                       jthreadGroup** groups_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ThreadGroupUtil::GetTopThreadGroups(env, group_count_ptr, groups_ptr);
+  }
+
+  static jvmtiError GetThreadGroupInfo(jvmtiEnv* env,
+                                       jthreadGroup group,
+                                       jvmtiThreadGroupInfo* info_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ThreadGroupUtil::GetThreadGroupInfo(env, group, info_ptr);
+  }
+
+  static jvmtiError GetThreadGroupChildren(jvmtiEnv* env,
+                                           jthreadGroup group,
+                                           jint* thread_count_ptr,
+                                           jthread** threads_ptr,
+                                           jint* group_count_ptr,
+                                           jthreadGroup** groups_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ThreadGroupUtil::GetThreadGroupChildren(env,
+                                                   group,
+                                                   thread_count_ptr,
+                                                   threads_ptr,
+                                                   group_count_ptr,
+                                                   groups_ptr);
+  }
+
+  static jvmtiError GetStackTrace(jvmtiEnv* env,
+                                  jthread thread,
+                                  jint start_depth,
+                                  jint max_frame_count,
+                                  jvmtiFrameInfo* frame_buffer,
+                                  jint* count_ptr) {
+    ENSURE_VALID_ENV(env);
+    return StackUtil::GetStackTrace(env,
+                                    thread,
+                                    start_depth,
+                                    max_frame_count,
+                                    frame_buffer,
+                                    count_ptr);
+  }
+
+  static jvmtiError GetAllStackTraces(jvmtiEnv* env,
+                                      jint max_frame_count,
+                                      jvmtiStackInfo** stack_info_ptr,
+                                      jint* thread_count_ptr) {
+    ENSURE_VALID_ENV(env);
+    return StackUtil::GetAllStackTraces(env, max_frame_count, stack_info_ptr, thread_count_ptr);
+  }
+
+  static jvmtiError GetThreadListStackTraces(jvmtiEnv* env,
+                                             jint thread_count,
+                                             const jthread* thread_list,
+                                             jint max_frame_count,
+                                             jvmtiStackInfo** stack_info_ptr) {
+    ENSURE_VALID_ENV(env);
+    return StackUtil::GetThreadListStackTraces(env,
+                                               thread_count,
+                                               thread_list,
+                                               max_frame_count,
+                                               stack_info_ptr);
+  }
+
+  static jvmtiError GetFrameCount(jvmtiEnv* env, jthread thread, jint* count_ptr) {
+    ENSURE_VALID_ENV(env);
+    return StackUtil::GetFrameCount(env, thread, count_ptr);
+  }
+
+  static jvmtiError PopFrame(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_pop_frame);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError GetFrameLocation(jvmtiEnv* env,
+                                     jthread thread,
+                                     jint depth,
+                                     jmethodID* method_ptr,
+                                     jlocation* location_ptr) {
+    ENSURE_VALID_ENV(env);
+    return StackUtil::GetFrameLocation(env, thread, depth, method_ptr, location_ptr);
+  }
+
+  static jvmtiError NotifyFramePop(jvmtiEnv* env,
+                                   jthread thread ATTRIBUTE_UNUSED,
+                                   jint depth ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_generate_frame_pop_events);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError ForceEarlyReturnObject(jvmtiEnv* env,
+                                           jthread thread ATTRIBUTE_UNUSED,
+                                           jobject value ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_force_early_return);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError ForceEarlyReturnInt(jvmtiEnv* env,
+                                        jthread thread ATTRIBUTE_UNUSED,
+                                        jint value ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_force_early_return);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError ForceEarlyReturnLong(jvmtiEnv* env,
+                                         jthread thread ATTRIBUTE_UNUSED,
+                                         jlong value ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_force_early_return);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError ForceEarlyReturnFloat(jvmtiEnv* env,
+                                          jthread thread ATTRIBUTE_UNUSED,
+                                          jfloat value ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_force_early_return);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError ForceEarlyReturnDouble(jvmtiEnv* env,
+                                           jthread thread ATTRIBUTE_UNUSED,
+                                           jdouble value ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_force_early_return);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError ForceEarlyReturnVoid(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_force_early_return);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError FollowReferences(jvmtiEnv* env,
+                                     jint heap_filter,
+                                     jclass klass,
+                                     jobject initial_object,
+                                     const jvmtiHeapCallbacks* callbacks,
+                                     const void* user_data) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_tag_objects);
+    HeapUtil heap_util(ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get());
+    return heap_util.FollowReferences(env,
+                                      heap_filter,
+                                      klass,
+                                      initial_object,
+                                      callbacks,
+                                      user_data);
+  }
+
+  static jvmtiError IterateThroughHeap(jvmtiEnv* env,
+                                       jint heap_filter,
+                                       jclass klass,
+                                       const jvmtiHeapCallbacks* callbacks,
+                                       const void* user_data) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_tag_objects);
+    HeapUtil heap_util(ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get());
+    return heap_util.IterateThroughHeap(env, heap_filter, klass, callbacks, user_data);
+  }
+
+  static jvmtiError GetTag(jvmtiEnv* env, jobject object, jlong* tag_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_tag_objects);
+
+    JNIEnv* jni_env = GetJniEnv(env);
+    if (jni_env == nullptr) {
+      return ERR(INTERNAL);
+    }
+
+    art::ScopedObjectAccess soa(jni_env);
+    art::ObjPtr<art::mirror::Object> obj = soa.Decode<art::mirror::Object>(object);
+    if (!ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table->GetTag(obj.Ptr(), tag_ptr)) {
+      *tag_ptr = 0;
+    }
+
+    return ERR(NONE);
+  }
+
+  static jvmtiError SetTag(jvmtiEnv* env, jobject object, jlong tag) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_tag_objects);
+
+    if (object == nullptr) {
+      return ERR(NULL_POINTER);
+    }
+
+    JNIEnv* jni_env = GetJniEnv(env);
+    if (jni_env == nullptr) {
+      return ERR(INTERNAL);
+    }
+
+    art::ScopedObjectAccess soa(jni_env);
+    art::ObjPtr<art::mirror::Object> obj = soa.Decode<art::mirror::Object>(object);
+    ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table->Set(obj.Ptr(), tag);
+
+    return ERR(NONE);
+  }
+
+  static jvmtiError GetObjectsWithTags(jvmtiEnv* env,
+                                       jint tag_count,
+                                       const jlong* tags,
+                                       jint* count_ptr,
+                                       jobject** object_result_ptr,
+                                       jlong** tag_result_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_tag_objects);
+
+    JNIEnv* jni_env = GetJniEnv(env);
+    if (jni_env == nullptr) {
+      return ERR(INTERNAL);
+    }
+
+    art::ScopedObjectAccess soa(jni_env);
+    return ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table->GetTaggedObjects(env,
+                                                                               tag_count,
+                                                                               tags,
+                                                                               count_ptr,
+                                                                               object_result_ptr,
+                                                                               tag_result_ptr);
+  }
+
+  static jvmtiError ForceGarbageCollection(jvmtiEnv* env) {
+    ENSURE_VALID_ENV(env);
+    return HeapUtil::ForceGarbageCollection(env);
+  }
+
+  static jvmtiError IterateOverObjectsReachableFromObject(
+      jvmtiEnv* env,
+      jobject object ATTRIBUTE_UNUSED,
+      jvmtiObjectReferenceCallback object_reference_callback ATTRIBUTE_UNUSED,
+      const void* user_data ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_tag_objects);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError IterateOverReachableObjects(
+      jvmtiEnv* env,
+      jvmtiHeapRootCallback heap_root_callback ATTRIBUTE_UNUSED,
+      jvmtiStackReferenceCallback stack_ref_callback ATTRIBUTE_UNUSED,
+      jvmtiObjectReferenceCallback object_ref_callback ATTRIBUTE_UNUSED,
+      const void* user_data ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_tag_objects);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError IterateOverHeap(jvmtiEnv* env,
+                                    jvmtiHeapObjectFilter object_filter ATTRIBUTE_UNUSED,
+                                    jvmtiHeapObjectCallback heap_object_callback ATTRIBUTE_UNUSED,
+                                    const void* user_data ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_tag_objects);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError IterateOverInstancesOfClass(
+      jvmtiEnv* env,
+      jclass klass ATTRIBUTE_UNUSED,
+      jvmtiHeapObjectFilter object_filter ATTRIBUTE_UNUSED,
+      jvmtiHeapObjectCallback heap_object_callback ATTRIBUTE_UNUSED,
+      const void* user_data ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_tag_objects);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError GetLocalObject(jvmtiEnv* env,
+                                   jthread thread,
+                                   jint depth,
+                                   jint slot,
+                                   jobject* value_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::GetLocalVariable(env, thread, depth, slot, value_ptr);
+  }
+
+  static jvmtiError GetLocalInstance(jvmtiEnv* env,
+                                     jthread thread,
+                                     jint depth,
+                                     jobject* value_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::GetLocalInstance(env, thread, depth, value_ptr);
+  }
+
+  static jvmtiError GetLocalInt(jvmtiEnv* env,
+                                jthread thread,
+                                jint depth,
+                                jint slot,
+                                jint* value_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::GetLocalVariable(env, thread, depth, slot, value_ptr);
+  }
+
+  static jvmtiError GetLocalLong(jvmtiEnv* env,
+                                 jthread thread,
+                                 jint depth,
+                                 jint slot,
+                                 jlong* value_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::GetLocalVariable(env, thread, depth, slot, value_ptr);
+  }
+
+  static jvmtiError GetLocalFloat(jvmtiEnv* env,
+                                  jthread thread,
+                                  jint depth,
+                                  jint slot,
+                                  jfloat* value_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::GetLocalVariable(env, thread, depth, slot, value_ptr);
+  }
+
+  static jvmtiError GetLocalDouble(jvmtiEnv* env,
+                                   jthread thread,
+                                   jint depth,
+                                   jint slot,
+                                   jdouble* value_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::GetLocalVariable(env, thread, depth, slot, value_ptr);
+  }
+
+  static jvmtiError SetLocalObject(jvmtiEnv* env,
+                                   jthread thread,
+                                   jint depth,
+                                   jint slot,
+                                   jobject value) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::SetLocalVariable(env, thread, depth, slot, value);
+  }
+
+  static jvmtiError SetLocalInt(jvmtiEnv* env,
+                                jthread thread,
+                                jint depth,
+                                jint slot,
+                                jint value) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::SetLocalVariable(env, thread, depth, slot, value);
+  }
+
+  static jvmtiError SetLocalLong(jvmtiEnv* env,
+                                 jthread thread,
+                                 jint depth,
+                                 jint slot,
+                                 jlong value) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::SetLocalVariable(env, thread, depth, slot, value);
+  }
+
+  static jvmtiError SetLocalFloat(jvmtiEnv* env,
+                                  jthread thread,
+                                  jint depth,
+                                  jint slot,
+                                  jfloat value) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::SetLocalVariable(env, thread, depth, slot, value);
+  }
+
+  static jvmtiError SetLocalDouble(jvmtiEnv* env,
+                                   jthread thread,
+                                   jint depth,
+                                   jint slot,
+                                   jdouble value) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::SetLocalVariable(env, thread, depth, slot, value);
+  }
+
+
+  static jvmtiError SetBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_generate_breakpoint_events);
+    return BreakpointUtil::SetBreakpoint(env, method, location);
+  }
+
+  static jvmtiError ClearBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_generate_breakpoint_events);
+    return BreakpointUtil::ClearBreakpoint(env, method, location);
+  }
+
+  static jvmtiError SetFieldAccessWatch(jvmtiEnv* env, jclass klass, jfieldID field) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_generate_field_access_events);
+    return FieldUtil::SetFieldAccessWatch(env, klass, field);
+  }
+
+  static jvmtiError ClearFieldAccessWatch(jvmtiEnv* env, jclass klass, jfieldID field) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_generate_field_access_events);
+    return FieldUtil::ClearFieldAccessWatch(env, klass, field);
+  }
+
+  static jvmtiError SetFieldModificationWatch(jvmtiEnv* env, jclass klass, jfieldID field) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_generate_field_modification_events);
+    return FieldUtil::SetFieldModificationWatch(env, klass, field);
+  }
+
+  static jvmtiError ClearFieldModificationWatch(jvmtiEnv* env, jclass klass, jfieldID field) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_generate_field_modification_events);
+    return FieldUtil::ClearFieldModificationWatch(env, klass, field);
+  }
+
+  static jvmtiError GetLoadedClasses(jvmtiEnv* env, jint* class_count_ptr, jclass** classes_ptr) {
+    ENSURE_VALID_ENV(env);
+    HeapUtil heap_util(ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get());
+    return heap_util.GetLoadedClasses(env, class_count_ptr, classes_ptr);
+  }
+
+  static jvmtiError GetClassLoaderClasses(jvmtiEnv* env,
+                                          jobject initiating_loader,
+                                          jint* class_count_ptr,
+                                          jclass** classes_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::GetClassLoaderClasses(env, initiating_loader, class_count_ptr, classes_ptr);
+  }
+
+  static jvmtiError GetClassSignature(jvmtiEnv* env,
+                                      jclass klass,
+                                      char** signature_ptr,
+                                      char** generic_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::GetClassSignature(env, klass, signature_ptr, generic_ptr);
+  }
+
+  static jvmtiError GetClassStatus(jvmtiEnv* env, jclass klass, jint* status_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::GetClassStatus(env, klass, status_ptr);
+  }
+
+  static jvmtiError GetSourceFileName(jvmtiEnv* env, jclass klass, char** source_name_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_source_file_name);
+    return ClassUtil::GetSourceFileName(env, klass, source_name_ptr);
+  }
+
+  static jvmtiError GetClassModifiers(jvmtiEnv* env, jclass klass, jint* modifiers_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::GetClassModifiers(env, klass, modifiers_ptr);
+  }
+
+  static jvmtiError GetClassMethods(jvmtiEnv* env,
+                                    jclass klass,
+                                    jint* method_count_ptr,
+                                    jmethodID** methods_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::GetClassMethods(env, klass, method_count_ptr, methods_ptr);
+  }
+
+  static jvmtiError GetClassFields(jvmtiEnv* env,
+                                   jclass klass,
+                                   jint* field_count_ptr,
+                                   jfieldID** fields_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::GetClassFields(env, klass, field_count_ptr, fields_ptr);
+  }
+
+  static jvmtiError GetImplementedInterfaces(jvmtiEnv* env,
+                                             jclass klass,
+                                             jint* interface_count_ptr,
+                                             jclass** interfaces_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::GetImplementedInterfaces(env, klass, interface_count_ptr, interfaces_ptr);
+  }
+
+  static jvmtiError GetClassVersionNumbers(jvmtiEnv* env,
+                                           jclass klass,
+                                           jint* minor_version_ptr,
+                                           jint* major_version_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::GetClassVersionNumbers(env, klass, minor_version_ptr, major_version_ptr);
+  }
+
+  static jvmtiError GetConstantPool(jvmtiEnv* env,
+                                    jclass klass ATTRIBUTE_UNUSED,
+                                    jint* constant_pool_count_ptr ATTRIBUTE_UNUSED,
+                                    jint* constant_pool_byte_count_ptr ATTRIBUTE_UNUSED,
+                                    unsigned char** constant_pool_bytes_ptr ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_constant_pool);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError IsInterface(jvmtiEnv* env, jclass klass, jboolean* is_interface_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::IsInterface(env, klass, is_interface_ptr);
+  }
+
+  static jvmtiError IsArrayClass(jvmtiEnv* env,
+                                 jclass klass,
+                                 jboolean* is_array_class_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::IsArrayClass(env, klass, is_array_class_ptr);
+  }
+
+  static jvmtiError IsModifiableClass(jvmtiEnv* env,
+                                      jclass klass,
+                                      jboolean* is_modifiable_class_ptr) {
+    ENSURE_VALID_ENV(env);
+    return Redefiner::IsModifiableClass(env, klass, is_modifiable_class_ptr);
+  }
+
+  static jvmtiError GetClassLoader(jvmtiEnv* env, jclass klass, jobject* classloader_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ClassUtil::GetClassLoader(env, klass, classloader_ptr);
+  }
+
+  static jvmtiError GetSourceDebugExtension(jvmtiEnv* env,
+                                            jclass klass,
+                                            char** source_debug_extension_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_source_debug_extension);
+    return ClassUtil::GetSourceDebugExtension(env, klass, source_debug_extension_ptr);
+  }
+
+  static jvmtiError RetransformClasses(jvmtiEnv* env, jint class_count, const jclass* classes) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_retransform_classes);
+    std::string error_msg;
+    jvmtiError res = Transformer::RetransformClasses(ArtJvmTiEnv::AsArtJvmTiEnv(env),
+                                                     &gEventHandler,
+                                                     art::Runtime::Current(),
+                                                     art::Thread::Current(),
+                                                     class_count,
+                                                     classes,
+                                                     &error_msg);
+    if (res != OK) {
+      LOG(WARNING) << "FAILURE TO RETRANFORM " << error_msg;
+    }
+    return res;
+  }
+
+  static jvmtiError RedefineClasses(jvmtiEnv* env,
+                                    jint class_count,
+                                    const jvmtiClassDefinition* class_definitions) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_redefine_classes);
+    std::string error_msg;
+    jvmtiError res = Redefiner::RedefineClasses(ArtJvmTiEnv::AsArtJvmTiEnv(env),
+                                                &gEventHandler,
+                                                art::Runtime::Current(),
+                                                art::Thread::Current(),
+                                                class_count,
+                                                class_definitions,
+                                                &error_msg);
+    if (res != OK) {
+      LOG(WARNING) << "FAILURE TO REDEFINE " << error_msg;
+    }
+    return res;
+  }
+
+  static jvmtiError GetObjectSize(jvmtiEnv* env, jobject object, jlong* size_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ObjectUtil::GetObjectSize(env, object, size_ptr);
+  }
+
+  static jvmtiError GetObjectHashCode(jvmtiEnv* env, jobject object, jint* hash_code_ptr) {
+    ENSURE_VALID_ENV(env);
+    return ObjectUtil::GetObjectHashCode(env, object, hash_code_ptr);
+  }
+
+  static jvmtiError GetObjectMonitorUsage(jvmtiEnv* env,
+                                          jobject object ATTRIBUTE_UNUSED,
+                                          jvmtiMonitorUsage* info_ptr ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_monitor_info);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError GetFieldName(jvmtiEnv* env,
+                                 jclass klass,
+                                 jfieldID field,
+                                 char** name_ptr,
+                                 char** signature_ptr,
+                                 char** generic_ptr) {
+    ENSURE_VALID_ENV(env);
+    return FieldUtil::GetFieldName(env, klass, field, name_ptr, signature_ptr, generic_ptr);
+  }
+
+  static jvmtiError GetFieldDeclaringClass(jvmtiEnv* env,
+                                           jclass klass,
+                                           jfieldID field,
+                                           jclass* declaring_class_ptr) {
+    ENSURE_VALID_ENV(env);
+    return FieldUtil::GetFieldDeclaringClass(env, klass, field, declaring_class_ptr);
+  }
+
+  static jvmtiError GetFieldModifiers(jvmtiEnv* env,
+                                      jclass klass,
+                                      jfieldID field,
+                                      jint* modifiers_ptr) {
+    ENSURE_VALID_ENV(env);
+    return FieldUtil::GetFieldModifiers(env, klass, field, modifiers_ptr);
+  }
+
+  static jvmtiError IsFieldSynthetic(jvmtiEnv* env,
+                                     jclass klass,
+                                     jfieldID field,
+                                     jboolean* is_synthetic_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_synthetic_attribute);
+    return FieldUtil::IsFieldSynthetic(env, klass, field, is_synthetic_ptr);
+  }
+
+  static jvmtiError GetMethodName(jvmtiEnv* env,
+                                  jmethodID method,
+                                  char** name_ptr,
+                                  char** signature_ptr,
+                                  char** generic_ptr) {
+    ENSURE_VALID_ENV(env);
+    return MethodUtil::GetMethodName(env, method, name_ptr, signature_ptr, generic_ptr);
+  }
+
+  static jvmtiError GetMethodDeclaringClass(jvmtiEnv* env,
+                                            jmethodID method,
+                                            jclass* declaring_class_ptr) {
+    ENSURE_VALID_ENV(env);
+    return MethodUtil::GetMethodDeclaringClass(env, method, declaring_class_ptr);
+  }
+
+  static jvmtiError GetMethodModifiers(jvmtiEnv* env,
+                                       jmethodID method,
+                                       jint* modifiers_ptr) {
+    ENSURE_VALID_ENV(env);
+    return MethodUtil::GetMethodModifiers(env, method, modifiers_ptr);
+  }
+
+  static jvmtiError GetMaxLocals(jvmtiEnv* env,
+                                 jmethodID method,
+                                 jint* max_ptr) {
+    ENSURE_VALID_ENV(env);
+    return MethodUtil::GetMaxLocals(env, method, max_ptr);
+  }
+
+  static jvmtiError GetArgumentsSize(jvmtiEnv* env,
+                                     jmethodID method,
+                                     jint* size_ptr) {
+    ENSURE_VALID_ENV(env);
+    return MethodUtil::GetArgumentsSize(env, method, size_ptr);
+  }
+
+  static jvmtiError GetLineNumberTable(jvmtiEnv* env,
+                                       jmethodID method,
+                                       jint* entry_count_ptr,
+                                       jvmtiLineNumberEntry** table_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_line_numbers);
+    return MethodUtil::GetLineNumberTable(env, method, entry_count_ptr, table_ptr);
+  }
+
+  static jvmtiError GetMethodLocation(jvmtiEnv* env,
+                                      jmethodID method,
+                                      jlocation* start_location_ptr,
+                                      jlocation* end_location_ptr) {
+    ENSURE_VALID_ENV(env);
+    return MethodUtil::GetMethodLocation(env, method, start_location_ptr, end_location_ptr);
+  }
+
+  static jvmtiError GetLocalVariableTable(jvmtiEnv* env,
+                                          jmethodID method,
+                                          jint* entry_count_ptr,
+                                          jvmtiLocalVariableEntry** table_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_access_local_variables);
+    return MethodUtil::GetLocalVariableTable(env, method, entry_count_ptr, table_ptr);
+  }
+
+  static jvmtiError GetBytecodes(jvmtiEnv* env,
+                                 jmethodID method,
+                                 jint* bytecode_count_ptr,
+                                 unsigned char** bytecodes_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_bytecodes);
+    return MethodUtil::GetBytecodes(env, method, bytecode_count_ptr, bytecodes_ptr);
+  }
+
+  static jvmtiError IsMethodNative(jvmtiEnv* env, jmethodID method, jboolean* is_native_ptr) {
+    ENSURE_VALID_ENV(env);
+    return MethodUtil::IsMethodNative(env, method, is_native_ptr);
+  }
+
+  static jvmtiError IsMethodSynthetic(jvmtiEnv* env, jmethodID method, jboolean* is_synthetic_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_synthetic_attribute);
+    return MethodUtil::IsMethodSynthetic(env, method, is_synthetic_ptr);
+  }
+
+  static jvmtiError IsMethodObsolete(jvmtiEnv* env, jmethodID method, jboolean* is_obsolete_ptr) {
+    ENSURE_VALID_ENV(env);
+    return MethodUtil::IsMethodObsolete(env, method, is_obsolete_ptr);
+  }
+
+  static jvmtiError SetNativeMethodPrefix(jvmtiEnv* env, const char* prefix ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_set_native_method_prefix);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError SetNativeMethodPrefixes(jvmtiEnv* env,
+                                            jint prefix_count ATTRIBUTE_UNUSED,
+                                            char** prefixes ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_set_native_method_prefix);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError CreateRawMonitor(jvmtiEnv* env, const char* name, jrawMonitorID* monitor_ptr) {
+    ENSURE_VALID_ENV(env);
+    return MonitorUtil::CreateRawMonitor(env, name, monitor_ptr);
+  }
+
+  static jvmtiError DestroyRawMonitor(jvmtiEnv* env, jrawMonitorID monitor) {
+    ENSURE_VALID_ENV(env);
+    return MonitorUtil::DestroyRawMonitor(env, monitor);
+  }
+
+  static jvmtiError RawMonitorEnter(jvmtiEnv* env, jrawMonitorID monitor) {
+    ENSURE_VALID_ENV(env);
+    return MonitorUtil::RawMonitorEnter(env, monitor);
+  }
+
+  static jvmtiError RawMonitorExit(jvmtiEnv* env, jrawMonitorID monitor) {
+    ENSURE_VALID_ENV(env);
+    return MonitorUtil::RawMonitorExit(env, monitor);
+  }
+
+  static jvmtiError RawMonitorWait(jvmtiEnv* env, jrawMonitorID monitor, jlong millis) {
+    ENSURE_VALID_ENV(env);
+    return MonitorUtil::RawMonitorWait(env, monitor, millis);
+  }
+
+  static jvmtiError RawMonitorNotify(jvmtiEnv* env, jrawMonitorID monitor) {
+    ENSURE_VALID_ENV(env);
+    return MonitorUtil::RawMonitorNotify(env, monitor);
+  }
+
+  static jvmtiError RawMonitorNotifyAll(jvmtiEnv* env, jrawMonitorID monitor) {
+    ENSURE_VALID_ENV(env);
+    return MonitorUtil::RawMonitorNotifyAll(env, monitor);
+  }
+
+  static jvmtiError SetJNIFunctionTable(jvmtiEnv* env, const jniNativeInterface* function_table) {
+    ENSURE_VALID_ENV(env);
+    return JNIUtil::SetJNIFunctionTable(env, function_table);
+  }
+
+  static jvmtiError GetJNIFunctionTable(jvmtiEnv* env, jniNativeInterface** function_table) {
+    ENSURE_VALID_ENV(env);
+    return JNIUtil::GetJNIFunctionTable(env, function_table);
+  }
+
+  // TODO: This will require locking, so that an agent can't remove callbacks when we're dispatching
+  //       an event.
+  static jvmtiError SetEventCallbacks(jvmtiEnv* env,
+                                      const jvmtiEventCallbacks* callbacks,
+                                      jint size_of_callbacks) {
+    ENSURE_VALID_ENV(env);
+    if (size_of_callbacks < 0) {
+      return ERR(ILLEGAL_ARGUMENT);
+    }
+
+    if (callbacks == nullptr) {
+      ArtJvmTiEnv::AsArtJvmTiEnv(env)->event_callbacks.reset();
+      return ERR(NONE);
+    }
+
+    std::unique_ptr<jvmtiEventCallbacks> tmp(new jvmtiEventCallbacks());
+    memset(tmp.get(), 0, sizeof(jvmtiEventCallbacks));
+    size_t copy_size = std::min(sizeof(jvmtiEventCallbacks),
+                                static_cast<size_t>(size_of_callbacks));
+    copy_size = art::RoundDown(copy_size, sizeof(void*));
+    memcpy(tmp.get(), callbacks, copy_size);
+
+    ArtJvmTiEnv::AsArtJvmTiEnv(env)->event_callbacks = std::move(tmp);
+
+    return ERR(NONE);
+  }
+
+  static jvmtiError SetEventNotificationMode(jvmtiEnv* env,
+                                             jvmtiEventMode mode,
+                                             jvmtiEvent event_type,
+                                             jthread event_thread,
+                                             ...) {
+    ENSURE_VALID_ENV(env);
+    art::Thread* art_thread = nullptr;
+    if (event_thread != nullptr) {
+      // TODO: Need non-aborting call here, to return JVMTI_ERROR_INVALID_THREAD.
+      art::ScopedObjectAccess soa(art::Thread::Current());
+      art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
+      art_thread = art::Thread::FromManagedThread(soa, event_thread);
+
+      if (art_thread == nullptr ||  // The thread hasn't been started or is already dead.
+          art_thread->IsStillStarting()) {
+        // TODO: We may want to let the EventHandler know, so it could clean up masks, potentially.
+        return ERR(THREAD_NOT_ALIVE);
+      }
+    }
+
+    ArtJvmTiEnv* art_env = ArtJvmTiEnv::AsArtJvmTiEnv(env);
+    return gEventHandler.SetEvent(art_env, art_thread, GetArtJvmtiEvent(art_env, event_type), mode);
+  }
+
+  static jvmtiError GenerateEvents(jvmtiEnv* env,
+                                   jvmtiEvent event_type ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    return OK;
+  }
+
+  static jvmtiError GetExtensionFunctions(jvmtiEnv* env,
+                                          jint* extension_count_ptr,
+                                          jvmtiExtensionFunctionInfo** extensions) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_NON_NULL(extension_count_ptr);
+    ENSURE_NON_NULL(extensions);
+
+    std::vector<jvmtiExtensionFunctionInfo> ext_vector;
+
+    // Holders for allocated values.
+    std::vector<JvmtiUniquePtr<char[]>> char_buffers;
+    std::vector<JvmtiUniquePtr<jvmtiParamInfo[]>> param_buffers;
+    std::vector<JvmtiUniquePtr<jvmtiError[]>> error_buffers;
+
+    // Add a helper struct that takes an arbitrary const char*. add_extension will use Allocate
+    // appropriately.
+    struct CParamInfo {
+      const char* name;
+      jvmtiParamKind kind;
+      jvmtiParamTypes base_type;
+      jboolean null_ok;
+    };
+
+    auto add_extension = [&](jvmtiExtensionFunction func,
+                             const char* id,
+                             const char* short_description,
+                             jint param_count,
+                             const std::vector<CParamInfo>& params,
+                             jint error_count,
+                             const std::vector<jvmtiError>& errors) {
+      jvmtiExtensionFunctionInfo func_info;
+      jvmtiError error;
+
+      func_info.func = func;
+
+      JvmtiUniquePtr<char[]> id_ptr = CopyString(env, id, &error);
+      if (id_ptr == nullptr) {
+        return error;
+      }
+      func_info.id = id_ptr.get();
+      char_buffers.push_back(std::move(id_ptr));
+
+      JvmtiUniquePtr<char[]> descr = CopyString(env, short_description, &error);
+      if (descr == nullptr) {
+        return error;
+      }
+      func_info.short_description = descr.get();
+      char_buffers.push_back(std::move(descr));
+
+      func_info.param_count = param_count;
+      if (param_count > 0) {
+        JvmtiUniquePtr<jvmtiParamInfo[]> params_ptr =
+            AllocJvmtiUniquePtr<jvmtiParamInfo[]>(env, param_count, &error);
+        if (params_ptr == nullptr) {
+          return error;
+        }
+        func_info.params = params_ptr.get();
+        param_buffers.push_back(std::move(params_ptr));
+
+        for (jint i = 0; i != param_count; ++i) {
+          JvmtiUniquePtr<char[]> param_name = CopyString(env, params[i].name, &error);
+          if (param_name == nullptr) {
+            return error;
+          }
+          func_info.params[i].name = param_name.get();
+          char_buffers.push_back(std::move(param_name));
+
+          func_info.params[i].kind = params[i].kind;
+          func_info.params[i].base_type = params[i].base_type;
+          func_info.params[i].null_ok = params[i].null_ok;
+        }
+      } else {
+        func_info.params = nullptr;
+      }
+
+      func_info.error_count = error_count;
+      if (error_count > 0) {
+        JvmtiUniquePtr<jvmtiError[]> errors_ptr =
+            AllocJvmtiUniquePtr<jvmtiError[]>(env, error_count, &error);
+        if (errors_ptr == nullptr) {
+          return error;
+        }
+        func_info.errors = errors_ptr.get();
+        error_buffers.push_back(std::move(errors_ptr));
+
+        for (jint i = 0; i != error_count; ++i) {
+          func_info.errors[i] = errors[i];
+        }
+      } else {
+        func_info.errors = nullptr;
+      }
+
+      ext_vector.push_back(func_info);
+
+      return ERR(NONE);
+    };
+
+    jvmtiError error;
+
+    // Heap extensions.
+    error = add_extension(
+        reinterpret_cast<jvmtiExtensionFunction>(HeapExtensions::GetObjectHeapId),
+        "com.android.art.heap.get_object_heap_id",
+        "Retrieve the heap id of the the object tagged with the given argument. An "
+            "arbitrary object is chosen if multiple objects exist with the same tag.",
+        2,
+        {                                                          // NOLINT [whitespace/braces] [4]
+            { "tag", JVMTI_KIND_IN, JVMTI_TYPE_JLONG, false},
+            { "heap_id", JVMTI_KIND_OUT, JVMTI_TYPE_JINT, false}
+        },
+        1,
+        { JVMTI_ERROR_NOT_FOUND });
+    if (error != ERR(NONE)) {
+      return error;
+    }
+
+    error = add_extension(
+        reinterpret_cast<jvmtiExtensionFunction>(HeapExtensions::GetHeapName),
+        "com.android.art.heap.get_heap_name",
+        "Retrieve the name of the heap with the given id.",
+        2,
+        {                                                          // NOLINT [whitespace/braces] [4]
+            { "heap_id", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false},
+            { "heap_name", JVMTI_KIND_ALLOC_BUF, JVMTI_TYPE_CCHAR, false}
+        },
+        1,
+        { JVMTI_ERROR_ILLEGAL_ARGUMENT });
+    if (error != ERR(NONE)) {
+      return error;
+    }
+
+    error = add_extension(
+        reinterpret_cast<jvmtiExtensionFunction>(HeapExtensions::IterateThroughHeapExt),
+        "com.android.art.heap.iterate_through_heap_ext",
+        "Iterate through a heap. This is equivalent to the standard IterateThroughHeap function,"
+        " except for additionally passing the heap id of the current object. The jvmtiHeapCallbacks"
+        " structure is reused, with the callbacks field overloaded to a signature of "
+        "jint (*)(jlong, jlong, jlong*, jint length, void*, jint).",
+        4,
+        {                                                          // NOLINT [whitespace/braces] [4]
+            { "heap_filter", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false},
+            { "klass", JVMTI_KIND_IN, JVMTI_TYPE_JCLASS, true},
+            { "callbacks", JVMTI_KIND_IN_PTR, JVMTI_TYPE_CVOID, false},
+            { "user_data", JVMTI_KIND_IN_PTR, JVMTI_TYPE_CVOID, true}
+        },
+        3,
+        {                                                          // NOLINT [whitespace/braces] [4]
+            JVMTI_ERROR_MUST_POSSESS_CAPABILITY,
+            JVMTI_ERROR_INVALID_CLASS,
+            JVMTI_ERROR_NULL_POINTER
+        });
+    if (error != ERR(NONE)) {
+      return error;
+    }
+
+    error = add_extension(
+        reinterpret_cast<jvmtiExtensionFunction>(AllocUtil::GetGlobalJvmtiAllocationState),
+        "com.android.art.alloc.get_global_jvmti_allocation_state",
+        "Returns the total amount of memory currently allocated by all jvmtiEnvs through the"
+        " 'Allocate' jvmti function. This does not include any memory that has been deallocated"
+        " through the 'Deallocate' function. This number is approximate and might not correspond"
+        " exactly to the sum of the sizes of all not freed allocations.",
+        1,
+        {                                                          // NOLINT [whitespace/braces] [4]
+            { "currently_allocated", JVMTI_KIND_OUT, JVMTI_TYPE_JLONG, false},
+        },
+        1,
+        { ERR(NULL_POINTER) });
+    if (error != ERR(NONE)) {
+      return error;
+    }
+
+    // Copy into output buffer.
+
+    *extension_count_ptr = ext_vector.size();
+    JvmtiUniquePtr<jvmtiExtensionFunctionInfo[]> out_data =
+        AllocJvmtiUniquePtr<jvmtiExtensionFunctionInfo[]>(env, ext_vector.size(), &error);
+    if (out_data == nullptr) {
+      return error;
+    }
+    memcpy(out_data.get(),
+           ext_vector.data(),
+           ext_vector.size() * sizeof(jvmtiExtensionFunctionInfo));
+    *extensions = out_data.release();
+
+    // Release all the buffer holders, we're OK now.
+    for (auto& holder : char_buffers) {
+      holder.release();
+    }
+    for (auto& holder : param_buffers) {
+      holder.release();
+    }
+    for (auto& holder : error_buffers) {
+      holder.release();
+    }
+
+    return ERR(NONE);
+  }
+
+  static jvmtiError GetExtensionEvents(jvmtiEnv* env,
+                                       jint* extension_count_ptr,
+                                       jvmtiExtensionEventInfo** extensions) {
+    ENSURE_VALID_ENV(env);
+    // We do not have any extension events.
+    *extension_count_ptr = 0;
+    *extensions = nullptr;
+
+    return ERR(NONE);
+  }
+
+  static jvmtiError SetExtensionEventCallback(jvmtiEnv* env,
+                                              jint extension_event_index ATTRIBUTE_UNUSED,
+                                              jvmtiExtensionEvent callback ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    // We do not have any extension events, so any call is illegal.
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+
+  static jvmtiError GetPotentialCapabilities(jvmtiEnv* env, jvmtiCapabilities* capabilities_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_NON_NULL(capabilities_ptr);
+    *capabilities_ptr = kPotentialCapabilities;
+    return OK;
+  }
+
+  static jvmtiError AddCapabilities(jvmtiEnv* env, const jvmtiCapabilities* capabilities_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_NON_NULL(capabilities_ptr);
+    ArtJvmTiEnv* art_env = static_cast<ArtJvmTiEnv*>(env);
+    jvmtiError ret = OK;
+    jvmtiCapabilities changed = {};
+    jvmtiCapabilities potential_capabilities = {};
+    ret = env->GetPotentialCapabilities(&potential_capabilities);
+    if (ret != OK) {
+      return ret;
+    }
+#define ADD_CAPABILITY(e) \
+    do { \
+      if (capabilities_ptr->e == 1) { \
+        if (potential_capabilities.e == 1) { \
+          if (art_env->capabilities.e != 1) { \
+            art_env->capabilities.e = 1; \
+            changed.e = 1; \
+          }\
+        } else { \
+          ret = ERR(NOT_AVAILABLE); \
+        } \
+      } \
+    } while (false)
+
+    ADD_CAPABILITY(can_tag_objects);
+    ADD_CAPABILITY(can_generate_field_modification_events);
+    ADD_CAPABILITY(can_generate_field_access_events);
+    ADD_CAPABILITY(can_get_bytecodes);
+    ADD_CAPABILITY(can_get_synthetic_attribute);
+    ADD_CAPABILITY(can_get_owned_monitor_info);
+    ADD_CAPABILITY(can_get_current_contended_monitor);
+    ADD_CAPABILITY(can_get_monitor_info);
+    ADD_CAPABILITY(can_pop_frame);
+    ADD_CAPABILITY(can_redefine_classes);
+    ADD_CAPABILITY(can_signal_thread);
+    ADD_CAPABILITY(can_get_source_file_name);
+    ADD_CAPABILITY(can_get_line_numbers);
+    ADD_CAPABILITY(can_get_source_debug_extension);
+    ADD_CAPABILITY(can_access_local_variables);
+    ADD_CAPABILITY(can_maintain_original_method_order);
+    ADD_CAPABILITY(can_generate_single_step_events);
+    ADD_CAPABILITY(can_generate_exception_events);
+    ADD_CAPABILITY(can_generate_frame_pop_events);
+    ADD_CAPABILITY(can_generate_breakpoint_events);
+    ADD_CAPABILITY(can_suspend);
+    ADD_CAPABILITY(can_redefine_any_class);
+    ADD_CAPABILITY(can_get_current_thread_cpu_time);
+    ADD_CAPABILITY(can_get_thread_cpu_time);
+    ADD_CAPABILITY(can_generate_method_entry_events);
+    ADD_CAPABILITY(can_generate_method_exit_events);
+    ADD_CAPABILITY(can_generate_all_class_hook_events);
+    ADD_CAPABILITY(can_generate_compiled_method_load_events);
+    ADD_CAPABILITY(can_generate_monitor_events);
+    ADD_CAPABILITY(can_generate_vm_object_alloc_events);
+    ADD_CAPABILITY(can_generate_native_method_bind_events);
+    ADD_CAPABILITY(can_generate_garbage_collection_events);
+    ADD_CAPABILITY(can_generate_object_free_events);
+    ADD_CAPABILITY(can_force_early_return);
+    ADD_CAPABILITY(can_get_owned_monitor_stack_depth_info);
+    ADD_CAPABILITY(can_get_constant_pool);
+    ADD_CAPABILITY(can_set_native_method_prefix);
+    ADD_CAPABILITY(can_retransform_classes);
+    ADD_CAPABILITY(can_retransform_any_class);
+    ADD_CAPABILITY(can_generate_resource_exhaustion_heap_events);
+    ADD_CAPABILITY(can_generate_resource_exhaustion_threads_events);
+#undef ADD_CAPABILITY
+    gEventHandler.HandleChangedCapabilities(ArtJvmTiEnv::AsArtJvmTiEnv(env),
+                                            changed,
+                                            /*added*/true);
+    return ret;
+  }
+
+  static jvmtiError RelinquishCapabilities(jvmtiEnv* env,
+                                           const jvmtiCapabilities* capabilities_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_NON_NULL(capabilities_ptr);
+    ArtJvmTiEnv* art_env = reinterpret_cast<ArtJvmTiEnv*>(env);
+    jvmtiCapabilities changed = {};
+#define DEL_CAPABILITY(e) \
+    do { \
+      if (capabilities_ptr->e == 1) { \
+        if (art_env->capabilities.e == 1) { \
+          art_env->capabilities.e = 0;\
+          changed.e = 1; \
+        } \
+      } \
+    } while (false)
+
+    DEL_CAPABILITY(can_tag_objects);
+    DEL_CAPABILITY(can_generate_field_modification_events);
+    DEL_CAPABILITY(can_generate_field_access_events);
+    DEL_CAPABILITY(can_get_bytecodes);
+    DEL_CAPABILITY(can_get_synthetic_attribute);
+    DEL_CAPABILITY(can_get_owned_monitor_info);
+    DEL_CAPABILITY(can_get_current_contended_monitor);
+    DEL_CAPABILITY(can_get_monitor_info);
+    DEL_CAPABILITY(can_pop_frame);
+    DEL_CAPABILITY(can_redefine_classes);
+    DEL_CAPABILITY(can_signal_thread);
+    DEL_CAPABILITY(can_get_source_file_name);
+    DEL_CAPABILITY(can_get_line_numbers);
+    DEL_CAPABILITY(can_get_source_debug_extension);
+    DEL_CAPABILITY(can_access_local_variables);
+    DEL_CAPABILITY(can_maintain_original_method_order);
+    DEL_CAPABILITY(can_generate_single_step_events);
+    DEL_CAPABILITY(can_generate_exception_events);
+    DEL_CAPABILITY(can_generate_frame_pop_events);
+    DEL_CAPABILITY(can_generate_breakpoint_events);
+    DEL_CAPABILITY(can_suspend);
+    DEL_CAPABILITY(can_redefine_any_class);
+    DEL_CAPABILITY(can_get_current_thread_cpu_time);
+    DEL_CAPABILITY(can_get_thread_cpu_time);
+    DEL_CAPABILITY(can_generate_method_entry_events);
+    DEL_CAPABILITY(can_generate_method_exit_events);
+    DEL_CAPABILITY(can_generate_all_class_hook_events);
+    DEL_CAPABILITY(can_generate_compiled_method_load_events);
+    DEL_CAPABILITY(can_generate_monitor_events);
+    DEL_CAPABILITY(can_generate_vm_object_alloc_events);
+    DEL_CAPABILITY(can_generate_native_method_bind_events);
+    DEL_CAPABILITY(can_generate_garbage_collection_events);
+    DEL_CAPABILITY(can_generate_object_free_events);
+    DEL_CAPABILITY(can_force_early_return);
+    DEL_CAPABILITY(can_get_owned_monitor_stack_depth_info);
+    DEL_CAPABILITY(can_get_constant_pool);
+    DEL_CAPABILITY(can_set_native_method_prefix);
+    DEL_CAPABILITY(can_retransform_classes);
+    DEL_CAPABILITY(can_retransform_any_class);
+    DEL_CAPABILITY(can_generate_resource_exhaustion_heap_events);
+    DEL_CAPABILITY(can_generate_resource_exhaustion_threads_events);
+#undef DEL_CAPABILITY
+    gEventHandler.HandleChangedCapabilities(ArtJvmTiEnv::AsArtJvmTiEnv(env),
+                                            changed,
+                                            /*added*/false);
+    return OK;
+  }
+
+  static jvmtiError GetCapabilities(jvmtiEnv* env, jvmtiCapabilities* capabilities_ptr) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_NON_NULL(capabilities_ptr);
+    ArtJvmTiEnv* artenv = reinterpret_cast<ArtJvmTiEnv*>(env);
+    *capabilities_ptr = artenv->capabilities;
+    return OK;
+  }
+
+  static jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiEnv* env,
+                                                 jvmtiTimerInfo* info_ptr ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_current_thread_cpu_time);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError GetCurrentThreadCpuTime(jvmtiEnv* env, jlong* nanos_ptr ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_current_thread_cpu_time);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError GetThreadCpuTimerInfo(jvmtiEnv* env,
+                                          jvmtiTimerInfo* info_ptr ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_thread_cpu_time);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError GetThreadCpuTime(jvmtiEnv* env,
+                                     jthread thread ATTRIBUTE_UNUSED,
+                                     jlong* nanos_ptr ATTRIBUTE_UNUSED) {
+    ENSURE_VALID_ENV(env);
+    ENSURE_HAS_CAP(env, can_get_thread_cpu_time);
+    return ERR(NOT_IMPLEMENTED);
+  }
+
+  static jvmtiError GetTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr) {
+    ENSURE_VALID_ENV(env);
+    return TimerUtil::GetTimerInfo(env, info_ptr);
+  }
+
+  static jvmtiError GetTime(jvmtiEnv* env, jlong* nanos_ptr) {
+    ENSURE_VALID_ENV(env);
+    return TimerUtil::GetTime(env, nanos_ptr);
+  }
+
+  static jvmtiError GetAvailableProcessors(jvmtiEnv* env, jint* processor_count_ptr) {
+    ENSURE_VALID_ENV(env);
+    return TimerUtil::GetAvailableProcessors(env, processor_count_ptr);
+  }
+
+  static jvmtiError AddToBootstrapClassLoaderSearch(jvmtiEnv* env, const char* segment) {
+    ENSURE_VALID_ENV(env);
+    return SearchUtil::AddToBootstrapClassLoaderSearch(env, segment);
+  }
+
+  static jvmtiError AddToSystemClassLoaderSearch(jvmtiEnv* env, const char* segment) {
+    ENSURE_VALID_ENV(env);
+    return SearchUtil::AddToSystemClassLoaderSearch(env, segment);
+  }
+
+  static jvmtiError GetSystemProperties(jvmtiEnv* env, jint* count_ptr, char*** property_ptr) {
+    ENSURE_VALID_ENV(env);
+    return PropertiesUtil::GetSystemProperties(env, count_ptr, property_ptr);
+  }
+
+  static jvmtiError GetSystemProperty(jvmtiEnv* env, const char* property, char** value_ptr) {
+    ENSURE_VALID_ENV(env);
+    return PropertiesUtil::GetSystemProperty(env, property, value_ptr);
+  }
+
+  static jvmtiError SetSystemProperty(jvmtiEnv* env, const char* property, const char* value) {
+    ENSURE_VALID_ENV(env);
+    return PropertiesUtil::SetSystemProperty(env, property, value);
+  }
+
+  static jvmtiError GetPhase(jvmtiEnv* env, jvmtiPhase* phase_ptr) {
+    ENSURE_VALID_ENV(env);
+    return PhaseUtil::GetPhase(env, phase_ptr);
+  }
+
+  static jvmtiError DisposeEnvironment(jvmtiEnv* env) {
+    ENSURE_VALID_ENV(env);
+    ArtJvmTiEnv* tienv = ArtJvmTiEnv::AsArtJvmTiEnv(env);
+    gEventHandler.RemoveArtJvmTiEnv(tienv);
+    art::Runtime::Current()->RemoveSystemWeakHolder(tienv->object_tag_table.get());
+    ThreadUtil::RemoveEnvironment(tienv);
+    delete tienv;
+    return OK;
+  }
+
+  static jvmtiError SetEnvironmentLocalStorage(jvmtiEnv* env, const void* data) {
+    ENSURE_VALID_ENV(env);
+    reinterpret_cast<ArtJvmTiEnv*>(env)->local_data = const_cast<void*>(data);
+    return OK;
+  }
+
+  static jvmtiError GetEnvironmentLocalStorage(jvmtiEnv* env, void** data_ptr) {
+    ENSURE_VALID_ENV(env);
+    *data_ptr = reinterpret_cast<ArtJvmTiEnv*>(env)->local_data;
+    return OK;
+  }
+
+  static jvmtiError GetVersionNumber(jvmtiEnv* env, jint* version_ptr) {
+    ENSURE_VALID_ENV(env);
+    *version_ptr = JVMTI_VERSION;
+    return OK;
+  }
+
+  static jvmtiError GetErrorName(jvmtiEnv* env, jvmtiError error,  char** name_ptr) {
+    ENSURE_NON_NULL(name_ptr);
+    auto copy_fn = [&](const char* name_cstr) {
+      jvmtiError res;
+      JvmtiUniquePtr<char[]> copy = CopyString(env, name_cstr, &res);
+      if (copy == nullptr) {
+        *name_ptr = nullptr;
+        return res;
+      } else {
+        *name_ptr = copy.release();
+        return OK;
+      }
+    };
+    switch (error) {
+#define ERROR_CASE(e) case (JVMTI_ERROR_ ## e) : \
+        return copy_fn("JVMTI_ERROR_"#e);
+      ERROR_CASE(NONE);
+      ERROR_CASE(INVALID_THREAD);
+      ERROR_CASE(INVALID_THREAD_GROUP);
+      ERROR_CASE(INVALID_PRIORITY);
+      ERROR_CASE(THREAD_NOT_SUSPENDED);
+      ERROR_CASE(THREAD_SUSPENDED);
+      ERROR_CASE(THREAD_NOT_ALIVE);
+      ERROR_CASE(INVALID_OBJECT);
+      ERROR_CASE(INVALID_CLASS);
+      ERROR_CASE(CLASS_NOT_PREPARED);
+      ERROR_CASE(INVALID_METHODID);
+      ERROR_CASE(INVALID_LOCATION);
+      ERROR_CASE(INVALID_FIELDID);
+      ERROR_CASE(NO_MORE_FRAMES);
+      ERROR_CASE(OPAQUE_FRAME);
+      ERROR_CASE(TYPE_MISMATCH);
+      ERROR_CASE(INVALID_SLOT);
+      ERROR_CASE(DUPLICATE);
+      ERROR_CASE(NOT_FOUND);
+      ERROR_CASE(INVALID_MONITOR);
+      ERROR_CASE(NOT_MONITOR_OWNER);
+      ERROR_CASE(INTERRUPT);
+      ERROR_CASE(INVALID_CLASS_FORMAT);
+      ERROR_CASE(CIRCULAR_CLASS_DEFINITION);
+      ERROR_CASE(FAILS_VERIFICATION);
+      ERROR_CASE(UNSUPPORTED_REDEFINITION_METHOD_ADDED);
+      ERROR_CASE(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED);
+      ERROR_CASE(INVALID_TYPESTATE);
+      ERROR_CASE(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED);
+      ERROR_CASE(UNSUPPORTED_REDEFINITION_METHOD_DELETED);
+      ERROR_CASE(UNSUPPORTED_VERSION);
+      ERROR_CASE(NAMES_DONT_MATCH);
+      ERROR_CASE(UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED);
+      ERROR_CASE(UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED);
+      ERROR_CASE(UNMODIFIABLE_CLASS);
+      ERROR_CASE(NOT_AVAILABLE);
+      ERROR_CASE(MUST_POSSESS_CAPABILITY);
+      ERROR_CASE(NULL_POINTER);
+      ERROR_CASE(ABSENT_INFORMATION);
+      ERROR_CASE(INVALID_EVENT_TYPE);
+      ERROR_CASE(ILLEGAL_ARGUMENT);
+      ERROR_CASE(NATIVE_METHOD);
+      ERROR_CASE(CLASS_LOADER_UNSUPPORTED);
+      ERROR_CASE(OUT_OF_MEMORY);
+      ERROR_CASE(ACCESS_DENIED);
+      ERROR_CASE(WRONG_PHASE);
+      ERROR_CASE(INTERNAL);
+      ERROR_CASE(UNATTACHED_THREAD);
+      ERROR_CASE(INVALID_ENVIRONMENT);
+#undef ERROR_CASE
+    }
+
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+
+  static jvmtiError SetVerboseFlag(jvmtiEnv* env,
+                                   jvmtiVerboseFlag flag,
+                                   jboolean value) {
+    ENSURE_VALID_ENV(env);
+    if (flag == jvmtiVerboseFlag::JVMTI_VERBOSE_OTHER) {
+      // OTHER is special, as it's 0, so can't do a bit check.
+      bool val = (value == JNI_TRUE) ? true : false;
+
+      art::gLogVerbosity.collector = val;
+      art::gLogVerbosity.compiler = val;
+      art::gLogVerbosity.deopt = val;
+      art::gLogVerbosity.heap = val;
+      art::gLogVerbosity.jdwp = val;
+      art::gLogVerbosity.jit = val;
+      art::gLogVerbosity.monitor = val;
+      art::gLogVerbosity.oat = val;
+      art::gLogVerbosity.profiler = val;
+      art::gLogVerbosity.signals = val;
+      art::gLogVerbosity.simulator = val;
+      art::gLogVerbosity.startup = val;
+      art::gLogVerbosity.third_party_jni = val;
+      art::gLogVerbosity.threads = val;
+      art::gLogVerbosity.verifier = val;
+      art::gLogVerbosity.image = val;
+
+      // Note: can't switch systrace_lock_logging. That requires changing entrypoints.
+
+      art::gLogVerbosity.agents = val;
+    } else {
+      // Spec isn't clear whether "flag" is a mask or supposed to be single. We implement the mask
+      // semantics.
+      constexpr std::underlying_type<jvmtiVerboseFlag>::type kMask =
+          jvmtiVerboseFlag::JVMTI_VERBOSE_GC |
+          jvmtiVerboseFlag::JVMTI_VERBOSE_CLASS |
+          jvmtiVerboseFlag::JVMTI_VERBOSE_JNI;
+      if ((flag & ~kMask) != 0) {
+        return ERR(ILLEGAL_ARGUMENT);
+      }
+
+      bool val = (value == JNI_TRUE) ? true : false;
+
+      if ((flag & jvmtiVerboseFlag::JVMTI_VERBOSE_GC) != 0) {
+        art::gLogVerbosity.gc = val;
+      }
+
+      if ((flag & jvmtiVerboseFlag::JVMTI_VERBOSE_CLASS) != 0) {
+        art::gLogVerbosity.class_linker = val;
+      }
+
+      if ((flag & jvmtiVerboseFlag::JVMTI_VERBOSE_JNI) != 0) {
+        art::gLogVerbosity.jni = val;
+      }
+    }
+
+    return ERR(NONE);
+  }
+
+  static jvmtiError GetJLocationFormat(jvmtiEnv* env, jvmtiJlocationFormat* format_ptr) {
+    ENSURE_VALID_ENV(env);
+    // Report BCI as jlocation format. We report dex bytecode indices.
+    if (format_ptr == nullptr) {
+      return ERR(NULL_POINTER);
+    }
+    *format_ptr = jvmtiJlocationFormat::JVMTI_JLOCATION_JVMBCI;
+    return ERR(NONE);
+  }
+};
+
+static bool IsJvmtiVersion(jint version) {
+  return version ==  JVMTI_VERSION_1 ||
+         version == JVMTI_VERSION_1_0 ||
+         version == JVMTI_VERSION_1_1 ||
+         version == JVMTI_VERSION_1_2 ||
+         version == JVMTI_VERSION;
+}
+
+extern const jvmtiInterface_1 gJvmtiInterface;
+
+ArtJvmTiEnv::ArtJvmTiEnv(art::JavaVMExt* runtime, EventHandler* event_handler)
+    : art_vm(runtime),
+      local_data(nullptr),
+      capabilities() {
+  object_tag_table = std::unique_ptr<ObjectTagTable>(new ObjectTagTable(event_handler, this));
+  functions = &gJvmtiInterface;
+}
+
+// Creates a jvmtiEnv and returns it with the art::ti::Env that is associated with it. new_art_ti
+// is a pointer to the uninitialized memory for an art::ti::Env.
+static void CreateArtJvmTiEnv(art::JavaVMExt* vm, /*out*/void** new_jvmtiEnv) {
+  struct ArtJvmTiEnv* env = new ArtJvmTiEnv(vm, &gEventHandler);
+  *new_jvmtiEnv = env;
+
+  gEventHandler.RegisterArtJvmTiEnv(env);
+
+  art::Runtime::Current()->AddSystemWeakHolder(
+      ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get());
+}
+
+// A hook that the runtime uses to allow plugins to handle GetEnv calls. It returns true and
+// places the return value in 'env' if this library can handle the GetEnv request. Otherwise
+// returns false and does not modify the 'env' pointer.
+static jint GetEnvHandler(art::JavaVMExt* vm, /*out*/void** env, jint version) {
+  if (IsJvmtiVersion(version)) {
+    CreateArtJvmTiEnv(vm, env);
+    return JNI_OK;
+  } else {
+    printf("version 0x%x is not valid!", version);
+    return JNI_EVERSION;
+  }
+}
+
+// The plugin initialization function. This adds the jvmti environment.
+extern "C" bool ArtPlugin_Initialize() {
+  art::Runtime* runtime = art::Runtime::Current();
+
+  if (runtime->IsStarted()) {
+    PhaseUtil::SetToLive();
+  } else {
+    PhaseUtil::SetToOnLoad();
+  }
+  PhaseUtil::Register(&gEventHandler);
+  ThreadUtil::Register(&gEventHandler);
+  ClassUtil::Register(&gEventHandler);
+  DumpUtil::Register(&gEventHandler);
+  MethodUtil::Register(&gEventHandler);
+  SearchUtil::Register();
+  HeapUtil::Register();
+
+  runtime->GetJavaVM()->AddEnvironmentHook(GetEnvHandler);
+
+  return true;
+}
+
+extern "C" bool ArtPlugin_Deinitialize() {
+  gEventHandler.Shutdown();
+  PhaseUtil::Unregister();
+  ThreadUtil::Unregister();
+  ClassUtil::Unregister();
+  DumpUtil::Unregister();
+  MethodUtil::Unregister();
+  SearchUtil::Unregister();
+  HeapUtil::Unregister();
+
+  return true;
+}
+
+// The actual struct holding all of the entrypoints into the jvmti interface.
+const jvmtiInterface_1 gJvmtiInterface = {
+  nullptr,  // reserved1
+  JvmtiFunctions::SetEventNotificationMode,
+  nullptr,  // reserved3
+  JvmtiFunctions::GetAllThreads,
+  JvmtiFunctions::SuspendThread,
+  JvmtiFunctions::ResumeThread,
+  JvmtiFunctions::StopThread,
+  JvmtiFunctions::InterruptThread,
+  JvmtiFunctions::GetThreadInfo,
+  JvmtiFunctions::GetOwnedMonitorInfo,  // 10
+  JvmtiFunctions::GetCurrentContendedMonitor,
+  JvmtiFunctions::RunAgentThread,
+  JvmtiFunctions::GetTopThreadGroups,
+  JvmtiFunctions::GetThreadGroupInfo,
+  JvmtiFunctions::GetThreadGroupChildren,
+  JvmtiFunctions::GetFrameCount,
+  JvmtiFunctions::GetThreadState,
+  JvmtiFunctions::GetCurrentThread,
+  JvmtiFunctions::GetFrameLocation,
+  JvmtiFunctions::NotifyFramePop,  // 20
+  JvmtiFunctions::GetLocalObject,
+  JvmtiFunctions::GetLocalInt,
+  JvmtiFunctions::GetLocalLong,
+  JvmtiFunctions::GetLocalFloat,
+  JvmtiFunctions::GetLocalDouble,
+  JvmtiFunctions::SetLocalObject,
+  JvmtiFunctions::SetLocalInt,
+  JvmtiFunctions::SetLocalLong,
+  JvmtiFunctions::SetLocalFloat,
+  JvmtiFunctions::SetLocalDouble,  // 30
+  JvmtiFunctions::CreateRawMonitor,
+  JvmtiFunctions::DestroyRawMonitor,
+  JvmtiFunctions::RawMonitorEnter,
+  JvmtiFunctions::RawMonitorExit,
+  JvmtiFunctions::RawMonitorWait,
+  JvmtiFunctions::RawMonitorNotify,
+  JvmtiFunctions::RawMonitorNotifyAll,
+  JvmtiFunctions::SetBreakpoint,
+  JvmtiFunctions::ClearBreakpoint,
+  nullptr,  // reserved40
+  JvmtiFunctions::SetFieldAccessWatch,
+  JvmtiFunctions::ClearFieldAccessWatch,
+  JvmtiFunctions::SetFieldModificationWatch,
+  JvmtiFunctions::ClearFieldModificationWatch,
+  JvmtiFunctions::IsModifiableClass,
+  JvmtiFunctions::Allocate,
+  JvmtiFunctions::Deallocate,
+  JvmtiFunctions::GetClassSignature,
+  JvmtiFunctions::GetClassStatus,
+  JvmtiFunctions::GetSourceFileName,  // 50
+  JvmtiFunctions::GetClassModifiers,
+  JvmtiFunctions::GetClassMethods,
+  JvmtiFunctions::GetClassFields,
+  JvmtiFunctions::GetImplementedInterfaces,
+  JvmtiFunctions::IsInterface,
+  JvmtiFunctions::IsArrayClass,
+  JvmtiFunctions::GetClassLoader,
+  JvmtiFunctions::GetObjectHashCode,
+  JvmtiFunctions::GetObjectMonitorUsage,
+  JvmtiFunctions::GetFieldName,  // 60
+  JvmtiFunctions::GetFieldDeclaringClass,
+  JvmtiFunctions::GetFieldModifiers,
+  JvmtiFunctions::IsFieldSynthetic,
+  JvmtiFunctions::GetMethodName,
+  JvmtiFunctions::GetMethodDeclaringClass,
+  JvmtiFunctions::GetMethodModifiers,
+  nullptr,  // reserved67
+  JvmtiFunctions::GetMaxLocals,
+  JvmtiFunctions::GetArgumentsSize,
+  JvmtiFunctions::GetLineNumberTable,  // 70
+  JvmtiFunctions::GetMethodLocation,
+  JvmtiFunctions::GetLocalVariableTable,
+  JvmtiFunctions::SetNativeMethodPrefix,
+  JvmtiFunctions::SetNativeMethodPrefixes,
+  JvmtiFunctions::GetBytecodes,
+  JvmtiFunctions::IsMethodNative,
+  JvmtiFunctions::IsMethodSynthetic,
+  JvmtiFunctions::GetLoadedClasses,
+  JvmtiFunctions::GetClassLoaderClasses,
+  JvmtiFunctions::PopFrame,  // 80
+  JvmtiFunctions::ForceEarlyReturnObject,
+  JvmtiFunctions::ForceEarlyReturnInt,
+  JvmtiFunctions::ForceEarlyReturnLong,
+  JvmtiFunctions::ForceEarlyReturnFloat,
+  JvmtiFunctions::ForceEarlyReturnDouble,
+  JvmtiFunctions::ForceEarlyReturnVoid,
+  JvmtiFunctions::RedefineClasses,
+  JvmtiFunctions::GetVersionNumber,
+  JvmtiFunctions::GetCapabilities,
+  JvmtiFunctions::GetSourceDebugExtension,  // 90
+  JvmtiFunctions::IsMethodObsolete,
+  JvmtiFunctions::SuspendThreadList,
+  JvmtiFunctions::ResumeThreadList,
+  nullptr,  // reserved94
+  nullptr,  // reserved95
+  nullptr,  // reserved96
+  nullptr,  // reserved97
+  nullptr,  // reserved98
+  nullptr,  // reserved99
+  JvmtiFunctions::GetAllStackTraces,  // 100
+  JvmtiFunctions::GetThreadListStackTraces,
+  JvmtiFunctions::GetThreadLocalStorage,
+  JvmtiFunctions::SetThreadLocalStorage,
+  JvmtiFunctions::GetStackTrace,
+  nullptr,  // reserved105
+  JvmtiFunctions::GetTag,
+  JvmtiFunctions::SetTag,
+  JvmtiFunctions::ForceGarbageCollection,
+  JvmtiFunctions::IterateOverObjectsReachableFromObject,
+  JvmtiFunctions::IterateOverReachableObjects,  // 110
+  JvmtiFunctions::IterateOverHeap,
+  JvmtiFunctions::IterateOverInstancesOfClass,
+  nullptr,  // reserved113
+  JvmtiFunctions::GetObjectsWithTags,
+  JvmtiFunctions::FollowReferences,
+  JvmtiFunctions::IterateThroughHeap,
+  nullptr,  // reserved117
+  nullptr,  // reserved118
+  nullptr,  // reserved119
+  JvmtiFunctions::SetJNIFunctionTable,  // 120
+  JvmtiFunctions::GetJNIFunctionTable,
+  JvmtiFunctions::SetEventCallbacks,
+  JvmtiFunctions::GenerateEvents,
+  JvmtiFunctions::GetExtensionFunctions,
+  JvmtiFunctions::GetExtensionEvents,
+  JvmtiFunctions::SetExtensionEventCallback,
+  JvmtiFunctions::DisposeEnvironment,
+  JvmtiFunctions::GetErrorName,
+  JvmtiFunctions::GetJLocationFormat,
+  JvmtiFunctions::GetSystemProperties,  // 130
+  JvmtiFunctions::GetSystemProperty,
+  JvmtiFunctions::SetSystemProperty,
+  JvmtiFunctions::GetPhase,
+  JvmtiFunctions::GetCurrentThreadCpuTimerInfo,
+  JvmtiFunctions::GetCurrentThreadCpuTime,
+  JvmtiFunctions::GetThreadCpuTimerInfo,
+  JvmtiFunctions::GetThreadCpuTime,
+  JvmtiFunctions::GetTimerInfo,
+  JvmtiFunctions::GetTime,
+  JvmtiFunctions::GetPotentialCapabilities,  // 140
+  nullptr,  // reserved141
+  JvmtiFunctions::AddCapabilities,
+  JvmtiFunctions::RelinquishCapabilities,
+  JvmtiFunctions::GetAvailableProcessors,
+  JvmtiFunctions::GetClassVersionNumbers,
+  JvmtiFunctions::GetConstantPool,
+  JvmtiFunctions::GetEnvironmentLocalStorage,
+  JvmtiFunctions::SetEnvironmentLocalStorage,
+  JvmtiFunctions::AddToBootstrapClassLoaderSearch,
+  JvmtiFunctions::SetVerboseFlag,  // 150
+  JvmtiFunctions::AddToSystemClassLoaderSearch,
+  JvmtiFunctions::RetransformClasses,
+  JvmtiFunctions::GetOwnedMonitorStackDepthInfo,
+  JvmtiFunctions::GetObjectSize,
+  JvmtiFunctions::GetLocalInstance,
+};
+
+};  // namespace openjdkjvmti
diff --git a/openjdkjvmti/README.md b/openjdkjvmti/README.md
new file mode 100644
index 0000000..b8bab57
--- /dev/null
+++ b/openjdkjvmti/README.md
@@ -0,0 +1,7 @@
+openjdkjvmti plugin
+====
+
+This is a partial implementation of the JVMTI v1.2 interface for the android
+runtime as a plugin. This allows the use of agents that can modify the running
+state of the program by modifying dex files in memory and performing other
+operations on the global runtime state.
diff --git a/openjdkjvmti/art_jvmti.h b/openjdkjvmti/art_jvmti.h
new file mode 100644
index 0000000..12f4cab
--- /dev/null
+++ b/openjdkjvmti/art_jvmti.h
@@ -0,0 +1,265 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_ART_JVMTI_H_
+#define ART_OPENJDKJVMTI_ART_JVMTI_H_
+
+#include <memory>
+#include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
+
+#include <jni.h>
+
+#include "base/casts.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/strlcpy.h"
+#include "events.h"
+#include "java_vm_ext.h"
+#include "jni_env_ext.h"
+#include "jvmti.h"
+#include "ti_breakpoint.h"
+
+namespace art {
+class ArtField;
+class ArtMethod;
+}  // namespace art
+
+namespace openjdkjvmti {
+
+class ObjectTagTable;
+
+// A structure that is a jvmtiEnv with additional information for the runtime.
+struct ArtJvmTiEnv : public jvmtiEnv {
+  art::JavaVMExt* art_vm;
+  void* local_data;
+  jvmtiCapabilities capabilities;
+
+  EventMasks event_masks;
+  std::unique_ptr<jvmtiEventCallbacks> event_callbacks;
+
+  // Tagging is specific to the jvmtiEnv.
+  std::unique_ptr<ObjectTagTable> object_tag_table;
+
+  // Set of watched fields is unique to each jvmtiEnv.
+  // TODO It might be good to follow the RI and only let one jvmtiEnv ever have the watch caps so
+  // we can record this on the field directly. We could do this either using free access-flag bits
+  // or by putting a list in the ClassExt of a field's DeclaringClass.
+  // TODO Maybe just have an extension to let one put a watch on every field, that would probably be
+  // good enough maybe since you probably want either a few or all/almost all of them.
+  std::unordered_set<art::ArtField*> access_watched_fields;
+  std::unordered_set<art::ArtField*> modify_watched_fields;
+
+  // Set of breakpoints is unique to each jvmtiEnv.
+  std::unordered_set<Breakpoint> breakpoints;
+
+  ArtJvmTiEnv(art::JavaVMExt* runtime, EventHandler* event_handler);
+
+  static ArtJvmTiEnv* AsArtJvmTiEnv(jvmtiEnv* env) {
+    return art::down_cast<ArtJvmTiEnv*>(env);
+  }
+};
+
+// Macro and constexpr to make error values less annoying to write.
+#define ERR(e) JVMTI_ERROR_ ## e
+static constexpr jvmtiError OK = JVMTI_ERROR_NONE;
+
+// Special error code for unimplemented functions in JVMTI
+static constexpr jvmtiError ERR(NOT_IMPLEMENTED) = JVMTI_ERROR_NOT_AVAILABLE;
+
+static inline JNIEnv* GetJniEnv(jvmtiEnv* env) {
+  JNIEnv* ret_value = nullptr;
+  jint res = reinterpret_cast<ArtJvmTiEnv*>(env)->art_vm->GetEnv(
+      reinterpret_cast<void**>(&ret_value), JNI_VERSION_1_1);
+  if (res != JNI_OK) {
+    return nullptr;
+  }
+  return ret_value;
+}
+
+template <typename T>
+class JvmtiDeleter {
+ public:
+  JvmtiDeleter() : env_(nullptr) {}
+  explicit JvmtiDeleter(jvmtiEnv* env) : env_(env) {}
+
+  JvmtiDeleter(JvmtiDeleter&) = default;
+  JvmtiDeleter(JvmtiDeleter&&) = default;
+  JvmtiDeleter& operator=(const JvmtiDeleter&) = default;
+
+  void operator()(T* ptr) const {
+    CHECK(env_ != nullptr);
+    jvmtiError ret = env_->Deallocate(reinterpret_cast<unsigned char*>(ptr));
+    CHECK(ret == ERR(NONE));
+  }
+
+ private:
+  mutable jvmtiEnv* env_;
+};
+
+template <typename T>
+class JvmtiDeleter<T[]> {
+  public:
+  JvmtiDeleter() : env_(nullptr) {}
+  explicit JvmtiDeleter(jvmtiEnv* env) : env_(env) {}
+
+  JvmtiDeleter(JvmtiDeleter&) = default;
+  JvmtiDeleter(JvmtiDeleter&&) = default;
+  JvmtiDeleter& operator=(const JvmtiDeleter&) = default;
+
+  template <typename U>
+  void operator()(U* ptr) const {
+    CHECK(env_ != nullptr);
+    jvmtiError ret = env_->Deallocate(reinterpret_cast<unsigned char*>(ptr));
+    CHECK(ret == ERR(NONE));
+  }
+
+ private:
+  mutable jvmtiEnv* env_;
+};
+
+template <typename T>
+using JvmtiUniquePtr = std::unique_ptr<T, JvmtiDeleter<T>>;
+
+template <typename T>
+ALWAYS_INLINE
+static inline JvmtiUniquePtr<T> MakeJvmtiUniquePtr(jvmtiEnv* env, T* mem) {
+  return JvmtiUniquePtr<T>(mem, JvmtiDeleter<T>(env));
+}
+
+template <typename T>
+ALWAYS_INLINE
+static inline JvmtiUniquePtr<T> MakeJvmtiUniquePtr(jvmtiEnv* env, unsigned char* mem) {
+  return JvmtiUniquePtr<T>(reinterpret_cast<T*>(mem), JvmtiDeleter<T>(env));
+}
+
+template <typename T>
+ALWAYS_INLINE
+static inline JvmtiUniquePtr<T> AllocJvmtiUniquePtr(jvmtiEnv* env, jvmtiError* error) {
+  unsigned char* tmp;
+  *error = env->Allocate(sizeof(T), &tmp);
+  if (*error != ERR(NONE)) {
+    return JvmtiUniquePtr<T>();
+  }
+  return JvmtiUniquePtr<T>(tmp, JvmtiDeleter<T>(env));
+}
+
+template <typename T>
+ALWAYS_INLINE
+static inline JvmtiUniquePtr<T> AllocJvmtiUniquePtr(jvmtiEnv* env,
+                                                    size_t count,
+                                                    jvmtiError* error) {
+  unsigned char* tmp;
+  *error = env->Allocate(sizeof(typename std::remove_extent<T>::type) * count, &tmp);
+  if (*error != ERR(NONE)) {
+    return JvmtiUniquePtr<T>();
+  }
+  return JvmtiUniquePtr<T>(reinterpret_cast<typename std::remove_extent<T>::type*>(tmp),
+                           JvmtiDeleter<T>(env));
+}
+
+ALWAYS_INLINE
+static inline jvmtiError CopyDataIntoJvmtiBuffer(ArtJvmTiEnv* env,
+                                                 const unsigned char* source,
+                                                 jint len,
+                                                 /*out*/unsigned char** dest) {
+  jvmtiError res = env->Allocate(len, dest);
+  if (res != OK) {
+    return res;
+  }
+  memcpy(reinterpret_cast<void*>(*dest),
+         reinterpret_cast<const void*>(source),
+         len);
+  return OK;
+}
+
+ALWAYS_INLINE
+static inline JvmtiUniquePtr<char[]> CopyString(jvmtiEnv* env, const char* src, jvmtiError* error) {
+  if (src == nullptr) {
+    JvmtiUniquePtr<char[]> ret = AllocJvmtiUniquePtr<char[]>(env, 0, error);
+    return ret;
+  }
+  size_t len = strlen(src) + 1;
+  JvmtiUniquePtr<char[]> ret = AllocJvmtiUniquePtr<char[]>(env, len, error);
+  if (ret != nullptr) {
+    strlcpy(ret.get(), src, len);
+  }
+  return ret;
+}
+
+const jvmtiCapabilities kPotentialCapabilities = {
+    .can_tag_objects                                 = 1,
+    .can_generate_field_modification_events          = 1,
+    .can_generate_field_access_events                = 1,
+    .can_get_bytecodes                               = 1,
+    .can_get_synthetic_attribute                     = 1,
+    .can_get_owned_monitor_info                      = 0,
+    .can_get_current_contended_monitor               = 0,
+    .can_get_monitor_info                            = 0,
+    .can_pop_frame                                   = 0,
+    .can_redefine_classes                            = 1,
+    .can_signal_thread                               = 0,
+    .can_get_source_file_name                        = 1,
+    .can_get_line_numbers                            = 1,
+    .can_get_source_debug_extension                  = 1,
+    .can_access_local_variables                      = 1,
+    .can_maintain_original_method_order              = 1,
+    .can_generate_single_step_events                 = 1,
+    .can_generate_exception_events                   = 0,
+    .can_generate_frame_pop_events                   = 0,
+    .can_generate_breakpoint_events                  = 1,
+    .can_suspend                                     = 1,
+    .can_redefine_any_class                          = 0,
+    .can_get_current_thread_cpu_time                 = 0,
+    .can_get_thread_cpu_time                         = 0,
+    .can_generate_method_entry_events                = 1,
+    .can_generate_method_exit_events                 = 1,
+    .can_generate_all_class_hook_events              = 0,
+    .can_generate_compiled_method_load_events        = 0,
+    .can_generate_monitor_events                     = 0,
+    .can_generate_vm_object_alloc_events             = 1,
+    .can_generate_native_method_bind_events          = 1,
+    .can_generate_garbage_collection_events          = 1,
+    .can_generate_object_free_events                 = 1,
+    .can_force_early_return                          = 0,
+    .can_get_owned_monitor_stack_depth_info          = 0,
+    .can_get_constant_pool                           = 0,
+    .can_set_native_method_prefix                    = 0,
+    .can_retransform_classes                         = 1,
+    .can_retransform_any_class                       = 0,
+    .can_generate_resource_exhaustion_heap_events    = 0,
+    .can_generate_resource_exhaustion_threads_events = 0,
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_ART_JVMTI_H_
diff --git a/openjdkjvmti/events-inl.h b/openjdkjvmti/events-inl.h
new file mode 100644
index 0000000..32dba3e
--- /dev/null
+++ b/openjdkjvmti/events-inl.h
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_OPENJDKJVMTI_EVENTS_INL_H_
+#define ART_OPENJDKJVMTI_EVENTS_INL_H_
+
+#include <array>
+
+#include "events.h"
+#include "jni_internal.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "ti_breakpoint.h"
+
+#include "art_jvmti.h"
+
+namespace openjdkjvmti {
+
+static inline ArtJvmtiEvent GetArtJvmtiEvent(ArtJvmTiEnv* env, jvmtiEvent e) {
+  if (UNLIKELY(e == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {
+    if (env->capabilities.can_retransform_classes) {
+      return ArtJvmtiEvent::kClassFileLoadHookRetransformable;
+    } else {
+      return ArtJvmtiEvent::kClassFileLoadHookNonRetransformable;
+    }
+  } else {
+    return static_cast<ArtJvmtiEvent>(e);
+  }
+}
+
+namespace impl {
+
+// Infrastructure to achieve type safety for event dispatch.
+
+#define FORALL_EVENT_TYPES(fn)                                                       \
+  fn(VMInit,                  ArtJvmtiEvent::kVmInit)                                \
+  fn(VMDeath,                 ArtJvmtiEvent::kVmDeath)                               \
+  fn(ThreadStart,             ArtJvmtiEvent::kThreadStart)                           \
+  fn(ThreadEnd,               ArtJvmtiEvent::kThreadEnd)                             \
+  fn(ClassFileLoadHook,       ArtJvmtiEvent::kClassFileLoadHookRetransformable)      \
+  fn(ClassFileLoadHook,       ArtJvmtiEvent::kClassFileLoadHookNonRetransformable)   \
+  fn(ClassLoad,               ArtJvmtiEvent::kClassLoad)                             \
+  fn(ClassPrepare,            ArtJvmtiEvent::kClassPrepare)                          \
+  fn(VMStart,                 ArtJvmtiEvent::kVmStart)                               \
+  fn(Exception,               ArtJvmtiEvent::kException)                             \
+  fn(ExceptionCatch,          ArtJvmtiEvent::kExceptionCatch)                        \
+  fn(SingleStep,              ArtJvmtiEvent::kSingleStep)                            \
+  fn(FramePop,                ArtJvmtiEvent::kFramePop)                              \
+  fn(Breakpoint,              ArtJvmtiEvent::kBreakpoint)                            \
+  fn(FieldAccess,             ArtJvmtiEvent::kFieldAccess)                           \
+  fn(FieldModification,       ArtJvmtiEvent::kFieldModification)                     \
+  fn(MethodEntry,             ArtJvmtiEvent::kMethodEntry)                           \
+  fn(MethodExit,              ArtJvmtiEvent::kMethodExit)                            \
+  fn(NativeMethodBind,        ArtJvmtiEvent::kNativeMethodBind)                      \
+  fn(CompiledMethodLoad,      ArtJvmtiEvent::kCompiledMethodLoad)                    \
+  fn(CompiledMethodUnload,    ArtJvmtiEvent::kCompiledMethodUnload)                  \
+  fn(DynamicCodeGenerated,    ArtJvmtiEvent::kDynamicCodeGenerated)                  \
+  fn(DataDumpRequest,         ArtJvmtiEvent::kDataDumpRequest)                       \
+  fn(MonitorWait,             ArtJvmtiEvent::kMonitorWait)                           \
+  fn(MonitorWaited,           ArtJvmtiEvent::kMonitorWaited)                         \
+  fn(MonitorContendedEnter,   ArtJvmtiEvent::kMonitorContendedEnter)                 \
+  fn(MonitorContendedEntered, ArtJvmtiEvent::kMonitorContendedEntered)               \
+  fn(ResourceExhausted,       ArtJvmtiEvent::kResourceExhausted)                     \
+  fn(GarbageCollectionStart,  ArtJvmtiEvent::kGarbageCollectionStart)                \
+  fn(GarbageCollectionFinish, ArtJvmtiEvent::kGarbageCollectionFinish)               \
+  fn(ObjectFree,              ArtJvmtiEvent::kObjectFree)                            \
+  fn(VMObjectAlloc,           ArtJvmtiEvent::kVmObjectAlloc)
+
+template <ArtJvmtiEvent kEvent>
+struct EventFnType {
+};
+
+#define EVENT_FN_TYPE(name, enum_name)               \
+template <>                                          \
+struct EventFnType<enum_name> {                      \
+  using type = decltype(jvmtiEventCallbacks().name); \
+};
+
+FORALL_EVENT_TYPES(EVENT_FN_TYPE)
+
+#undef EVENT_FN_TYPE
+
+template <ArtJvmtiEvent kEvent>
+ALWAYS_INLINE inline typename EventFnType<kEvent>::type GetCallback(ArtJvmTiEnv* env);
+
+#define GET_CALLBACK(name, enum_name)                                     \
+template <>                                                               \
+ALWAYS_INLINE inline EventFnType<enum_name>::type GetCallback<enum_name>( \
+    ArtJvmTiEnv* env) {                                                   \
+  if (env->event_callbacks == nullptr) {                                  \
+    return nullptr;                                                       \
+  }                                                                       \
+  return env->event_callbacks->name;                                      \
+}
+
+FORALL_EVENT_TYPES(GET_CALLBACK)
+
+#undef GET_CALLBACK
+
+#undef FORALL_EVENT_TYPES
+
+}  // namespace impl
+
+// C++ does not allow partial template function specialization. The dispatch for our separated
+// ClassFileLoadHook event types is the same, so use this helper for code deduplication.
+// TODO Locking of some type!
+template <ArtJvmtiEvent kEvent>
+inline void EventHandler::DispatchClassFileLoadHookEvent(art::Thread* thread,
+                                                         JNIEnv* jnienv,
+                                                         jclass class_being_redefined,
+                                                         jobject loader,
+                                                         const char* name,
+                                                         jobject protection_domain,
+                                                         jint class_data_len,
+                                                         const unsigned char* class_data,
+                                                         jint* new_class_data_len,
+                                                         unsigned char** new_class_data) const {
+  static_assert(kEvent == ArtJvmtiEvent::kClassFileLoadHookRetransformable ||
+                kEvent == ArtJvmtiEvent::kClassFileLoadHookNonRetransformable, "Unsupported event");
+  DCHECK(*new_class_data == nullptr);
+  jint current_len = class_data_len;
+  unsigned char* current_class_data = const_cast<unsigned char*>(class_data);
+  ArtJvmTiEnv* last_env = nullptr;
+  for (ArtJvmTiEnv* env : envs) {
+    if (env == nullptr) {
+      continue;
+    }
+    if (ShouldDispatch<kEvent>(env, thread)) {
+      ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred());
+      jnienv->ExceptionClear();
+      jint new_len = 0;
+      unsigned char* new_data = nullptr;
+      auto callback = impl::GetCallback<kEvent>(env);
+      callback(env,
+               jnienv,
+               class_being_redefined,
+               loader,
+               name,
+               protection_domain,
+               current_len,
+               current_class_data,
+               &new_len,
+               &new_data);
+      if (thr.get() != nullptr && !jnienv->ExceptionCheck()) {
+        jnienv->Throw(thr.get());
+      }
+      if (new_data != nullptr && new_data != current_class_data) {
+        // Destroy the data the last transformer made. We skip this if the previous state was the
+        // initial one since we don't know here which jvmtiEnv allocated it.
+        // NB Currently this doesn't matter since all allocations just go to malloc but in the
+        // future we might have jvmtiEnv's keep track of their allocations for leak-checking.
+        if (last_env != nullptr) {
+          last_env->Deallocate(current_class_data);
+        }
+        last_env = env;
+        current_class_data = new_data;
+        current_len = new_len;
+      }
+    }
+  }
+  if (last_env != nullptr) {
+    *new_class_data_len = current_len;
+    *new_class_data = current_class_data;
+  }
+}
+
+// Our goal for DispatchEvent: Do not allow implicit type conversion. Types of ...args must match
+// exactly the argument types of the corresponding Jvmti kEvent function pointer.
+
+template <ArtJvmtiEvent kEvent, typename ...Args>
+inline void EventHandler::DispatchEvent(art::Thread* thread, Args... args) const {
+  for (ArtJvmTiEnv* env : envs) {
+    if (env != nullptr) {
+      DispatchEvent<kEvent, Args...>(env, thread, args...);
+    }
+  }
+}
+
+// Events with JNIEnvs need to stash pending exceptions since they can cause new ones to be thrown.
+// In accordance with the JVMTI specification we allow exceptions originating from events to
+// overwrite the current exception, including exceptions originating from earlier events.
+// TODO It would be nice to add the overwritten exceptions to the suppressed exceptions list of the
+// newest exception.
+template <ArtJvmtiEvent kEvent, typename ...Args>
+inline void EventHandler::DispatchEvent(art::Thread* thread, JNIEnv* jnienv, Args... args) const {
+  for (ArtJvmTiEnv* env : envs) {
+    if (env != nullptr) {
+      ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred());
+      jnienv->ExceptionClear();
+      DispatchEvent<kEvent, JNIEnv*, Args...>(env, thread, jnienv, args...);
+      if (thr.get() != nullptr && !jnienv->ExceptionCheck()) {
+        jnienv->Throw(thr.get());
+      }
+    }
+  }
+}
+
+template <ArtJvmtiEvent kEvent, typename ...Args>
+inline void EventHandler::DispatchEvent(ArtJvmTiEnv* env, art::Thread* thread, Args... args) const {
+  using FnType = void(jvmtiEnv*, Args...);
+  if (ShouldDispatch<kEvent>(env, thread)) {
+    FnType* callback = impl::GetCallback<kEvent>(env);
+    if (callback != nullptr) {
+      (*callback)(env, args...);
+    }
+  }
+}
+
+// Need to give custom specializations for Breakpoint since it needs to filter out which particular
+// methods/dex_pcs agents get notified on.
+template <>
+inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kBreakpoint>(art::Thread* thread,
+                                                                    JNIEnv* jnienv,
+                                                                    jthread jni_thread,
+                                                                    jmethodID jmethod,
+                                                                    jlocation location) const {
+  art::ArtMethod* method = art::jni::DecodeArtMethod(jmethod);
+  for (ArtJvmTiEnv* env : envs) {
+    // Search for a breakpoint on this particular method and location.
+    if (env != nullptr &&
+        ShouldDispatch<ArtJvmtiEvent::kBreakpoint>(env, thread) &&
+        env->breakpoints.find({method, location}) != env->breakpoints.end()) {
+      // We temporarily clear any pending exceptions so the event can call back into java code.
+      ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred());
+      jnienv->ExceptionClear();
+      auto callback = impl::GetCallback<ArtJvmtiEvent::kBreakpoint>(env);
+      (*callback)(env, jnienv, jni_thread, jmethod, location);
+      if (thr.get() != nullptr && !jnienv->ExceptionCheck()) {
+        jnienv->Throw(thr.get());
+      }
+    }
+  }
+}
+
+// Need to give custom specializations for FieldAccess and FieldModification since they need to
+// filter out which particular fields agents want to get notified on.
+// TODO The spec allows us to do shortcuts like only allow one agent to ever set these watches. This
+// could make the system more performant.
+template <>
+inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kFieldModification>(art::Thread* thread,
+                                                                           JNIEnv* jnienv,
+                                                                           jthread jni_thread,
+                                                                           jmethodID method,
+                                                                           jlocation location,
+                                                                           jclass field_klass,
+                                                                           jobject object,
+                                                                           jfieldID field,
+                                                                           char type_char,
+                                                                           jvalue val) const {
+  for (ArtJvmTiEnv* env : envs) {
+    if (env != nullptr &&
+        ShouldDispatch<ArtJvmtiEvent::kFieldModification>(env, thread) &&
+        env->modify_watched_fields.find(
+            art::jni::DecodeArtField(field)) != env->modify_watched_fields.end()) {
+      ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred());
+      jnienv->ExceptionClear();
+      auto callback = impl::GetCallback<ArtJvmtiEvent::kFieldModification>(env);
+      (*callback)(env,
+                  jnienv,
+                  jni_thread,
+                  method,
+                  location,
+                  field_klass,
+                  object,
+                  field,
+                  type_char,
+                  val);
+      if (thr.get() != nullptr && !jnienv->ExceptionCheck()) {
+        jnienv->Throw(thr.get());
+      }
+    }
+  }
+}
+
+template <>
+inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kFieldAccess>(art::Thread* thread,
+                                                                     JNIEnv* jnienv,
+                                                                     jthread jni_thread,
+                                                                     jmethodID method,
+                                                                     jlocation location,
+                                                                     jclass field_klass,
+                                                                     jobject object,
+                                                                     jfieldID field) const {
+  for (ArtJvmTiEnv* env : envs) {
+    if (env != nullptr &&
+        ShouldDispatch<ArtJvmtiEvent::kFieldAccess>(env, thread) &&
+        env->access_watched_fields.find(
+            art::jni::DecodeArtField(field)) != env->access_watched_fields.end()) {
+      ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred());
+      jnienv->ExceptionClear();
+      auto callback = impl::GetCallback<ArtJvmtiEvent::kFieldAccess>(env);
+      (*callback)(env, jnienv, jni_thread, method, location, field_klass, object, field);
+      if (thr.get() != nullptr && !jnienv->ExceptionCheck()) {
+        jnienv->Throw(thr.get());
+      }
+    }
+  }
+}
+
+// Need to give a custom specialization for NativeMethodBind since it has to deal with an out
+// variable.
+template <>
+inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>(art::Thread* thread,
+                                                                          JNIEnv* jnienv,
+                                                                          jthread jni_thread,
+                                                                          jmethodID method,
+                                                                          void* cur_method,
+                                                                          void** new_method) const {
+  *new_method = cur_method;
+  for (ArtJvmTiEnv* env : envs) {
+    if (env != nullptr && ShouldDispatch<ArtJvmtiEvent::kNativeMethodBind>(env, thread)) {
+      auto callback = impl::GetCallback<ArtJvmtiEvent::kNativeMethodBind>(env);
+      (*callback)(env, jnienv, jni_thread, method, cur_method, new_method);
+      if (*new_method != nullptr) {
+        cur_method = *new_method;
+      }
+    }
+  }
+}
+
+// C++ does not allow partial template function specialization. The dispatch for our separated
+// ClassFileLoadHook event types is the same, and in the DispatchClassFileLoadHookEvent helper.
+// The following two DispatchEvent specializations dispatch to it.
+template <>
+inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookRetransformable>(
+    art::Thread* thread,
+    JNIEnv* jnienv,
+    jclass class_being_redefined,
+    jobject loader,
+    const char* name,
+    jobject protection_domain,
+    jint class_data_len,
+    const unsigned char* class_data,
+    jint* new_class_data_len,
+    unsigned char** new_class_data) const {
+  return DispatchClassFileLoadHookEvent<ArtJvmtiEvent::kClassFileLoadHookRetransformable>(
+      thread,
+      jnienv,
+      class_being_redefined,
+      loader,
+      name,
+      protection_domain,
+      class_data_len,
+      class_data,
+      new_class_data_len,
+      new_class_data);
+}
+template <>
+inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookNonRetransformable>(
+    art::Thread* thread,
+    JNIEnv* jnienv,
+    jclass class_being_redefined,
+    jobject loader,
+    const char* name,
+    jobject protection_domain,
+    jint class_data_len,
+    const unsigned char* class_data,
+    jint* new_class_data_len,
+    unsigned char** new_class_data) const {
+  return DispatchClassFileLoadHookEvent<ArtJvmtiEvent::kClassFileLoadHookNonRetransformable>(
+      thread,
+      jnienv,
+      class_being_redefined,
+      loader,
+      name,
+      protection_domain,
+      class_data_len,
+      class_data,
+      new_class_data_len,
+      new_class_data);
+}
+
+template <ArtJvmtiEvent kEvent>
+inline bool EventHandler::ShouldDispatch(ArtJvmTiEnv* env,
+                                         art::Thread* thread) {
+  bool dispatch = env->event_masks.global_event_mask.Test(kEvent);
+
+  if (!dispatch && thread != nullptr && env->event_masks.unioned_thread_event_mask.Test(kEvent)) {
+    EventMask* mask = env->event_masks.GetEventMaskOrNull(thread);
+    dispatch = mask != nullptr && mask->Test(kEvent);
+  }
+  return dispatch;
+}
+
+inline void EventHandler::RecalculateGlobalEventMask(ArtJvmtiEvent event) {
+  bool union_value = false;
+  for (const ArtJvmTiEnv* stored_env : envs) {
+    if (stored_env == nullptr) {
+      continue;
+    }
+    union_value |= stored_env->event_masks.global_event_mask.Test(event);
+    union_value |= stored_env->event_masks.unioned_thread_event_mask.Test(event);
+    if (union_value) {
+      break;
+    }
+  }
+  global_mask.Set(event, union_value);
+}
+
+inline bool EventHandler::NeedsEventUpdate(ArtJvmTiEnv* env,
+                                           const jvmtiCapabilities& caps,
+                                           bool added) {
+  ArtJvmtiEvent event = added ? ArtJvmtiEvent::kClassFileLoadHookNonRetransformable
+                              : ArtJvmtiEvent::kClassFileLoadHookRetransformable;
+  return (added && caps.can_access_local_variables == 1) ||
+      (caps.can_retransform_classes == 1 &&
+       IsEventEnabledAnywhere(event) &&
+       env->event_masks.IsEnabledAnywhere(event));
+}
+
+inline void EventHandler::HandleChangedCapabilities(ArtJvmTiEnv* env,
+                                                    const jvmtiCapabilities& caps,
+                                                    bool added) {
+  if (UNLIKELY(NeedsEventUpdate(env, caps, added))) {
+    env->event_masks.HandleChangedCapabilities(caps, added);
+    if (caps.can_retransform_classes == 1) {
+      RecalculateGlobalEventMask(ArtJvmtiEvent::kClassFileLoadHookRetransformable);
+      RecalculateGlobalEventMask(ArtJvmtiEvent::kClassFileLoadHookNonRetransformable);
+    }
+    if (added && caps.can_access_local_variables == 1) {
+      HandleLocalAccessCapabilityAdded();
+    }
+  }
+}
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_EVENTS_INL_H_
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc
new file mode 100644
index 0000000..2944a45
--- /dev/null
+++ b/openjdkjvmti/events.cc
@@ -0,0 +1,791 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "events-inl.h"
+
+#include "art_field-inl.h"
+#include "art_jvmti.h"
+#include "art_method-inl.h"
+#include "base/logging.h"
+#include "gc/allocation_listener.h"
+#include "gc/gc_pause_listener.h"
+#include "gc/heap.h"
+#include "gc/scoped_gc_critical_section.h"
+#include "handle_scope-inl.h"
+#include "instrumentation.h"
+#include "jni_env_ext-inl.h"
+#include "jni_internal.h"
+#include "mirror/class.h"
+#include "mirror/object-inl.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "runtime.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-inl.h"
+#include "thread_list.h"
+#include "ti_phase.h"
+
+namespace openjdkjvmti {
+
+bool EventMasks::IsEnabledAnywhere(ArtJvmtiEvent event) {
+  return global_event_mask.Test(event) || unioned_thread_event_mask.Test(event);
+}
+
+EventMask& EventMasks::GetEventMask(art::Thread* thread) {
+  if (thread == nullptr) {
+    return global_event_mask;
+  }
+
+  for (auto& pair : thread_event_masks) {
+    const UniqueThread& unique_thread = pair.first;
+    if (unique_thread.first == thread &&
+        unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
+      return pair.second;
+    }
+  }
+
+  // TODO: Remove old UniqueThread with the same pointer, if exists.
+
+  thread_event_masks.emplace_back(UniqueThread(thread, thread->GetTid()), EventMask());
+  return thread_event_masks.back().second;
+}
+
+EventMask* EventMasks::GetEventMaskOrNull(art::Thread* thread) {
+  if (thread == nullptr) {
+    return &global_event_mask;
+  }
+
+  for (auto& pair : thread_event_masks) {
+    const UniqueThread& unique_thread = pair.first;
+    if (unique_thread.first == thread &&
+        unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
+      return &pair.second;
+    }
+  }
+
+  return nullptr;
+}
+
+
+void EventMasks::EnableEvent(art::Thread* thread, ArtJvmtiEvent event) {
+  DCHECK(EventMask::EventIsInRange(event));
+  GetEventMask(thread).Set(event);
+  if (thread != nullptr) {
+    unioned_thread_event_mask.Set(event, true);
+  }
+}
+
+void EventMasks::DisableEvent(art::Thread* thread, ArtJvmtiEvent event) {
+  DCHECK(EventMask::EventIsInRange(event));
+  GetEventMask(thread).Set(event, false);
+  if (thread != nullptr) {
+    // Regenerate union for the event.
+    bool union_value = false;
+    for (auto& pair : thread_event_masks) {
+      union_value |= pair.second.Test(event);
+      if (union_value) {
+        break;
+      }
+    }
+    unioned_thread_event_mask.Set(event, union_value);
+  }
+}
+
+void EventMasks::HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added) {
+  if (UNLIKELY(caps.can_retransform_classes == 1)) {
+    // If we are giving this env the retransform classes cap we need to switch all events of
+    // NonTransformable to Transformable and vice versa.
+    ArtJvmtiEvent to_remove = caps_added ? ArtJvmtiEvent::kClassFileLoadHookNonRetransformable
+                                         : ArtJvmtiEvent::kClassFileLoadHookRetransformable;
+    ArtJvmtiEvent to_add = caps_added ? ArtJvmtiEvent::kClassFileLoadHookRetransformable
+                                      : ArtJvmtiEvent::kClassFileLoadHookNonRetransformable;
+    if (global_event_mask.Test(to_remove)) {
+      CHECK(!global_event_mask.Test(to_add));
+      global_event_mask.Set(to_remove, false);
+      global_event_mask.Set(to_add, true);
+    }
+
+    if (unioned_thread_event_mask.Test(to_remove)) {
+      CHECK(!unioned_thread_event_mask.Test(to_add));
+      unioned_thread_event_mask.Set(to_remove, false);
+      unioned_thread_event_mask.Set(to_add, true);
+    }
+    for (auto thread_mask : thread_event_masks) {
+      if (thread_mask.second.Test(to_remove)) {
+        CHECK(!thread_mask.second.Test(to_add));
+        thread_mask.second.Set(to_remove, false);
+        thread_mask.second.Set(to_add, true);
+      }
+    }
+  }
+}
+
+void EventHandler::RegisterArtJvmTiEnv(ArtJvmTiEnv* env) {
+  // Since we never shrink this array we might as well try to fill gaps.
+  auto it = std::find(envs.begin(), envs.end(), nullptr);
+  if (it != envs.end()) {
+    *it = env;
+  } else {
+    envs.push_back(env);
+  }
+}
+
+void EventHandler::RemoveArtJvmTiEnv(ArtJvmTiEnv* env) {
+  // Since we might be currently iterating over the envs list we cannot actually erase elements.
+  // Instead we will simply replace them with 'nullptr' and skip them manually.
+  auto it = std::find(envs.begin(), envs.end(), env);
+  if (it != envs.end()) {
+    *it = nullptr;
+    for (size_t i = static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal);
+         i <= static_cast<size_t>(ArtJvmtiEvent::kMaxEventTypeVal);
+         ++i) {
+      RecalculateGlobalEventMask(static_cast<ArtJvmtiEvent>(i));
+    }
+  }
+}
+
+static bool IsThreadControllable(ArtJvmtiEvent event) {
+  switch (event) {
+    case ArtJvmtiEvent::kVmInit:
+    case ArtJvmtiEvent::kVmStart:
+    case ArtJvmtiEvent::kVmDeath:
+    case ArtJvmtiEvent::kThreadStart:
+    case ArtJvmtiEvent::kCompiledMethodLoad:
+    case ArtJvmtiEvent::kCompiledMethodUnload:
+    case ArtJvmtiEvent::kDynamicCodeGenerated:
+    case ArtJvmtiEvent::kDataDumpRequest:
+      return false;
+
+    default:
+      return true;
+  }
+}
+
+class JvmtiAllocationListener : public art::gc::AllocationListener {
+ public:
+  explicit JvmtiAllocationListener(EventHandler* handler) : handler_(handler) {}
+
+  void ObjectAllocated(art::Thread* self, art::ObjPtr<art::mirror::Object>* obj, size_t byte_count)
+      OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    DCHECK_EQ(self, art::Thread::Current());
+
+    if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kVmObjectAlloc)) {
+      art::StackHandleScope<1> hs(self);
+      auto h = hs.NewHandleWrapper(obj);
+      // jvmtiEventVMObjectAlloc parameters:
+      //      jvmtiEnv *jvmti_env,
+      //      JNIEnv* jni_env,
+      //      jthread thread,
+      //      jobject object,
+      //      jclass object_klass,
+      //      jlong size
+      art::JNIEnvExt* jni_env = self->GetJniEnv();
+
+      jthread thread_peer;
+      if (self->IsStillStarting()) {
+        thread_peer = nullptr;
+      } else {
+        thread_peer = jni_env->AddLocalReference<jthread>(self->GetPeer());
+      }
+
+      ScopedLocalRef<jthread> thread(jni_env, thread_peer);
+      ScopedLocalRef<jobject> object(
+          jni_env, jni_env->AddLocalReference<jobject>(*obj));
+      ScopedLocalRef<jclass> klass(
+          jni_env, jni_env->AddLocalReference<jclass>(obj->Ptr()->GetClass()));
+
+      handler_->DispatchEvent<ArtJvmtiEvent::kVmObjectAlloc>(self,
+                                                             reinterpret_cast<JNIEnv*>(jni_env),
+                                                             thread.get(),
+                                                             object.get(),
+                                                             klass.get(),
+                                                             static_cast<jlong>(byte_count));
+    }
+  }
+
+ private:
+  EventHandler* handler_;
+};
+
+static void SetupObjectAllocationTracking(art::gc::AllocationListener* listener, bool enable) {
+  // We must not hold the mutator lock here, but if we're in FastJNI, for example, we might. For
+  // now, do a workaround: (possibly) acquire and release.
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ScopedThreadSuspension sts(soa.Self(), art::ThreadState::kSuspended);
+  if (enable) {
+    art::Runtime::Current()->GetHeap()->SetAllocationListener(listener);
+  } else {
+    art::Runtime::Current()->GetHeap()->RemoveAllocationListener();
+  }
+}
+
+// Report GC pauses (see spec) as GARBAGE_COLLECTION_START and GARBAGE_COLLECTION_END.
+class JvmtiGcPauseListener : public art::gc::GcPauseListener {
+ public:
+  explicit JvmtiGcPauseListener(EventHandler* handler)
+      : handler_(handler),
+        start_enabled_(false),
+        finish_enabled_(false) {}
+
+  void StartPause() OVERRIDE {
+    handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionStart>(nullptr);
+  }
+
+  void EndPause() OVERRIDE {
+    handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionFinish>(nullptr);
+  }
+
+  bool IsEnabled() {
+    return start_enabled_ || finish_enabled_;
+  }
+
+  void SetStartEnabled(bool e) {
+    start_enabled_ = e;
+  }
+
+  void SetFinishEnabled(bool e) {
+    finish_enabled_ = e;
+  }
+
+ private:
+  EventHandler* handler_;
+  bool start_enabled_;
+  bool finish_enabled_;
+};
+
+static void SetupGcPauseTracking(JvmtiGcPauseListener* listener, ArtJvmtiEvent event, bool enable) {
+  bool old_state = listener->IsEnabled();
+
+  if (event == ArtJvmtiEvent::kGarbageCollectionStart) {
+    listener->SetStartEnabled(enable);
+  } else {
+    listener->SetFinishEnabled(enable);
+  }
+
+  bool new_state = listener->IsEnabled();
+
+  if (old_state != new_state) {
+    if (new_state) {
+      art::Runtime::Current()->GetHeap()->SetGcPauseListener(listener);
+    } else {
+      art::Runtime::Current()->GetHeap()->RemoveGcPauseListener();
+    }
+  }
+}
+
+template<typename Type>
+static Type AddLocalRef(art::JNIEnvExt* e, art::mirror::Object* obj)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  return (obj == nullptr) ? nullptr : e->AddLocalReference<Type>(obj);
+}
+
+class JvmtiMethodTraceListener FINAL : public art::instrumentation::InstrumentationListener {
+ public:
+  explicit JvmtiMethodTraceListener(EventHandler* handler) : event_handler_(handler) {}
+
+  template<ArtJvmtiEvent kEvent, typename ...Args>
+  void RunEventCallback(art::Thread* self, art::JNIEnvExt* jnienv, Args... args)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    ScopedLocalRef<jthread> thread_jni(jnienv, AddLocalRef<jthread>(jnienv, self->GetPeer()));
+    // Just give the event a good sized JNI frame. 100 should be fine.
+    jnienv->PushFrame(100);
+    {
+      // Need to do trampoline! :(
+      art::ScopedThreadSuspension sts(self, art::ThreadState::kNative);
+      event_handler_->DispatchEvent<kEvent>(self,
+                                            static_cast<JNIEnv*>(jnienv),
+                                            thread_jni.get(),
+                                            args...);
+    }
+    jnienv->PopFrame();
+  }
+
+  // Call-back for when a method is entered.
+  void MethodEntered(art::Thread* self,
+                     art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
+                     art::ArtMethod* method,
+                     uint32_t dex_pc ATTRIBUTE_UNUSED)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    if (!method->IsRuntimeMethod() &&
+        event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodEntry)) {
+      art::JNIEnvExt* jnienv = self->GetJniEnv();
+      RunEventCallback<ArtJvmtiEvent::kMethodEntry>(self,
+                                                    jnienv,
+                                                    art::jni::EncodeArtMethod(method));
+    }
+  }
+
+  // Callback for when a method is exited with a reference return value.
+  void MethodExited(art::Thread* self,
+                    art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
+                    art::ArtMethod* method,
+                    uint32_t dex_pc ATTRIBUTE_UNUSED,
+                    art::Handle<art::mirror::Object> return_value)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    if (!method->IsRuntimeMethod() &&
+        event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodExit)) {
+      DCHECK_EQ(method->GetReturnTypePrimitive(), art::Primitive::kPrimNot)
+          << method->PrettyMethod();
+      DCHECK(!self->IsExceptionPending());
+      jvalue val;
+      art::JNIEnvExt* jnienv = self->GetJniEnv();
+      ScopedLocalRef<jobject> return_jobj(jnienv, AddLocalRef<jobject>(jnienv, return_value.Get()));
+      val.l = return_jobj.get();
+      RunEventCallback<ArtJvmtiEvent::kMethodExit>(
+          self,
+          jnienv,
+          art::jni::EncodeArtMethod(method),
+          /*was_popped_by_exception*/ static_cast<jboolean>(JNI_FALSE),
+          val);
+    }
+  }
+
+  // Call-back for when a method is exited.
+  void MethodExited(art::Thread* self,
+                    art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
+                    art::ArtMethod* method,
+                    uint32_t dex_pc ATTRIBUTE_UNUSED,
+                    const art::JValue& return_value)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    if (!method->IsRuntimeMethod() &&
+        event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodExit)) {
+      DCHECK_NE(method->GetReturnTypePrimitive(), art::Primitive::kPrimNot)
+          << method->PrettyMethod();
+      DCHECK(!self->IsExceptionPending());
+      jvalue val;
+      art::JNIEnvExt* jnienv = self->GetJniEnv();
+      // 64bit integer is the largest value in the union so we should be fine simply copying it into
+      // the union.
+      val.j = return_value.GetJ();
+      RunEventCallback<ArtJvmtiEvent::kMethodExit>(
+          self,
+          jnienv,
+          art::jni::EncodeArtMethod(method),
+          /*was_popped_by_exception*/ static_cast<jboolean>(JNI_FALSE),
+          val);
+    }
+  }
+
+  // Call-back for when a method is popped due to an exception throw. A method will either cause a
+  // MethodExited call-back or a MethodUnwind call-back when its activation is removed.
+  void MethodUnwind(art::Thread* self,
+                    art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
+                    art::ArtMethod* method,
+                    uint32_t dex_pc ATTRIBUTE_UNUSED)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    if (!method->IsRuntimeMethod() &&
+        event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodExit)) {
+      jvalue val;
+      // Just set this to 0xffffffffffffffff so it's not uninitialized.
+      val.j = static_cast<jlong>(-1);
+      art::JNIEnvExt* jnienv = self->GetJniEnv();
+      art::StackHandleScope<1> hs(self);
+      art::Handle<art::mirror::Throwable> old_exception(hs.NewHandle(self->GetException()));
+      CHECK(!old_exception.IsNull());
+      self->ClearException();
+      RunEventCallback<ArtJvmtiEvent::kMethodExit>(
+          self,
+          jnienv,
+          art::jni::EncodeArtMethod(method),
+          /*was_popped_by_exception*/ static_cast<jboolean>(JNI_TRUE),
+          val);
+      // Match RI behavior of just throwing away original exception if a new one is thrown.
+      if (LIKELY(!self->IsExceptionPending())) {
+        self->SetException(old_exception.Get());
+      }
+    }
+  }
+
+  // Call-back for when the dex pc moves in a method.
+  void DexPcMoved(art::Thread* self,
+                  art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
+                  art::ArtMethod* method,
+                  uint32_t new_dex_pc)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    DCHECK(!method->IsRuntimeMethod());
+    // Default methods might be copied to multiple classes. We need to get the canonical version of
+    // this method so that we can check for breakpoints correctly.
+    // TODO We should maybe do this on other events to ensure that we are consistent WRT default
+    // methods. This could interact with obsolete methods if we ever let interface redefinition
+    // happen though.
+    method = method->GetCanonicalMethod();
+    art::JNIEnvExt* jnienv = self->GetJniEnv();
+    jmethodID jmethod = art::jni::EncodeArtMethod(method);
+    jlocation location = static_cast<jlocation>(new_dex_pc);
+    // Step event is reported first according to the spec.
+    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kSingleStep)) {
+      RunEventCallback<ArtJvmtiEvent::kSingleStep>(self, jnienv, jmethod, location);
+    }
+    // Next we do the Breakpoint events. The Dispatch code will filter the individual
+    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kBreakpoint)) {
+      RunEventCallback<ArtJvmtiEvent::kBreakpoint>(self, jnienv, jmethod, location);
+    }
+  }
+
+  // Call-back for when we read from a field.
+  void FieldRead(art::Thread* self,
+                 art::Handle<art::mirror::Object> this_object,
+                 art::ArtMethod* method,
+                 uint32_t dex_pc,
+                 art::ArtField* field)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kFieldAccess)) {
+      art::JNIEnvExt* jnienv = self->GetJniEnv();
+      // DCHECK(!self->IsExceptionPending());
+      ScopedLocalRef<jobject> this_ref(jnienv, AddLocalRef<jobject>(jnienv, this_object.Get()));
+      ScopedLocalRef<jobject> fklass(jnienv,
+                                     AddLocalRef<jobject>(jnienv,
+                                                          field->GetDeclaringClass().Ptr()));
+      RunEventCallback<ArtJvmtiEvent::kFieldAccess>(self,
+                                                    jnienv,
+                                                    art::jni::EncodeArtMethod(method),
+                                                    static_cast<jlocation>(dex_pc),
+                                                    static_cast<jclass>(fklass.get()),
+                                                    this_ref.get(),
+                                                    art::jni::EncodeArtField(field));
+    }
+  }
+
+  void FieldWritten(art::Thread* self,
+                    art::Handle<art::mirror::Object> this_object,
+                    art::ArtMethod* method,
+                    uint32_t dex_pc,
+                    art::ArtField* field,
+                    art::Handle<art::mirror::Object> new_val)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kFieldModification)) {
+      art::JNIEnvExt* jnienv = self->GetJniEnv();
+      // DCHECK(!self->IsExceptionPending());
+      ScopedLocalRef<jobject> this_ref(jnienv, AddLocalRef<jobject>(jnienv, this_object.Get()));
+      ScopedLocalRef<jobject> fklass(jnienv,
+                                     AddLocalRef<jobject>(jnienv,
+                                                          field->GetDeclaringClass().Ptr()));
+      ScopedLocalRef<jobject> fval(jnienv, AddLocalRef<jobject>(jnienv, new_val.Get()));
+      jvalue val;
+      val.l = fval.get();
+      RunEventCallback<ArtJvmtiEvent::kFieldModification>(
+          self,
+          jnienv,
+          art::jni::EncodeArtMethod(method),
+          static_cast<jlocation>(dex_pc),
+          static_cast<jclass>(fklass.get()),
+          field->IsStatic() ? nullptr :  this_ref.get(),
+          art::jni::EncodeArtField(field),
+          'L',  // type_char
+          val);
+    }
+  }
+
+  // Call-back for when we write into a field.
+  void FieldWritten(art::Thread* self,
+                    art::Handle<art::mirror::Object> this_object,
+                    art::ArtMethod* method,
+                    uint32_t dex_pc,
+                    art::ArtField* field,
+                    const art::JValue& field_value)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kFieldModification)) {
+      art::JNIEnvExt* jnienv = self->GetJniEnv();
+      DCHECK(!self->IsExceptionPending());
+      ScopedLocalRef<jobject> this_ref(jnienv, AddLocalRef<jobject>(jnienv, this_object.Get()));
+      ScopedLocalRef<jobject> fklass(jnienv,
+                                     AddLocalRef<jobject>(jnienv,
+                                                          field->GetDeclaringClass().Ptr()));
+      char type_char = art::Primitive::Descriptor(field->GetTypeAsPrimitiveType())[0];
+      jvalue val;
+      // 64bit integer is the largest value in the union so we should be fine simply copying it into
+      // the union.
+      val.j = field_value.GetJ();
+      RunEventCallback<ArtJvmtiEvent::kFieldModification>(
+          self,
+          jnienv,
+          art::jni::EncodeArtMethod(method),
+          static_cast<jlocation>(dex_pc),
+          static_cast<jclass>(fklass.get()),
+          field->IsStatic() ? nullptr :  this_ref.get(),  // nb static field modification get given
+                                                          // the class as this_object for some
+                                                          // reason.
+          art::jni::EncodeArtField(field),
+          type_char,
+          val);
+    }
+  }
+
+  // Call-back when an exception is caught.
+  void ExceptionCaught(art::Thread* self ATTRIBUTE_UNUSED,
+                       art::Handle<art::mirror::Throwable> exception_object ATTRIBUTE_UNUSED)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    return;
+  }
+
+  // Call-back for when we execute a branch.
+  void Branch(art::Thread* self ATTRIBUTE_UNUSED,
+              art::ArtMethod* method ATTRIBUTE_UNUSED,
+              uint32_t dex_pc ATTRIBUTE_UNUSED,
+              int32_t dex_pc_offset ATTRIBUTE_UNUSED)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    return;
+  }
+
+  // Call-back for when we get an invokevirtual or an invokeinterface.
+  void InvokeVirtualOrInterface(art::Thread* self ATTRIBUTE_UNUSED,
+                                art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
+                                art::ArtMethod* caller ATTRIBUTE_UNUSED,
+                                uint32_t dex_pc ATTRIBUTE_UNUSED,
+                                art::ArtMethod* callee ATTRIBUTE_UNUSED)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    return;
+  }
+
+ private:
+  EventHandler* const event_handler_;
+};
+
+static uint32_t GetInstrumentationEventsFor(ArtJvmtiEvent event) {
+  switch (event) {
+    case ArtJvmtiEvent::kMethodEntry:
+      return art::instrumentation::Instrumentation::kMethodEntered;
+    case ArtJvmtiEvent::kMethodExit:
+      return art::instrumentation::Instrumentation::kMethodExited |
+             art::instrumentation::Instrumentation::kMethodUnwind;
+    case ArtJvmtiEvent::kFieldModification:
+      return art::instrumentation::Instrumentation::kFieldWritten;
+    case ArtJvmtiEvent::kFieldAccess:
+      return art::instrumentation::Instrumentation::kFieldRead;
+    case ArtJvmtiEvent::kBreakpoint:
+    case ArtJvmtiEvent::kSingleStep:
+      return art::instrumentation::Instrumentation::kDexPcMoved;
+    default:
+      LOG(FATAL) << "Unknown event ";
+      return 0;
+  }
+}
+
+static void SetupTraceListener(JvmtiMethodTraceListener* listener,
+                               ArtJvmtiEvent event,
+                               bool enable) {
+  art::ScopedThreadStateChange stsc(art::Thread::Current(), art::ThreadState::kNative);
+  uint32_t new_events = GetInstrumentationEventsFor(event);
+  art::instrumentation::Instrumentation* instr = art::Runtime::Current()->GetInstrumentation();
+  art::gc::ScopedGCCriticalSection gcs(art::Thread::Current(),
+                                       art::gc::kGcCauseInstrumentation,
+                                       art::gc::kCollectorTypeInstrumentation);
+  art::ScopedSuspendAll ssa("jvmti method tracing installation");
+  if (enable) {
+    // TODO Depending on the features being used we should be able to avoid deoptimizing everything
+    // like we do here.
+    if (!instr->AreAllMethodsDeoptimized()) {
+      instr->EnableMethodTracing("jvmti-tracing", /*needs_interpreter*/true);
+    }
+    instr->AddListener(listener, new_events);
+  } else {
+    instr->RemoveListener(listener, new_events);
+  }
+}
+
+void EventHandler::HandleLocalAccessCapabilityAdded() {
+  art::ScopedThreadStateChange stsc(art::Thread::Current(), art::ThreadState::kNative);
+  art::instrumentation::Instrumentation* instr = art::Runtime::Current()->GetInstrumentation();
+  art::gc::ScopedGCCriticalSection gcs(art::Thread::Current(),
+                                       art::gc::kGcCauseInstrumentation,
+                                       art::gc::kCollectorTypeInstrumentation);
+  art::ScopedSuspendAll ssa("Deoptimize everything for local variable access", true);
+  // TODO This should be disabled when there are no environments using it.
+  if (!instr->CanDeoptimize()) {
+    instr->EnableDeoptimization();
+  }
+  // TODO We should be able to support can_access_local_variables without this.
+  instr->DeoptimizeEverything("jvmti-local-variable-access");
+}
+
+// Handle special work for the given event type, if necessary.
+void EventHandler::HandleEventType(ArtJvmtiEvent event, bool enable) {
+  switch (event) {
+    case ArtJvmtiEvent::kVmObjectAlloc:
+      SetupObjectAllocationTracking(alloc_listener_.get(), enable);
+      return;
+
+    case ArtJvmtiEvent::kGarbageCollectionStart:
+    case ArtJvmtiEvent::kGarbageCollectionFinish:
+      SetupGcPauseTracking(gc_pause_listener_.get(), event, enable);
+      return;
+
+    case ArtJvmtiEvent::kBreakpoint:
+    case ArtJvmtiEvent::kSingleStep: {
+      ArtJvmtiEvent other = (event == ArtJvmtiEvent::kBreakpoint) ? ArtJvmtiEvent::kSingleStep
+                                                                  : ArtJvmtiEvent::kBreakpoint;
+      // We only need to do anything if there isn't already a listener installed/held-on by the
+      // other jvmti event that uses DexPcMoved.
+      if (!IsEventEnabledAnywhere(other)) {
+        SetupTraceListener(method_trace_listener_.get(), event, enable);
+      }
+      return;
+    }
+    case ArtJvmtiEvent::kMethodEntry:
+    case ArtJvmtiEvent::kMethodExit:
+    case ArtJvmtiEvent::kFieldAccess:
+    case ArtJvmtiEvent::kFieldModification:
+      SetupTraceListener(method_trace_listener_.get(), event, enable);
+      return;
+
+    default:
+      break;
+  }
+}
+
+// Checks to see if the env has the capabilities associated with the given event.
+static bool HasAssociatedCapability(ArtJvmTiEnv* env,
+                                    ArtJvmtiEvent event) {
+  jvmtiCapabilities caps = env->capabilities;
+  switch (event) {
+    case ArtJvmtiEvent::kBreakpoint:
+      return caps.can_generate_breakpoint_events == 1;
+
+    case ArtJvmtiEvent::kCompiledMethodLoad:
+    case ArtJvmtiEvent::kCompiledMethodUnload:
+      return caps.can_generate_compiled_method_load_events == 1;
+
+    case ArtJvmtiEvent::kException:
+    case ArtJvmtiEvent::kExceptionCatch:
+      return caps.can_generate_exception_events == 1;
+
+    case ArtJvmtiEvent::kFieldAccess:
+      return caps.can_generate_field_access_events == 1;
+
+    case ArtJvmtiEvent::kFieldModification:
+      return caps.can_generate_field_modification_events == 1;
+
+    case ArtJvmtiEvent::kFramePop:
+      return caps.can_generate_frame_pop_events == 1;
+
+    case ArtJvmtiEvent::kGarbageCollectionStart:
+    case ArtJvmtiEvent::kGarbageCollectionFinish:
+      return caps.can_generate_garbage_collection_events == 1;
+
+    case ArtJvmtiEvent::kMethodEntry:
+      return caps.can_generate_method_entry_events == 1;
+
+    case ArtJvmtiEvent::kMethodExit:
+      return caps.can_generate_method_exit_events == 1;
+
+    case ArtJvmtiEvent::kMonitorContendedEnter:
+    case ArtJvmtiEvent::kMonitorContendedEntered:
+    case ArtJvmtiEvent::kMonitorWait:
+    case ArtJvmtiEvent::kMonitorWaited:
+      return caps.can_generate_monitor_events == 1;
+
+    case ArtJvmtiEvent::kNativeMethodBind:
+      return caps.can_generate_native_method_bind_events == 1;
+
+    case ArtJvmtiEvent::kObjectFree:
+      return caps.can_generate_object_free_events == 1;
+
+    case ArtJvmtiEvent::kSingleStep:
+      return caps.can_generate_single_step_events == 1;
+
+    case ArtJvmtiEvent::kVmObjectAlloc:
+      return caps.can_generate_vm_object_alloc_events == 1;
+
+    default:
+      return true;
+  }
+}
+
+jvmtiError EventHandler::SetEvent(ArtJvmTiEnv* env,
+                                  art::Thread* thread,
+                                  ArtJvmtiEvent event,
+                                  jvmtiEventMode mode) {
+  if (thread != nullptr) {
+    art::ThreadState state = thread->GetState();
+    if (state == art::ThreadState::kStarting ||
+        state == art::ThreadState::kTerminated ||
+        thread->IsStillStarting()) {
+      return ERR(THREAD_NOT_ALIVE);
+    }
+    if (!IsThreadControllable(event)) {
+      return ERR(ILLEGAL_ARGUMENT);
+    }
+  }
+
+  if (mode != JVMTI_ENABLE && mode != JVMTI_DISABLE) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+
+  if (!EventMask::EventIsInRange(event)) {
+    return ERR(INVALID_EVENT_TYPE);
+  }
+
+  if (!HasAssociatedCapability(env, event)) {
+    return ERR(MUST_POSSESS_CAPABILITY);
+  }
+
+  bool old_state = global_mask.Test(event);
+
+  if (mode == JVMTI_ENABLE) {
+    env->event_masks.EnableEvent(thread, event);
+    global_mask.Set(event);
+  } else {
+    DCHECK_EQ(mode, JVMTI_DISABLE);
+
+    env->event_masks.DisableEvent(thread, event);
+    RecalculateGlobalEventMask(event);
+  }
+
+  bool new_state = global_mask.Test(event);
+
+  // Handle any special work required for the event type.
+  if (new_state != old_state) {
+    HandleEventType(event, mode == JVMTI_ENABLE);
+  }
+
+  return ERR(NONE);
+}
+
+void EventHandler::Shutdown() {
+  // Need to remove the method_trace_listener_ if it's there.
+  art::Thread* self = art::Thread::Current();
+  art::gc::ScopedGCCriticalSection gcs(self,
+                                       art::gc::kGcCauseInstrumentation,
+                                       art::gc::kCollectorTypeInstrumentation);
+  art::ScopedSuspendAll ssa("jvmti method tracing uninstallation");
+  // Just remove every possible event.
+  art::Runtime::Current()->GetInstrumentation()->RemoveListener(method_trace_listener_.get(), ~0);
+}
+
+EventHandler::EventHandler() {
+  alloc_listener_.reset(new JvmtiAllocationListener(this));
+  gc_pause_listener_.reset(new JvmtiGcPauseListener(this));
+  method_trace_listener_.reset(new JvmtiMethodTraceListener(this));
+}
+
+EventHandler::~EventHandler() {
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/events.h b/openjdkjvmti/events.h
new file mode 100644
index 0000000..3d05fa1
--- /dev/null
+++ b/openjdkjvmti/events.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_OPENJDKJVMTI_EVENTS_H_
+#define ART_OPENJDKJVMTI_EVENTS_H_
+
+#include <bitset>
+#include <vector>
+
+#include "base/logging.h"
+#include "jvmti.h"
+#include "thread.h"
+
+namespace openjdkjvmti {
+
+struct ArtJvmTiEnv;
+class JvmtiAllocationListener;
+class JvmtiGcPauseListener;
+class JvmtiMethodTraceListener;
+
+// an enum for ArtEvents. This differs from the JVMTI events only in that we distinguish between
+// retransformation capable and incapable loading
+enum class ArtJvmtiEvent {
+    kMinEventTypeVal = JVMTI_MIN_EVENT_TYPE_VAL,
+    kVmInit = JVMTI_EVENT_VM_INIT,
+    kVmDeath = JVMTI_EVENT_VM_DEATH,
+    kThreadStart = JVMTI_EVENT_THREAD_START,
+    kThreadEnd = JVMTI_EVENT_THREAD_END,
+    kClassFileLoadHookNonRetransformable = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
+    kClassLoad = JVMTI_EVENT_CLASS_LOAD,
+    kClassPrepare = JVMTI_EVENT_CLASS_PREPARE,
+    kVmStart = JVMTI_EVENT_VM_START,
+    kException = JVMTI_EVENT_EXCEPTION,
+    kExceptionCatch = JVMTI_EVENT_EXCEPTION_CATCH,
+    kSingleStep = JVMTI_EVENT_SINGLE_STEP,
+    kFramePop = JVMTI_EVENT_FRAME_POP,
+    kBreakpoint = JVMTI_EVENT_BREAKPOINT,
+    kFieldAccess = JVMTI_EVENT_FIELD_ACCESS,
+    kFieldModification = JVMTI_EVENT_FIELD_MODIFICATION,
+    kMethodEntry = JVMTI_EVENT_METHOD_ENTRY,
+    kMethodExit = JVMTI_EVENT_METHOD_EXIT,
+    kNativeMethodBind = JVMTI_EVENT_NATIVE_METHOD_BIND,
+    kCompiledMethodLoad = JVMTI_EVENT_COMPILED_METHOD_LOAD,
+    kCompiledMethodUnload = JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
+    kDynamicCodeGenerated = JVMTI_EVENT_DYNAMIC_CODE_GENERATED,
+    kDataDumpRequest = JVMTI_EVENT_DATA_DUMP_REQUEST,
+    kMonitorWait = JVMTI_EVENT_MONITOR_WAIT,
+    kMonitorWaited = JVMTI_EVENT_MONITOR_WAITED,
+    kMonitorContendedEnter = JVMTI_EVENT_MONITOR_CONTENDED_ENTER,
+    kMonitorContendedEntered = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED,
+    kResourceExhausted = JVMTI_EVENT_RESOURCE_EXHAUSTED,
+    kGarbageCollectionStart = JVMTI_EVENT_GARBAGE_COLLECTION_START,
+    kGarbageCollectionFinish = JVMTI_EVENT_GARBAGE_COLLECTION_FINISH,
+    kObjectFree = JVMTI_EVENT_OBJECT_FREE,
+    kVmObjectAlloc = JVMTI_EVENT_VM_OBJECT_ALLOC,
+    kClassFileLoadHookRetransformable = JVMTI_MAX_EVENT_TYPE_VAL + 1,
+    kMaxEventTypeVal = kClassFileLoadHookRetransformable,
+};
+
+// Convert a jvmtiEvent into a ArtJvmtiEvent
+ALWAYS_INLINE static inline ArtJvmtiEvent GetArtJvmtiEvent(ArtJvmTiEnv* env, jvmtiEvent e);
+
+static inline jvmtiEvent GetJvmtiEvent(ArtJvmtiEvent e) {
+  if (UNLIKELY(e == ArtJvmtiEvent::kClassFileLoadHookRetransformable)) {
+    return JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
+  } else {
+    return static_cast<jvmtiEvent>(e);
+  }
+}
+
+struct EventMask {
+  static constexpr size_t kEventsSize =
+      static_cast<size_t>(ArtJvmtiEvent::kMaxEventTypeVal) -
+      static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal) + 1;
+  std::bitset<kEventsSize> bit_set;
+
+  static bool EventIsInRange(ArtJvmtiEvent event) {
+    return event >= ArtJvmtiEvent::kMinEventTypeVal && event <= ArtJvmtiEvent::kMaxEventTypeVal;
+  }
+
+  void Set(ArtJvmtiEvent event, bool value = true) {
+    DCHECK(EventIsInRange(event));
+    bit_set.set(static_cast<size_t>(event) - static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal),
+                value);
+  }
+
+  bool Test(ArtJvmtiEvent event) const {
+    DCHECK(EventIsInRange(event));
+    return bit_set.test(
+        static_cast<size_t>(event) - static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal));
+  }
+};
+
+struct EventMasks {
+  // The globally enabled events.
+  EventMask global_event_mask;
+
+  // The per-thread enabled events.
+
+  // It is not enough to store a Thread pointer, as these may be reused. Use the pointer and the
+  // thread id.
+  // Note: We could just use the tid like tracing does.
+  using UniqueThread = std::pair<art::Thread*, uint32_t>;
+  // TODO: Native thread objects are immovable, so we can use them as keys in an (unordered) map,
+  //       if necessary.
+  std::vector<std::pair<UniqueThread, EventMask>> thread_event_masks;
+
+  // A union of the per-thread events, for fast-pathing.
+  EventMask unioned_thread_event_mask;
+
+  EventMask& GetEventMask(art::Thread* thread);
+  EventMask* GetEventMaskOrNull(art::Thread* thread);
+  void EnableEvent(art::Thread* thread, ArtJvmtiEvent event);
+  void DisableEvent(art::Thread* thread, ArtJvmtiEvent event);
+  bool IsEnabledAnywhere(ArtJvmtiEvent event);
+  // Make any changes to event masks needed for the given capability changes. If caps_added is true
+  // then caps is all the newly set capabilities of the jvmtiEnv. If it is false then caps is the
+  // set of all capabilities that were removed from the jvmtiEnv.
+  void HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added);
+};
+
+// Helper class for event handling.
+class EventHandler {
+ public:
+  EventHandler();
+  ~EventHandler();
+
+  // do cleanup for the event handler.
+  void Shutdown();
+
+  // Register an env. It is assumed that this happens on env creation, that is, no events are
+  // enabled, yet.
+  void RegisterArtJvmTiEnv(ArtJvmTiEnv* env);
+
+  // Remove an env.
+  void RemoveArtJvmTiEnv(ArtJvmTiEnv* env);
+
+  bool IsEventEnabledAnywhere(ArtJvmtiEvent event) const {
+    if (!EventMask::EventIsInRange(event)) {
+      return false;
+    }
+    return global_mask.Test(event);
+  }
+
+  jvmtiError SetEvent(ArtJvmTiEnv* env,
+                      art::Thread* thread,
+                      ArtJvmtiEvent event,
+                      jvmtiEventMode mode);
+
+  // Dispatch event to all registered environments.
+  template <ArtJvmtiEvent kEvent, typename ...Args>
+  ALWAYS_INLINE
+  inline void DispatchEvent(art::Thread* thread, Args... args) const;
+  // Dispatch event to all registered environments stashing exceptions as needed. This works since
+  // JNIEnv* is always the second argument if it is passed to an event. Needed since C++ does not
+  // allow partial template function specialization.
+  template <ArtJvmtiEvent kEvent, typename ...Args>
+  ALWAYS_INLINE
+  void DispatchEvent(art::Thread* thread, JNIEnv* jnienv, Args... args) const;
+  // Dispatch event to the given environment, only.
+  template <ArtJvmtiEvent kEvent, typename ...Args>
+  ALWAYS_INLINE
+  inline void DispatchEvent(ArtJvmTiEnv* env, art::Thread* thread, Args... args) const;
+
+  // Tell the event handler capabilities were added/lost so it can adjust the sent events.If
+  // caps_added is true then caps is all the newly set capabilities of the jvmtiEnv. If it is false
+  // then caps is the set of all capabilities that were removed from the jvmtiEnv.
+  ALWAYS_INLINE
+  inline void HandleChangedCapabilities(ArtJvmTiEnv* env,
+                                        const jvmtiCapabilities& caps,
+                                        bool added);
+
+ private:
+  template <ArtJvmtiEvent kEvent>
+  ALWAYS_INLINE
+  static inline bool ShouldDispatch(ArtJvmTiEnv* env, art::Thread* thread);
+
+  ALWAYS_INLINE
+  inline bool NeedsEventUpdate(ArtJvmTiEnv* env,
+                               const jvmtiCapabilities& caps,
+                               bool added);
+
+  // Recalculates the event mask for the given event.
+  ALWAYS_INLINE
+  inline void RecalculateGlobalEventMask(ArtJvmtiEvent event);
+
+  template <ArtJvmtiEvent kEvent>
+  ALWAYS_INLINE inline void DispatchClassFileLoadHookEvent(art::Thread* thread,
+                                                           JNIEnv* jnienv,
+                                                           jclass class_being_redefined,
+                                                           jobject loader,
+                                                           const char* name,
+                                                           jobject protection_domain,
+                                                           jint class_data_len,
+                                                           const unsigned char* class_data,
+                                                           jint* new_class_data_len,
+                                                           unsigned char** new_class_data) const;
+
+  void HandleEventType(ArtJvmtiEvent event, bool enable);
+  void HandleLocalAccessCapabilityAdded();
+
+  // List of all JvmTiEnv objects that have been created, in their creation order.
+  // NB Some elements might be null representing envs that have been deleted. They should be skipped
+  // anytime this list is used.
+  std::vector<ArtJvmTiEnv*> envs;
+
+  // A union of all enabled events, anywhere.
+  EventMask global_mask;
+
+  std::unique_ptr<JvmtiAllocationListener> alloc_listener_;
+  std::unique_ptr<JvmtiGcPauseListener> gc_pause_listener_;
+  std::unique_ptr<JvmtiMethodTraceListener> method_trace_listener_;
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_EVENTS_H_
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
new file mode 100644
index 0000000..5bfa5ca
--- /dev/null
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -0,0 +1,91 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "fixed_up_dex_file.h"
+#include "dex_file-inl.h"
+
+// Runtime includes.
+#include "dex_to_dex_decompiler.h"
+#include "oat_file.h"
+#include "vdex_file.h"
+
+namespace openjdkjvmti {
+
+static void RecomputeDexChecksum(art::DexFile* dex_file)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  reinterpret_cast<art::DexFile::Header*>(const_cast<uint8_t*>(dex_file->Begin()))->checksum_ =
+      dex_file->CalculateChecksum();
+}
+
+static void DoDexUnquicken(const art::DexFile& new_dex_file, const art::DexFile& original_dex_file)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  const art::OatDexFile* oat_dex = original_dex_file.GetOatDexFile();
+  if (oat_dex == nullptr) {
+    return;
+  }
+  const art::OatFile* oat_file = oat_dex->GetOatFile();
+  if (oat_file == nullptr) {
+    return;
+  }
+  const art::VdexFile* vdex = oat_file->GetVdexFile();
+  if (vdex == nullptr) {
+    return;
+  }
+  vdex->FullyUnquickenDexFile(new_dex_file, original_dex_file);
+}
+
+std::unique_ptr<FixedUpDexFile> FixedUpDexFile::Create(const art::DexFile& original) {
+  // Copy the data into mutable memory.
+  std::vector<unsigned char> data;
+  data.resize(original.Size());
+  memcpy(data.data(), original.Begin(), original.Size());
+  std::string error;
+  std::unique_ptr<const art::DexFile> new_dex_file(art::DexFile::Open(
+      data.data(),
+      data.size(),
+      /*location*/"Unquickening_dexfile.dex",
+      /*location_checksum*/0,
+      /*oat_dex_file*/nullptr,
+      /*verify*/false,
+      /*verify_checksum*/false,
+      &error));
+  if (new_dex_file.get() == nullptr) {
+    LOG(ERROR) << "Unable to open dex file from memory for unquickening! error: " << error;
+    return nullptr;
+  }
+
+  DoDexUnquicken(*new_dex_file, original);
+  RecomputeDexChecksum(const_cast<art::DexFile*>(new_dex_file.get()));
+  std::unique_ptr<FixedUpDexFile> ret(new FixedUpDexFile(std::move(new_dex_file), std::move(data)));
+  return ret;
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/fixed_up_dex_file.h b/openjdkjvmti/fixed_up_dex_file.h
new file mode 100644
index 0000000..4cb39cf
--- /dev/null
+++ b/openjdkjvmti/fixed_up_dex_file.h
@@ -0,0 +1,83 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_FIXED_UP_DEX_FILE_H_
+#define ART_OPENJDKJVMTI_FIXED_UP_DEX_FILE_H_
+
+#include <memory>
+#include <vector>
+
+#include "jni.h"
+#include "jvmti.h"
+
+#include "base/mutex.h"
+#include "dex_file.h"
+
+namespace openjdkjvmti {
+
+// A holder for a DexFile that has been 'fixed up' to ensure it is fully compliant with the
+// published standard (no internal/quick opcodes, all fields are the defined values, etc). This is
+// used to ensure that agents get a consistent dex file regardless of what version of android they
+// are running on.
+class FixedUpDexFile {
+ public:
+  static std::unique_ptr<FixedUpDexFile> Create(const art::DexFile& original)
+      REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+  const art::DexFile& GetDexFile() {
+    return *dex_file_;
+  }
+
+  const unsigned char* Begin() {
+    return data_.data();
+  }
+
+  size_t Size() {
+    return data_.size();
+  }
+
+ private:
+  explicit FixedUpDexFile(std::unique_ptr<const art::DexFile> fixed_up_dex_file,
+                          std::vector<unsigned char> data)
+      : dex_file_(std::move(fixed_up_dex_file)),
+        data_(std::move(data)) {}
+
+  // the fixed up DexFile
+  std::unique_ptr<const art::DexFile> dex_file_;
+  // The backing data for dex_file_.
+  const std::vector<unsigned char> data_;
+
+  DISALLOW_COPY_AND_ASSIGN(FixedUpDexFile);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_FIXED_UP_DEX_FILE_H_
diff --git a/openjdkjvmti/include/jvmti.h b/openjdkjvmti/include/jvmti.h
new file mode 100644
index 0000000..de07c16
--- /dev/null
+++ b/openjdkjvmti/include/jvmti.h
@@ -0,0 +1,2534 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+    /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
+
+
+    /* Include file for the Java(tm) Virtual Machine Tool Interface */
+
+#ifndef _JAVA_JVMTI_H_
+#define _JAVA_JVMTI_H_
+
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+    JVMTI_VERSION_1   = 0x30010000,
+    JVMTI_VERSION_1_0 = 0x30010000,
+    JVMTI_VERSION_1_1 = 0x30010100,
+    JVMTI_VERSION_1_2 = 0x30010200,
+
+    JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (2 * 0x100) + 1  /* version: 1.2.1 */
+};
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
+
+JNIEXPORT jint JNICALL
+Agent_OnAttach(JavaVM* vm, char* options, void* reserved);
+
+JNIEXPORT void JNICALL
+Agent_OnUnload(JavaVM *vm);
+
+    /* Forward declaration of the environment */
+
+struct _jvmtiEnv;
+
+struct jvmtiInterface_1_;
+
+#ifdef __cplusplus
+typedef _jvmtiEnv jvmtiEnv;
+#else
+typedef const struct jvmtiInterface_1_ *jvmtiEnv;
+#endif /* __cplusplus */
+
+/* Derived Base Types */
+
+typedef jobject jthread;
+typedef jobject jthreadGroup;
+typedef jlong jlocation;
+struct _jrawMonitorID;
+typedef struct _jrawMonitorID *jrawMonitorID;
+typedef struct JNINativeInterface jniNativeInterface;
+
+    /* Constants */
+
+
+    /* Thread State Flags */
+
+enum {
+    JVMTI_THREAD_STATE_ALIVE = 0x0001,
+    JVMTI_THREAD_STATE_TERMINATED = 0x0002,
+    JVMTI_THREAD_STATE_RUNNABLE = 0x0004,
+    JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400,
+    JVMTI_THREAD_STATE_WAITING = 0x0080,
+    JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010,
+    JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020,
+    JVMTI_THREAD_STATE_SLEEPING = 0x0040,
+    JVMTI_THREAD_STATE_IN_OBJECT_WAIT = 0x0100,
+    JVMTI_THREAD_STATE_PARKED = 0x0200,
+    JVMTI_THREAD_STATE_SUSPENDED = 0x100000,
+    JVMTI_THREAD_STATE_INTERRUPTED = 0x200000,
+    JVMTI_THREAD_STATE_IN_NATIVE = 0x400000,
+    JVMTI_THREAD_STATE_VENDOR_1 = 0x10000000,
+    JVMTI_THREAD_STATE_VENDOR_2 = 0x20000000,
+    JVMTI_THREAD_STATE_VENDOR_3 = 0x40000000
+};
+
+    /* java.lang.Thread.State Conversion Masks */
+
+enum {
+    JVMTI_JAVA_LANG_THREAD_STATE_MASK = JVMTI_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT,
+    JVMTI_JAVA_LANG_THREAD_STATE_NEW = 0,
+    JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED = JVMTI_THREAD_STATE_TERMINATED,
+    JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE,
+    JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,
+    JVMTI_JAVA_LANG_THREAD_STATE_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY,
+    JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
+};
+
+    /* Thread Priority Constants */
+
+enum {
+    JVMTI_THREAD_MIN_PRIORITY = 1,
+    JVMTI_THREAD_NORM_PRIORITY = 5,
+    JVMTI_THREAD_MAX_PRIORITY = 10
+};
+
+    /* Heap Filter Flags */
+
+enum {
+    JVMTI_HEAP_FILTER_TAGGED = 0x4,
+    JVMTI_HEAP_FILTER_UNTAGGED = 0x8,
+    JVMTI_HEAP_FILTER_CLASS_TAGGED = 0x10,
+    JVMTI_HEAP_FILTER_CLASS_UNTAGGED = 0x20
+};
+
+    /* Heap Visit Control Flags */
+
+enum {
+    JVMTI_VISIT_OBJECTS = 0x100,
+    JVMTI_VISIT_ABORT = 0x8000
+};
+
+    /* Heap Reference Enumeration */
+
+typedef enum {
+    JVMTI_HEAP_REFERENCE_CLASS = 1,
+    JVMTI_HEAP_REFERENCE_FIELD = 2,
+    JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT = 3,
+    JVMTI_HEAP_REFERENCE_CLASS_LOADER = 4,
+    JVMTI_HEAP_REFERENCE_SIGNERS = 5,
+    JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN = 6,
+    JVMTI_HEAP_REFERENCE_INTERFACE = 7,
+    JVMTI_HEAP_REFERENCE_STATIC_FIELD = 8,
+    JVMTI_HEAP_REFERENCE_CONSTANT_POOL = 9,
+    JVMTI_HEAP_REFERENCE_SUPERCLASS = 10,
+    JVMTI_HEAP_REFERENCE_JNI_GLOBAL = 21,
+    JVMTI_HEAP_REFERENCE_SYSTEM_CLASS = 22,
+    JVMTI_HEAP_REFERENCE_MONITOR = 23,
+    JVMTI_HEAP_REFERENCE_STACK_LOCAL = 24,
+    JVMTI_HEAP_REFERENCE_JNI_LOCAL = 25,
+    JVMTI_HEAP_REFERENCE_THREAD = 26,
+    JVMTI_HEAP_REFERENCE_OTHER = 27
+} jvmtiHeapReferenceKind;
+
+    /* Primitive Type Enumeration */
+
+typedef enum {
+    JVMTI_PRIMITIVE_TYPE_BOOLEAN = 90,
+    JVMTI_PRIMITIVE_TYPE_BYTE = 66,
+    JVMTI_PRIMITIVE_TYPE_CHAR = 67,
+    JVMTI_PRIMITIVE_TYPE_SHORT = 83,
+    JVMTI_PRIMITIVE_TYPE_INT = 73,
+    JVMTI_PRIMITIVE_TYPE_LONG = 74,
+    JVMTI_PRIMITIVE_TYPE_FLOAT = 70,
+    JVMTI_PRIMITIVE_TYPE_DOUBLE = 68
+} jvmtiPrimitiveType;
+
+    /* Heap Object Filter Enumeration */
+
+typedef enum {
+    JVMTI_HEAP_OBJECT_TAGGED = 1,
+    JVMTI_HEAP_OBJECT_UNTAGGED = 2,
+    JVMTI_HEAP_OBJECT_EITHER = 3
+} jvmtiHeapObjectFilter;
+
+    /* Heap Root Kind Enumeration */
+
+typedef enum {
+    JVMTI_HEAP_ROOT_JNI_GLOBAL = 1,
+    JVMTI_HEAP_ROOT_SYSTEM_CLASS = 2,
+    JVMTI_HEAP_ROOT_MONITOR = 3,
+    JVMTI_HEAP_ROOT_STACK_LOCAL = 4,
+    JVMTI_HEAP_ROOT_JNI_LOCAL = 5,
+    JVMTI_HEAP_ROOT_THREAD = 6,
+    JVMTI_HEAP_ROOT_OTHER = 7
+} jvmtiHeapRootKind;
+
+    /* Object Reference Enumeration */
+
+typedef enum {
+    JVMTI_REFERENCE_CLASS = 1,
+    JVMTI_REFERENCE_FIELD = 2,
+    JVMTI_REFERENCE_ARRAY_ELEMENT = 3,
+    JVMTI_REFERENCE_CLASS_LOADER = 4,
+    JVMTI_REFERENCE_SIGNERS = 5,
+    JVMTI_REFERENCE_PROTECTION_DOMAIN = 6,
+    JVMTI_REFERENCE_INTERFACE = 7,
+    JVMTI_REFERENCE_STATIC_FIELD = 8,
+    JVMTI_REFERENCE_CONSTANT_POOL = 9
+} jvmtiObjectReferenceKind;
+
+    /* Iteration Control Enumeration */
+
+typedef enum {
+    JVMTI_ITERATION_CONTINUE = 1,
+    JVMTI_ITERATION_IGNORE = 2,
+    JVMTI_ITERATION_ABORT = 0
+} jvmtiIterationControl;
+
+    /* Class Status Flags */
+
+enum {
+    JVMTI_CLASS_STATUS_VERIFIED = 1,
+    JVMTI_CLASS_STATUS_PREPARED = 2,
+    JVMTI_CLASS_STATUS_INITIALIZED = 4,
+    JVMTI_CLASS_STATUS_ERROR = 8,
+    JVMTI_CLASS_STATUS_ARRAY = 16,
+    JVMTI_CLASS_STATUS_PRIMITIVE = 32
+};
+
+    /* Event Enable/Disable */
+
+typedef enum {
+    JVMTI_ENABLE = 1,
+    JVMTI_DISABLE = 0
+} jvmtiEventMode;
+
+    /* Extension Function/Event Parameter Types */
+
+typedef enum {
+    JVMTI_TYPE_JBYTE = 101,
+    JVMTI_TYPE_JCHAR = 102,
+    JVMTI_TYPE_JSHORT = 103,
+    JVMTI_TYPE_JINT = 104,
+    JVMTI_TYPE_JLONG = 105,
+    JVMTI_TYPE_JFLOAT = 106,
+    JVMTI_TYPE_JDOUBLE = 107,
+    JVMTI_TYPE_JBOOLEAN = 108,
+    JVMTI_TYPE_JOBJECT = 109,
+    JVMTI_TYPE_JTHREAD = 110,
+    JVMTI_TYPE_JCLASS = 111,
+    JVMTI_TYPE_JVALUE = 112,
+    JVMTI_TYPE_JFIELDID = 113,
+    JVMTI_TYPE_JMETHODID = 114,
+    JVMTI_TYPE_CCHAR = 115,
+    JVMTI_TYPE_CVOID = 116,
+    JVMTI_TYPE_JNIENV = 117
+} jvmtiParamTypes;
+
+    /* Extension Function/Event Parameter Kinds */
+
+typedef enum {
+    JVMTI_KIND_IN = 91,
+    JVMTI_KIND_IN_PTR = 92,
+    JVMTI_KIND_IN_BUF = 93,
+    JVMTI_KIND_ALLOC_BUF = 94,
+    JVMTI_KIND_ALLOC_ALLOC_BUF = 95,
+    JVMTI_KIND_OUT = 96,
+    JVMTI_KIND_OUT_BUF = 97
+} jvmtiParamKind;
+
+    /* Timer Kinds */
+
+typedef enum {
+    JVMTI_TIMER_USER_CPU = 30,
+    JVMTI_TIMER_TOTAL_CPU = 31,
+    JVMTI_TIMER_ELAPSED = 32
+} jvmtiTimerKind;
+
+    /* Phases of execution */
+
+typedef enum {
+    JVMTI_PHASE_ONLOAD = 1,
+    JVMTI_PHASE_PRIMORDIAL = 2,
+    JVMTI_PHASE_START = 6,
+    JVMTI_PHASE_LIVE = 4,
+    JVMTI_PHASE_DEAD = 8
+} jvmtiPhase;
+
+    /* Version Interface Types */
+
+enum {
+    JVMTI_VERSION_INTERFACE_JNI = 0x00000000,
+    JVMTI_VERSION_INTERFACE_JVMTI = 0x30000000
+};
+
+    /* Version Masks */
+
+enum {
+    JVMTI_VERSION_MASK_INTERFACE_TYPE = 0x70000000,
+    JVMTI_VERSION_MASK_MAJOR = 0x0FFF0000,
+    JVMTI_VERSION_MASK_MINOR = 0x0000FF00,
+    JVMTI_VERSION_MASK_MICRO = 0x000000FF
+};
+
+    /* Version Shifts */
+
+enum {
+    JVMTI_VERSION_SHIFT_MAJOR = 16,
+    JVMTI_VERSION_SHIFT_MINOR = 8,
+    JVMTI_VERSION_SHIFT_MICRO = 0
+};
+
+    /* Verbose Flag Enumeration */
+
+typedef enum {
+    JVMTI_VERBOSE_OTHER = 0,
+    JVMTI_VERBOSE_GC = 1,
+    JVMTI_VERBOSE_CLASS = 2,
+    JVMTI_VERBOSE_JNI = 4
+} jvmtiVerboseFlag;
+
+    /* JLocation Format Enumeration */
+
+typedef enum {
+    JVMTI_JLOCATION_JVMBCI = 1,
+    JVMTI_JLOCATION_MACHINEPC = 2,
+    JVMTI_JLOCATION_OTHER = 0
+} jvmtiJlocationFormat;
+
+    /* Resource Exhaustion Flags */
+
+enum {
+    JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR = 0x0001,
+    JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP = 0x0002,
+    JVMTI_RESOURCE_EXHAUSTED_THREADS = 0x0004
+};
+
+    /* Errors */
+
+typedef enum {
+    JVMTI_ERROR_NONE = 0,
+    JVMTI_ERROR_INVALID_THREAD = 10,
+    JVMTI_ERROR_INVALID_THREAD_GROUP = 11,
+    JVMTI_ERROR_INVALID_PRIORITY = 12,
+    JVMTI_ERROR_THREAD_NOT_SUSPENDED = 13,
+    JVMTI_ERROR_THREAD_SUSPENDED = 14,
+    JVMTI_ERROR_THREAD_NOT_ALIVE = 15,
+    JVMTI_ERROR_INVALID_OBJECT = 20,
+    JVMTI_ERROR_INVALID_CLASS = 21,
+    JVMTI_ERROR_CLASS_NOT_PREPARED = 22,
+    JVMTI_ERROR_INVALID_METHODID = 23,
+    JVMTI_ERROR_INVALID_LOCATION = 24,
+    JVMTI_ERROR_INVALID_FIELDID = 25,
+    JVMTI_ERROR_NO_MORE_FRAMES = 31,
+    JVMTI_ERROR_OPAQUE_FRAME = 32,
+    JVMTI_ERROR_TYPE_MISMATCH = 34,
+    JVMTI_ERROR_INVALID_SLOT = 35,
+    JVMTI_ERROR_DUPLICATE = 40,
+    JVMTI_ERROR_NOT_FOUND = 41,
+    JVMTI_ERROR_INVALID_MONITOR = 50,
+    JVMTI_ERROR_NOT_MONITOR_OWNER = 51,
+    JVMTI_ERROR_INTERRUPT = 52,
+    JVMTI_ERROR_INVALID_CLASS_FORMAT = 60,
+    JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION = 61,
+    JVMTI_ERROR_FAILS_VERIFICATION = 62,
+    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED = 63,
+    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED = 64,
+    JVMTI_ERROR_INVALID_TYPESTATE = 65,
+    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED = 66,
+    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED = 67,
+    JVMTI_ERROR_UNSUPPORTED_VERSION = 68,
+    JVMTI_ERROR_NAMES_DONT_MATCH = 69,
+    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED = 70,
+    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED = 71,
+    JVMTI_ERROR_UNMODIFIABLE_CLASS = 79,
+    JVMTI_ERROR_NOT_AVAILABLE = 98,
+    JVMTI_ERROR_MUST_POSSESS_CAPABILITY = 99,
+    JVMTI_ERROR_NULL_POINTER = 100,
+    JVMTI_ERROR_ABSENT_INFORMATION = 101,
+    JVMTI_ERROR_INVALID_EVENT_TYPE = 102,
+    JVMTI_ERROR_ILLEGAL_ARGUMENT = 103,
+    JVMTI_ERROR_NATIVE_METHOD = 104,
+    JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED = 106,
+    JVMTI_ERROR_OUT_OF_MEMORY = 110,
+    JVMTI_ERROR_ACCESS_DENIED = 111,
+    JVMTI_ERROR_WRONG_PHASE = 112,
+    JVMTI_ERROR_INTERNAL = 113,
+    JVMTI_ERROR_UNATTACHED_THREAD = 115,
+    JVMTI_ERROR_INVALID_ENVIRONMENT = 116,
+    JVMTI_ERROR_MAX = 116
+} jvmtiError;
+
+    /* Event IDs */
+
+typedef enum {
+    JVMTI_MIN_EVENT_TYPE_VAL = 50,
+    JVMTI_EVENT_VM_INIT = 50,
+    JVMTI_EVENT_VM_DEATH = 51,
+    JVMTI_EVENT_THREAD_START = 52,
+    JVMTI_EVENT_THREAD_END = 53,
+    JVMTI_EVENT_CLASS_FILE_LOAD_HOOK = 54,
+    JVMTI_EVENT_CLASS_LOAD = 55,
+    JVMTI_EVENT_CLASS_PREPARE = 56,
+    JVMTI_EVENT_VM_START = 57,
+    JVMTI_EVENT_EXCEPTION = 58,
+    JVMTI_EVENT_EXCEPTION_CATCH = 59,
+    JVMTI_EVENT_SINGLE_STEP = 60,
+    JVMTI_EVENT_FRAME_POP = 61,
+    JVMTI_EVENT_BREAKPOINT = 62,
+    JVMTI_EVENT_FIELD_ACCESS = 63,
+    JVMTI_EVENT_FIELD_MODIFICATION = 64,
+    JVMTI_EVENT_METHOD_ENTRY = 65,
+    JVMTI_EVENT_METHOD_EXIT = 66,
+    JVMTI_EVENT_NATIVE_METHOD_BIND = 67,
+    JVMTI_EVENT_COMPILED_METHOD_LOAD = 68,
+    JVMTI_EVENT_COMPILED_METHOD_UNLOAD = 69,
+    JVMTI_EVENT_DYNAMIC_CODE_GENERATED = 70,
+    JVMTI_EVENT_DATA_DUMP_REQUEST = 71,
+    JVMTI_EVENT_MONITOR_WAIT = 73,
+    JVMTI_EVENT_MONITOR_WAITED = 74,
+    JVMTI_EVENT_MONITOR_CONTENDED_ENTER = 75,
+    JVMTI_EVENT_MONITOR_CONTENDED_ENTERED = 76,
+    JVMTI_EVENT_RESOURCE_EXHAUSTED = 80,
+    JVMTI_EVENT_GARBAGE_COLLECTION_START = 81,
+    JVMTI_EVENT_GARBAGE_COLLECTION_FINISH = 82,
+    JVMTI_EVENT_OBJECT_FREE = 83,
+    JVMTI_EVENT_VM_OBJECT_ALLOC = 84,
+    JVMTI_MAX_EVENT_TYPE_VAL = 84
+} jvmtiEvent;
+
+
+    /* Pre-Declarations */
+struct _jvmtiThreadInfo;
+typedef struct _jvmtiThreadInfo jvmtiThreadInfo;
+struct _jvmtiMonitorStackDepthInfo;
+typedef struct _jvmtiMonitorStackDepthInfo jvmtiMonitorStackDepthInfo;
+struct _jvmtiThreadGroupInfo;
+typedef struct _jvmtiThreadGroupInfo jvmtiThreadGroupInfo;
+struct _jvmtiFrameInfo;
+typedef struct _jvmtiFrameInfo jvmtiFrameInfo;
+struct _jvmtiStackInfo;
+typedef struct _jvmtiStackInfo jvmtiStackInfo;
+struct _jvmtiHeapReferenceInfoField;
+typedef struct _jvmtiHeapReferenceInfoField jvmtiHeapReferenceInfoField;
+struct _jvmtiHeapReferenceInfoArray;
+typedef struct _jvmtiHeapReferenceInfoArray jvmtiHeapReferenceInfoArray;
+struct _jvmtiHeapReferenceInfoConstantPool;
+typedef struct _jvmtiHeapReferenceInfoConstantPool jvmtiHeapReferenceInfoConstantPool;
+struct _jvmtiHeapReferenceInfoStackLocal;
+typedef struct _jvmtiHeapReferenceInfoStackLocal jvmtiHeapReferenceInfoStackLocal;
+struct _jvmtiHeapReferenceInfoJniLocal;
+typedef struct _jvmtiHeapReferenceInfoJniLocal jvmtiHeapReferenceInfoJniLocal;
+struct _jvmtiHeapReferenceInfoReserved;
+typedef struct _jvmtiHeapReferenceInfoReserved jvmtiHeapReferenceInfoReserved;
+union _jvmtiHeapReferenceInfo;
+typedef union _jvmtiHeapReferenceInfo jvmtiHeapReferenceInfo;
+struct _jvmtiHeapCallbacks;
+typedef struct _jvmtiHeapCallbacks jvmtiHeapCallbacks;
+struct _jvmtiClassDefinition;
+typedef struct _jvmtiClassDefinition jvmtiClassDefinition;
+struct _jvmtiMonitorUsage;
+typedef struct _jvmtiMonitorUsage jvmtiMonitorUsage;
+struct _jvmtiLineNumberEntry;
+typedef struct _jvmtiLineNumberEntry jvmtiLineNumberEntry;
+struct _jvmtiLocalVariableEntry;
+typedef struct _jvmtiLocalVariableEntry jvmtiLocalVariableEntry;
+struct _jvmtiParamInfo;
+typedef struct _jvmtiParamInfo jvmtiParamInfo;
+struct _jvmtiExtensionFunctionInfo;
+typedef struct _jvmtiExtensionFunctionInfo jvmtiExtensionFunctionInfo;
+struct _jvmtiExtensionEventInfo;
+typedef struct _jvmtiExtensionEventInfo jvmtiExtensionEventInfo;
+struct _jvmtiTimerInfo;
+typedef struct _jvmtiTimerInfo jvmtiTimerInfo;
+struct _jvmtiAddrLocationMap;
+typedef struct _jvmtiAddrLocationMap jvmtiAddrLocationMap;
+
+    /* Function Types */
+
+typedef void (JNICALL *jvmtiStartFunction)
+    (jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg);
+
+typedef jint (JNICALL *jvmtiHeapIterationCallback)
+    (jlong class_tag, jlong size, jlong* tag_ptr, jint length, void* user_data);
+
+typedef jint (JNICALL *jvmtiHeapReferenceCallback)
+    (jvmtiHeapReferenceKind reference_kind, const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, jlong referrer_class_tag, jlong size, jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data);
+
+typedef jint (JNICALL *jvmtiPrimitiveFieldCallback)
+    (jvmtiHeapReferenceKind kind, const jvmtiHeapReferenceInfo* info, jlong object_class_tag, jlong* object_tag_ptr, jvalue value, jvmtiPrimitiveType value_type, void* user_data);
+
+typedef jint (JNICALL *jvmtiArrayPrimitiveValueCallback)
+    (jlong class_tag, jlong size, jlong* tag_ptr, jint element_count, jvmtiPrimitiveType element_type, const void* elements, void* user_data);
+
+typedef jint (JNICALL *jvmtiStringPrimitiveValueCallback)
+    (jlong class_tag, jlong size, jlong* tag_ptr, const jchar* value, jint value_length, void* user_data);
+
+typedef jint (JNICALL *jvmtiReservedCallback)
+    ();
+
+typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback)
+    (jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback)
+    (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiStackReferenceCallback)
+    (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong thread_tag, jint depth, jmethodID method, jint slot, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiObjectReferenceCallback)
+    (jvmtiObjectReferenceKind reference_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong referrer_tag, jint referrer_index, void* user_data);
+
+typedef jvmtiError (JNICALL *jvmtiExtensionFunction)
+    (jvmtiEnv* jvmti_env,  ...);
+
+typedef void (JNICALL *jvmtiExtensionEvent)
+    (jvmtiEnv* jvmti_env,  ...);
+
+
+    /* Structure Types */
+struct _jvmtiThreadInfo {
+    char* name;
+    jint priority;
+    jboolean is_daemon;
+    jthreadGroup thread_group;
+    jobject context_class_loader;
+};
+struct _jvmtiMonitorStackDepthInfo {
+    jobject monitor;
+    jint stack_depth;
+};
+struct _jvmtiThreadGroupInfo {
+    jthreadGroup parent;
+    char* name;
+    jint max_priority;
+    jboolean is_daemon;
+};
+struct _jvmtiFrameInfo {
+    jmethodID method;
+    jlocation location;
+};
+struct _jvmtiStackInfo {
+    jthread thread;
+    jint state;
+    jvmtiFrameInfo* frame_buffer;
+    jint frame_count;
+};
+struct _jvmtiHeapReferenceInfoField {
+    jint index;
+};
+struct _jvmtiHeapReferenceInfoArray {
+    jint index;
+};
+struct _jvmtiHeapReferenceInfoConstantPool {
+    jint index;
+};
+struct _jvmtiHeapReferenceInfoStackLocal {
+    jlong thread_tag;
+    jlong thread_id;
+    jint depth;
+    jmethodID method;
+    jlocation location;
+    jint slot;
+};
+struct _jvmtiHeapReferenceInfoJniLocal {
+    jlong thread_tag;
+    jlong thread_id;
+    jint depth;
+    jmethodID method;
+};
+struct _jvmtiHeapReferenceInfoReserved {
+    jlong reserved1;
+    jlong reserved2;
+    jlong reserved3;
+    jlong reserved4;
+    jlong reserved5;
+    jlong reserved6;
+    jlong reserved7;
+    jlong reserved8;
+};
+union _jvmtiHeapReferenceInfo {
+    jvmtiHeapReferenceInfoField field;
+    jvmtiHeapReferenceInfoArray array;
+    jvmtiHeapReferenceInfoConstantPool constant_pool;
+    jvmtiHeapReferenceInfoStackLocal stack_local;
+    jvmtiHeapReferenceInfoJniLocal jni_local;
+    jvmtiHeapReferenceInfoReserved other;
+};
+struct _jvmtiHeapCallbacks {
+    jvmtiHeapIterationCallback heap_iteration_callback;
+    jvmtiHeapReferenceCallback heap_reference_callback;
+    jvmtiPrimitiveFieldCallback primitive_field_callback;
+    jvmtiArrayPrimitiveValueCallback array_primitive_value_callback;
+    jvmtiStringPrimitiveValueCallback string_primitive_value_callback;
+    jvmtiReservedCallback reserved5;
+    jvmtiReservedCallback reserved6;
+    jvmtiReservedCallback reserved7;
+    jvmtiReservedCallback reserved8;
+    jvmtiReservedCallback reserved9;
+    jvmtiReservedCallback reserved10;
+    jvmtiReservedCallback reserved11;
+    jvmtiReservedCallback reserved12;
+    jvmtiReservedCallback reserved13;
+    jvmtiReservedCallback reserved14;
+    jvmtiReservedCallback reserved15;
+};
+struct _jvmtiClassDefinition {
+    jclass klass;
+    jint class_byte_count;
+    const unsigned char* class_bytes;
+};
+struct _jvmtiMonitorUsage {
+    jthread owner;
+    jint entry_count;
+    jint waiter_count;
+    jthread* waiters;
+    jint notify_waiter_count;
+    jthread* notify_waiters;
+};
+struct _jvmtiLineNumberEntry {
+    jlocation start_location;
+    jint line_number;
+};
+struct _jvmtiLocalVariableEntry {
+    jlocation start_location;
+    jint length;
+    char* name;
+    char* signature;
+    char* generic_signature;
+    jint slot;
+};
+struct _jvmtiParamInfo {
+    char* name;
+    jvmtiParamKind kind;
+    jvmtiParamTypes base_type;
+    jboolean null_ok;
+};
+struct _jvmtiExtensionFunctionInfo {
+    jvmtiExtensionFunction func;
+    char* id;
+    char* short_description;
+    jint param_count;
+    jvmtiParamInfo* params;
+    jint error_count;
+    jvmtiError* errors;
+};
+struct _jvmtiExtensionEventInfo {
+    jint extension_event_index;
+    char* id;
+    char* short_description;
+    jint param_count;
+    jvmtiParamInfo* params;
+};
+struct _jvmtiTimerInfo {
+    jlong max_value;
+    jboolean may_skip_forward;
+    jboolean may_skip_backward;
+    jvmtiTimerKind kind;
+    jlong reserved1;
+    jlong reserved2;
+};
+struct _jvmtiAddrLocationMap {
+    const void* start_address;
+    jlocation location;
+};
+
+typedef struct {
+    unsigned int can_tag_objects : 1;
+    unsigned int can_generate_field_modification_events : 1;
+    unsigned int can_generate_field_access_events : 1;
+    unsigned int can_get_bytecodes : 1;
+    unsigned int can_get_synthetic_attribute : 1;
+    unsigned int can_get_owned_monitor_info : 1;
+    unsigned int can_get_current_contended_monitor : 1;
+    unsigned int can_get_monitor_info : 1;
+    unsigned int can_pop_frame : 1;
+    unsigned int can_redefine_classes : 1;
+    unsigned int can_signal_thread : 1;
+    unsigned int can_get_source_file_name : 1;
+    unsigned int can_get_line_numbers : 1;
+    unsigned int can_get_source_debug_extension : 1;
+    unsigned int can_access_local_variables : 1;
+    unsigned int can_maintain_original_method_order : 1;
+    unsigned int can_generate_single_step_events : 1;
+    unsigned int can_generate_exception_events : 1;
+    unsigned int can_generate_frame_pop_events : 1;
+    unsigned int can_generate_breakpoint_events : 1;
+    unsigned int can_suspend : 1;
+    unsigned int can_redefine_any_class : 1;
+    unsigned int can_get_current_thread_cpu_time : 1;
+    unsigned int can_get_thread_cpu_time : 1;
+    unsigned int can_generate_method_entry_events : 1;
+    unsigned int can_generate_method_exit_events : 1;
+    unsigned int can_generate_all_class_hook_events : 1;
+    unsigned int can_generate_compiled_method_load_events : 1;
+    unsigned int can_generate_monitor_events : 1;
+    unsigned int can_generate_vm_object_alloc_events : 1;
+    unsigned int can_generate_native_method_bind_events : 1;
+    unsigned int can_generate_garbage_collection_events : 1;
+    unsigned int can_generate_object_free_events : 1;
+    unsigned int can_force_early_return : 1;
+    unsigned int can_get_owned_monitor_stack_depth_info : 1;
+    unsigned int can_get_constant_pool : 1;
+    unsigned int can_set_native_method_prefix : 1;
+    unsigned int can_retransform_classes : 1;
+    unsigned int can_retransform_any_class : 1;
+    unsigned int can_generate_resource_exhaustion_heap_events : 1;
+    unsigned int can_generate_resource_exhaustion_threads_events : 1;
+    unsigned int : 7;
+    unsigned int : 16;
+    unsigned int : 16;
+    unsigned int : 16;
+    unsigned int : 16;
+    unsigned int : 16;
+} jvmtiCapabilities;
+
+
+    /* Event Definitions */
+
+typedef void (JNICALL *jvmtiEventReserved)(void);
+
+
+typedef void (JNICALL *jvmtiEventBreakpoint)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jmethodID method,
+     jlocation location);
+
+typedef void (JNICALL *jvmtiEventClassFileLoadHook)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jclass class_being_redefined,
+     jobject loader,
+     const char* name,
+     jobject protection_domain,
+     jint class_data_len,
+     const unsigned char* class_data,
+     jint* new_class_data_len,
+     unsigned char** new_class_data);
+
+typedef void (JNICALL *jvmtiEventClassLoad)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jclass klass);
+
+typedef void (JNICALL *jvmtiEventClassPrepare)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jclass klass);
+
+typedef void (JNICALL *jvmtiEventCompiledMethodLoad)
+    (jvmtiEnv *jvmti_env,
+     jmethodID method,
+     jint code_size,
+     const void* code_addr,
+     jint map_length,
+     const jvmtiAddrLocationMap* map,
+     const void* compile_info);
+
+typedef void (JNICALL *jvmtiEventCompiledMethodUnload)
+    (jvmtiEnv *jvmti_env,
+     jmethodID method,
+     const void* code_addr);
+
+typedef void (JNICALL *jvmtiEventDataDumpRequest)
+    (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventDynamicCodeGenerated)
+    (jvmtiEnv *jvmti_env,
+     const char* name,
+     const void* address,
+     jint length);
+
+typedef void (JNICALL *jvmtiEventException)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jmethodID method,
+     jlocation location,
+     jobject exception,
+     jmethodID catch_method,
+     jlocation catch_location);
+
+typedef void (JNICALL *jvmtiEventExceptionCatch)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jmethodID method,
+     jlocation location,
+     jobject exception);
+
+typedef void (JNICALL *jvmtiEventFieldAccess)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jmethodID method,
+     jlocation location,
+     jclass field_klass,
+     jobject object,
+     jfieldID field);
+
+typedef void (JNICALL *jvmtiEventFieldModification)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jmethodID method,
+     jlocation location,
+     jclass field_klass,
+     jobject object,
+     jfieldID field,
+     char signature_type,
+     jvalue new_value);
+
+typedef void (JNICALL *jvmtiEventFramePop)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jmethodID method,
+     jboolean was_popped_by_exception);
+
+typedef void (JNICALL *jvmtiEventGarbageCollectionFinish)
+    (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventGarbageCollectionStart)
+    (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventMethodEntry)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jmethodID method);
+
+typedef void (JNICALL *jvmtiEventMethodExit)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jmethodID method,
+     jboolean was_popped_by_exception,
+     jvalue return_value);
+
+typedef void (JNICALL *jvmtiEventMonitorContendedEnter)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jobject object);
+
+typedef void (JNICALL *jvmtiEventMonitorContendedEntered)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jobject object);
+
+typedef void (JNICALL *jvmtiEventMonitorWait)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jobject object,
+     jlong timeout);
+
+typedef void (JNICALL *jvmtiEventMonitorWaited)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jobject object,
+     jboolean timed_out);
+
+typedef void (JNICALL *jvmtiEventNativeMethodBind)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jmethodID method,
+     void* address,
+     void** new_address_ptr);
+
+typedef void (JNICALL *jvmtiEventObjectFree)
+    (jvmtiEnv *jvmti_env,
+     jlong tag);
+
+typedef void (JNICALL *jvmtiEventResourceExhausted)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jint flags,
+     const void* reserved,
+     const char* description);
+
+typedef void (JNICALL *jvmtiEventSingleStep)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jmethodID method,
+     jlocation location);
+
+typedef void (JNICALL *jvmtiEventThreadEnd)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread);
+
+typedef void (JNICALL *jvmtiEventThreadStart)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread);
+
+typedef void (JNICALL *jvmtiEventVMDeath)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env);
+
+typedef void (JNICALL *jvmtiEventVMInit)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread);
+
+typedef void (JNICALL *jvmtiEventVMObjectAlloc)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env,
+     jthread thread,
+     jobject object,
+     jclass object_klass,
+     jlong size);
+
+typedef void (JNICALL *jvmtiEventVMStart)
+    (jvmtiEnv *jvmti_env,
+     JNIEnv* jni_env);
+
+    /* Event Callback Structure */
+
+typedef struct {
+                              /*   50 : VM Initialization Event */
+    jvmtiEventVMInit VMInit;
+                              /*   51 : VM Death Event */
+    jvmtiEventVMDeath VMDeath;
+                              /*   52 : Thread Start */
+    jvmtiEventThreadStart ThreadStart;
+                              /*   53 : Thread End */
+    jvmtiEventThreadEnd ThreadEnd;
+                              /*   54 : Class File Load Hook */
+    jvmtiEventClassFileLoadHook ClassFileLoadHook;
+                              /*   55 : Class Load */
+    jvmtiEventClassLoad ClassLoad;
+                              /*   56 : Class Prepare */
+    jvmtiEventClassPrepare ClassPrepare;
+                              /*   57 : VM Start Event */
+    jvmtiEventVMStart VMStart;
+                              /*   58 : Exception */
+    jvmtiEventException Exception;
+                              /*   59 : Exception Catch */
+    jvmtiEventExceptionCatch ExceptionCatch;
+                              /*   60 : Single Step */
+    jvmtiEventSingleStep SingleStep;
+                              /*   61 : Frame Pop */
+    jvmtiEventFramePop FramePop;
+                              /*   62 : Breakpoint */
+    jvmtiEventBreakpoint Breakpoint;
+                              /*   63 : Field Access */
+    jvmtiEventFieldAccess FieldAccess;
+                              /*   64 : Field Modification */
+    jvmtiEventFieldModification FieldModification;
+                              /*   65 : Method Entry */
+    jvmtiEventMethodEntry MethodEntry;
+                              /*   66 : Method Exit */
+    jvmtiEventMethodExit MethodExit;
+                              /*   67 : Native Method Bind */
+    jvmtiEventNativeMethodBind NativeMethodBind;
+                              /*   68 : Compiled Method Load */
+    jvmtiEventCompiledMethodLoad CompiledMethodLoad;
+                              /*   69 : Compiled Method Unload */
+    jvmtiEventCompiledMethodUnload CompiledMethodUnload;
+                              /*   70 : Dynamic Code Generated */
+    jvmtiEventDynamicCodeGenerated DynamicCodeGenerated;
+                              /*   71 : Data Dump Request */
+    jvmtiEventDataDumpRequest DataDumpRequest;
+                              /*   72 */
+    jvmtiEventReserved reserved72;
+                              /*   73 : Monitor Wait */
+    jvmtiEventMonitorWait MonitorWait;
+                              /*   74 : Monitor Waited */
+    jvmtiEventMonitorWaited MonitorWaited;
+                              /*   75 : Monitor Contended Enter */
+    jvmtiEventMonitorContendedEnter MonitorContendedEnter;
+                              /*   76 : Monitor Contended Entered */
+    jvmtiEventMonitorContendedEntered MonitorContendedEntered;
+                              /*   77 */
+    jvmtiEventReserved reserved77;
+                              /*   78 */
+    jvmtiEventReserved reserved78;
+                              /*   79 */
+    jvmtiEventReserved reserved79;
+                              /*   80 : Resource Exhausted */
+    jvmtiEventResourceExhausted ResourceExhausted;
+                              /*   81 : Garbage Collection Start */
+    jvmtiEventGarbageCollectionStart GarbageCollectionStart;
+                              /*   82 : Garbage Collection Finish */
+    jvmtiEventGarbageCollectionFinish GarbageCollectionFinish;
+                              /*   83 : Object Free */
+    jvmtiEventObjectFree ObjectFree;
+                              /*   84 : VM Object Allocation */
+    jvmtiEventVMObjectAlloc VMObjectAlloc;
+} jvmtiEventCallbacks;
+
+
+    /* Function Interface */
+
+typedef struct jvmtiInterface_1_ {
+
+  /*   1 :  RESERVED */
+  void *reserved1;
+
+  /*   2 : Set Event Notification Mode */
+  jvmtiError (JNICALL *SetEventNotificationMode) (jvmtiEnv* env,
+    jvmtiEventMode mode,
+    jvmtiEvent event_type,
+    jthread event_thread,
+     ...);
+
+  /*   3 :  RESERVED */
+  void *reserved3;
+
+  /*   4 : Get All Threads */
+  jvmtiError (JNICALL *GetAllThreads) (jvmtiEnv* env,
+    jint* threads_count_ptr,
+    jthread** threads_ptr);
+
+  /*   5 : Suspend Thread */
+  jvmtiError (JNICALL *SuspendThread) (jvmtiEnv* env,
+    jthread thread);
+
+  /*   6 : Resume Thread */
+  jvmtiError (JNICALL *ResumeThread) (jvmtiEnv* env,
+    jthread thread);
+
+  /*   7 : Stop Thread */
+  jvmtiError (JNICALL *StopThread) (jvmtiEnv* env,
+    jthread thread,
+    jobject exception);
+
+  /*   8 : Interrupt Thread */
+  jvmtiError (JNICALL *InterruptThread) (jvmtiEnv* env,
+    jthread thread);
+
+  /*   9 : Get Thread Info */
+  jvmtiError (JNICALL *GetThreadInfo) (jvmtiEnv* env,
+    jthread thread,
+    jvmtiThreadInfo* info_ptr);
+
+  /*   10 : Get Owned Monitor Info */
+  jvmtiError (JNICALL *GetOwnedMonitorInfo) (jvmtiEnv* env,
+    jthread thread,
+    jint* owned_monitor_count_ptr,
+    jobject** owned_monitors_ptr);
+
+  /*   11 : Get Current Contended Monitor */
+  jvmtiError (JNICALL *GetCurrentContendedMonitor) (jvmtiEnv* env,
+    jthread thread,
+    jobject* monitor_ptr);
+
+  /*   12 : Run Agent Thread */
+  jvmtiError (JNICALL *RunAgentThread) (jvmtiEnv* env,
+    jthread thread,
+    jvmtiStartFunction proc,
+    const void* arg,
+    jint priority);
+
+  /*   13 : Get Top Thread Groups */
+  jvmtiError (JNICALL *GetTopThreadGroups) (jvmtiEnv* env,
+    jint* group_count_ptr,
+    jthreadGroup** groups_ptr);
+
+  /*   14 : Get Thread Group Info */
+  jvmtiError (JNICALL *GetThreadGroupInfo) (jvmtiEnv* env,
+    jthreadGroup group,
+    jvmtiThreadGroupInfo* info_ptr);
+
+  /*   15 : Get Thread Group Children */
+  jvmtiError (JNICALL *GetThreadGroupChildren) (jvmtiEnv* env,
+    jthreadGroup group,
+    jint* thread_count_ptr,
+    jthread** threads_ptr,
+    jint* group_count_ptr,
+    jthreadGroup** groups_ptr);
+
+  /*   16 : Get Frame Count */
+  jvmtiError (JNICALL *GetFrameCount) (jvmtiEnv* env,
+    jthread thread,
+    jint* count_ptr);
+
+  /*   17 : Get Thread State */
+  jvmtiError (JNICALL *GetThreadState) (jvmtiEnv* env,
+    jthread thread,
+    jint* thread_state_ptr);
+
+  /*   18 : Get Current Thread */
+  jvmtiError (JNICALL *GetCurrentThread) (jvmtiEnv* env,
+    jthread* thread_ptr);
+
+  /*   19 : Get Frame Location */
+  jvmtiError (JNICALL *GetFrameLocation) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jmethodID* method_ptr,
+    jlocation* location_ptr);
+
+  /*   20 : Notify Frame Pop */
+  jvmtiError (JNICALL *NotifyFramePop) (jvmtiEnv* env,
+    jthread thread,
+    jint depth);
+
+  /*   21 : Get Local Variable - Object */
+  jvmtiError (JNICALL *GetLocalObject) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jint slot,
+    jobject* value_ptr);
+
+  /*   22 : Get Local Variable - Int */
+  jvmtiError (JNICALL *GetLocalInt) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jint slot,
+    jint* value_ptr);
+
+  /*   23 : Get Local Variable - Long */
+  jvmtiError (JNICALL *GetLocalLong) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jint slot,
+    jlong* value_ptr);
+
+  /*   24 : Get Local Variable - Float */
+  jvmtiError (JNICALL *GetLocalFloat) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jint slot,
+    jfloat* value_ptr);
+
+  /*   25 : Get Local Variable - Double */
+  jvmtiError (JNICALL *GetLocalDouble) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jint slot,
+    jdouble* value_ptr);
+
+  /*   26 : Set Local Variable - Object */
+  jvmtiError (JNICALL *SetLocalObject) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jint slot,
+    jobject value);
+
+  /*   27 : Set Local Variable - Int */
+  jvmtiError (JNICALL *SetLocalInt) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jint slot,
+    jint value);
+
+  /*   28 : Set Local Variable - Long */
+  jvmtiError (JNICALL *SetLocalLong) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jint slot,
+    jlong value);
+
+  /*   29 : Set Local Variable - Float */
+  jvmtiError (JNICALL *SetLocalFloat) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jint slot,
+    jfloat value);
+
+  /*   30 : Set Local Variable - Double */
+  jvmtiError (JNICALL *SetLocalDouble) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jint slot,
+    jdouble value);
+
+  /*   31 : Create Raw Monitor */
+  jvmtiError (JNICALL *CreateRawMonitor) (jvmtiEnv* env,
+    const char* name,
+    jrawMonitorID* monitor_ptr);
+
+  /*   32 : Destroy Raw Monitor */
+  jvmtiError (JNICALL *DestroyRawMonitor) (jvmtiEnv* env,
+    jrawMonitorID monitor);
+
+  /*   33 : Raw Monitor Enter */
+  jvmtiError (JNICALL *RawMonitorEnter) (jvmtiEnv* env,
+    jrawMonitorID monitor);
+
+  /*   34 : Raw Monitor Exit */
+  jvmtiError (JNICALL *RawMonitorExit) (jvmtiEnv* env,
+    jrawMonitorID monitor);
+
+  /*   35 : Raw Monitor Wait */
+  jvmtiError (JNICALL *RawMonitorWait) (jvmtiEnv* env,
+    jrawMonitorID monitor,
+    jlong millis);
+
+  /*   36 : Raw Monitor Notify */
+  jvmtiError (JNICALL *RawMonitorNotify) (jvmtiEnv* env,
+    jrawMonitorID monitor);
+
+  /*   37 : Raw Monitor Notify All */
+  jvmtiError (JNICALL *RawMonitorNotifyAll) (jvmtiEnv* env,
+    jrawMonitorID monitor);
+
+  /*   38 : Set Breakpoint */
+  jvmtiError (JNICALL *SetBreakpoint) (jvmtiEnv* env,
+    jmethodID method,
+    jlocation location);
+
+  /*   39 : Clear Breakpoint */
+  jvmtiError (JNICALL *ClearBreakpoint) (jvmtiEnv* env,
+    jmethodID method,
+    jlocation location);
+
+  /*   40 :  RESERVED */
+  void *reserved40;
+
+  /*   41 : Set Field Access Watch */
+  jvmtiError (JNICALL *SetFieldAccessWatch) (jvmtiEnv* env,
+    jclass klass,
+    jfieldID field);
+
+  /*   42 : Clear Field Access Watch */
+  jvmtiError (JNICALL *ClearFieldAccessWatch) (jvmtiEnv* env,
+    jclass klass,
+    jfieldID field);
+
+  /*   43 : Set Field Modification Watch */
+  jvmtiError (JNICALL *SetFieldModificationWatch) (jvmtiEnv* env,
+    jclass klass,
+    jfieldID field);
+
+  /*   44 : Clear Field Modification Watch */
+  jvmtiError (JNICALL *ClearFieldModificationWatch) (jvmtiEnv* env,
+    jclass klass,
+    jfieldID field);
+
+  /*   45 : Is Modifiable Class */
+  jvmtiError (JNICALL *IsModifiableClass) (jvmtiEnv* env,
+    jclass klass,
+    jboolean* is_modifiable_class_ptr);
+
+  /*   46 : Allocate */
+  jvmtiError (JNICALL *Allocate) (jvmtiEnv* env,
+    jlong size,
+    unsigned char** mem_ptr);
+
+  /*   47 : Deallocate */
+  jvmtiError (JNICALL *Deallocate) (jvmtiEnv* env,
+    unsigned char* mem);
+
+  /*   48 : Get Class Signature */
+  jvmtiError (JNICALL *GetClassSignature) (jvmtiEnv* env,
+    jclass klass,
+    char** signature_ptr,
+    char** generic_ptr);
+
+  /*   49 : Get Class Status */
+  jvmtiError (JNICALL *GetClassStatus) (jvmtiEnv* env,
+    jclass klass,
+    jint* status_ptr);
+
+  /*   50 : Get Source File Name */
+  jvmtiError (JNICALL *GetSourceFileName) (jvmtiEnv* env,
+    jclass klass,
+    char** source_name_ptr);
+
+  /*   51 : Get Class Modifiers */
+  jvmtiError (JNICALL *GetClassModifiers) (jvmtiEnv* env,
+    jclass klass,
+    jint* modifiers_ptr);
+
+  /*   52 : Get Class Methods */
+  jvmtiError (JNICALL *GetClassMethods) (jvmtiEnv* env,
+    jclass klass,
+    jint* method_count_ptr,
+    jmethodID** methods_ptr);
+
+  /*   53 : Get Class Fields */
+  jvmtiError (JNICALL *GetClassFields) (jvmtiEnv* env,
+    jclass klass,
+    jint* field_count_ptr,
+    jfieldID** fields_ptr);
+
+  /*   54 : Get Implemented Interfaces */
+  jvmtiError (JNICALL *GetImplementedInterfaces) (jvmtiEnv* env,
+    jclass klass,
+    jint* interface_count_ptr,
+    jclass** interfaces_ptr);
+
+  /*   55 : Is Interface */
+  jvmtiError (JNICALL *IsInterface) (jvmtiEnv* env,
+    jclass klass,
+    jboolean* is_interface_ptr);
+
+  /*   56 : Is Array Class */
+  jvmtiError (JNICALL *IsArrayClass) (jvmtiEnv* env,
+    jclass klass,
+    jboolean* is_array_class_ptr);
+
+  /*   57 : Get Class Loader */
+  jvmtiError (JNICALL *GetClassLoader) (jvmtiEnv* env,
+    jclass klass,
+    jobject* classloader_ptr);
+
+  /*   58 : Get Object Hash Code */
+  jvmtiError (JNICALL *GetObjectHashCode) (jvmtiEnv* env,
+    jobject object,
+    jint* hash_code_ptr);
+
+  /*   59 : Get Object Monitor Usage */
+  jvmtiError (JNICALL *GetObjectMonitorUsage) (jvmtiEnv* env,
+    jobject object,
+    jvmtiMonitorUsage* info_ptr);
+
+  /*   60 : Get Field Name (and Signature) */
+  jvmtiError (JNICALL *GetFieldName) (jvmtiEnv* env,
+    jclass klass,
+    jfieldID field,
+    char** name_ptr,
+    char** signature_ptr,
+    char** generic_ptr);
+
+  /*   61 : Get Field Declaring Class */
+  jvmtiError (JNICALL *GetFieldDeclaringClass) (jvmtiEnv* env,
+    jclass klass,
+    jfieldID field,
+    jclass* declaring_class_ptr);
+
+  /*   62 : Get Field Modifiers */
+  jvmtiError (JNICALL *GetFieldModifiers) (jvmtiEnv* env,
+    jclass klass,
+    jfieldID field,
+    jint* modifiers_ptr);
+
+  /*   63 : Is Field Synthetic */
+  jvmtiError (JNICALL *IsFieldSynthetic) (jvmtiEnv* env,
+    jclass klass,
+    jfieldID field,
+    jboolean* is_synthetic_ptr);
+
+  /*   64 : Get Method Name (and Signature) */
+  jvmtiError (JNICALL *GetMethodName) (jvmtiEnv* env,
+    jmethodID method,
+    char** name_ptr,
+    char** signature_ptr,
+    char** generic_ptr);
+
+  /*   65 : Get Method Declaring Class */
+  jvmtiError (JNICALL *GetMethodDeclaringClass) (jvmtiEnv* env,
+    jmethodID method,
+    jclass* declaring_class_ptr);
+
+  /*   66 : Get Method Modifiers */
+  jvmtiError (JNICALL *GetMethodModifiers) (jvmtiEnv* env,
+    jmethodID method,
+    jint* modifiers_ptr);
+
+  /*   67 :  RESERVED */
+  void *reserved67;
+
+  /*   68 : Get Max Locals */
+  jvmtiError (JNICALL *GetMaxLocals) (jvmtiEnv* env,
+    jmethodID method,
+    jint* max_ptr);
+
+  /*   69 : Get Arguments Size */
+  jvmtiError (JNICALL *GetArgumentsSize) (jvmtiEnv* env,
+    jmethodID method,
+    jint* size_ptr);
+
+  /*   70 : Get Line Number Table */
+  jvmtiError (JNICALL *GetLineNumberTable) (jvmtiEnv* env,
+    jmethodID method,
+    jint* entry_count_ptr,
+    jvmtiLineNumberEntry** table_ptr);
+
+  /*   71 : Get Method Location */
+  jvmtiError (JNICALL *GetMethodLocation) (jvmtiEnv* env,
+    jmethodID method,
+    jlocation* start_location_ptr,
+    jlocation* end_location_ptr);
+
+  /*   72 : Get Local Variable Table */
+  jvmtiError (JNICALL *GetLocalVariableTable) (jvmtiEnv* env,
+    jmethodID method,
+    jint* entry_count_ptr,
+    jvmtiLocalVariableEntry** table_ptr);
+
+  /*   73 : Set Native Method Prefix */
+  jvmtiError (JNICALL *SetNativeMethodPrefix) (jvmtiEnv* env,
+    const char* prefix);
+
+  /*   74 : Set Native Method Prefixes */
+  jvmtiError (JNICALL *SetNativeMethodPrefixes) (jvmtiEnv* env,
+    jint prefix_count,
+    char** prefixes);
+
+  /*   75 : Get Bytecodes */
+  jvmtiError (JNICALL *GetBytecodes) (jvmtiEnv* env,
+    jmethodID method,
+    jint* bytecode_count_ptr,
+    unsigned char** bytecodes_ptr);
+
+  /*   76 : Is Method Native */
+  jvmtiError (JNICALL *IsMethodNative) (jvmtiEnv* env,
+    jmethodID method,
+    jboolean* is_native_ptr);
+
+  /*   77 : Is Method Synthetic */
+  jvmtiError (JNICALL *IsMethodSynthetic) (jvmtiEnv* env,
+    jmethodID method,
+    jboolean* is_synthetic_ptr);
+
+  /*   78 : Get Loaded Classes */
+  jvmtiError (JNICALL *GetLoadedClasses) (jvmtiEnv* env,
+    jint* class_count_ptr,
+    jclass** classes_ptr);
+
+  /*   79 : Get Classloader Classes */
+  jvmtiError (JNICALL *GetClassLoaderClasses) (jvmtiEnv* env,
+    jobject initiating_loader,
+    jint* class_count_ptr,
+    jclass** classes_ptr);
+
+  /*   80 : Pop Frame */
+  jvmtiError (JNICALL *PopFrame) (jvmtiEnv* env,
+    jthread thread);
+
+  /*   81 : Force Early Return - Object */
+  jvmtiError (JNICALL *ForceEarlyReturnObject) (jvmtiEnv* env,
+    jthread thread,
+    jobject value);
+
+  /*   82 : Force Early Return - Int */
+  jvmtiError (JNICALL *ForceEarlyReturnInt) (jvmtiEnv* env,
+    jthread thread,
+    jint value);
+
+  /*   83 : Force Early Return - Long */
+  jvmtiError (JNICALL *ForceEarlyReturnLong) (jvmtiEnv* env,
+    jthread thread,
+    jlong value);
+
+  /*   84 : Force Early Return - Float */
+  jvmtiError (JNICALL *ForceEarlyReturnFloat) (jvmtiEnv* env,
+    jthread thread,
+    jfloat value);
+
+  /*   85 : Force Early Return - Double */
+  jvmtiError (JNICALL *ForceEarlyReturnDouble) (jvmtiEnv* env,
+    jthread thread,
+    jdouble value);
+
+  /*   86 : Force Early Return - Void */
+  jvmtiError (JNICALL *ForceEarlyReturnVoid) (jvmtiEnv* env,
+    jthread thread);
+
+  /*   87 : Redefine Classes */
+  jvmtiError (JNICALL *RedefineClasses) (jvmtiEnv* env,
+    jint class_count,
+    const jvmtiClassDefinition* class_definitions);
+
+  /*   88 : Get Version Number */
+  jvmtiError (JNICALL *GetVersionNumber) (jvmtiEnv* env,
+    jint* version_ptr);
+
+  /*   89 : Get Capabilities */
+  jvmtiError (JNICALL *GetCapabilities) (jvmtiEnv* env,
+    jvmtiCapabilities* capabilities_ptr);
+
+  /*   90 : Get Source Debug Extension */
+  jvmtiError (JNICALL *GetSourceDebugExtension) (jvmtiEnv* env,
+    jclass klass,
+    char** source_debug_extension_ptr);
+
+  /*   91 : Is Method Obsolete */
+  jvmtiError (JNICALL *IsMethodObsolete) (jvmtiEnv* env,
+    jmethodID method,
+    jboolean* is_obsolete_ptr);
+
+  /*   92 : Suspend Thread List */
+  jvmtiError (JNICALL *SuspendThreadList) (jvmtiEnv* env,
+    jint request_count,
+    const jthread* request_list,
+    jvmtiError* results);
+
+  /*   93 : Resume Thread List */
+  jvmtiError (JNICALL *ResumeThreadList) (jvmtiEnv* env,
+    jint request_count,
+    const jthread* request_list,
+    jvmtiError* results);
+
+  /*   94 :  RESERVED */
+  void *reserved94;
+
+  /*   95 :  RESERVED */
+  void *reserved95;
+
+  /*   96 :  RESERVED */
+  void *reserved96;
+
+  /*   97 :  RESERVED */
+  void *reserved97;
+
+  /*   98 :  RESERVED */
+  void *reserved98;
+
+  /*   99 :  RESERVED */
+  void *reserved99;
+
+  /*   100 : Get All Stack Traces */
+  jvmtiError (JNICALL *GetAllStackTraces) (jvmtiEnv* env,
+    jint max_frame_count,
+    jvmtiStackInfo** stack_info_ptr,
+    jint* thread_count_ptr);
+
+  /*   101 : Get Thread List Stack Traces */
+  jvmtiError (JNICALL *GetThreadListStackTraces) (jvmtiEnv* env,
+    jint thread_count,
+    const jthread* thread_list,
+    jint max_frame_count,
+    jvmtiStackInfo** stack_info_ptr);
+
+  /*   102 : Get Thread Local Storage */
+  jvmtiError (JNICALL *GetThreadLocalStorage) (jvmtiEnv* env,
+    jthread thread,
+    void** data_ptr);
+
+  /*   103 : Set Thread Local Storage */
+  jvmtiError (JNICALL *SetThreadLocalStorage) (jvmtiEnv* env,
+    jthread thread,
+    const void* data);
+
+  /*   104 : Get Stack Trace */
+  jvmtiError (JNICALL *GetStackTrace) (jvmtiEnv* env,
+    jthread thread,
+    jint start_depth,
+    jint max_frame_count,
+    jvmtiFrameInfo* frame_buffer,
+    jint* count_ptr);
+
+  /*   105 :  RESERVED */
+  void *reserved105;
+
+  /*   106 : Get Tag */
+  jvmtiError (JNICALL *GetTag) (jvmtiEnv* env,
+    jobject object,
+    jlong* tag_ptr);
+
+  /*   107 : Set Tag */
+  jvmtiError (JNICALL *SetTag) (jvmtiEnv* env,
+    jobject object,
+    jlong tag);
+
+  /*   108 : Force Garbage Collection */
+  jvmtiError (JNICALL *ForceGarbageCollection) (jvmtiEnv* env);
+
+  /*   109 : Iterate Over Objects Reachable From Object */
+  jvmtiError (JNICALL *IterateOverObjectsReachableFromObject) (jvmtiEnv* env,
+    jobject object,
+    jvmtiObjectReferenceCallback object_reference_callback,
+    const void* user_data);
+
+  /*   110 : Iterate Over Reachable Objects */
+  jvmtiError (JNICALL *IterateOverReachableObjects) (jvmtiEnv* env,
+    jvmtiHeapRootCallback heap_root_callback,
+    jvmtiStackReferenceCallback stack_ref_callback,
+    jvmtiObjectReferenceCallback object_ref_callback,
+    const void* user_data);
+
+  /*   111 : Iterate Over Heap */
+  jvmtiError (JNICALL *IterateOverHeap) (jvmtiEnv* env,
+    jvmtiHeapObjectFilter object_filter,
+    jvmtiHeapObjectCallback heap_object_callback,
+    const void* user_data);
+
+  /*   112 : Iterate Over Instances Of Class */
+  jvmtiError (JNICALL *IterateOverInstancesOfClass) (jvmtiEnv* env,
+    jclass klass,
+    jvmtiHeapObjectFilter object_filter,
+    jvmtiHeapObjectCallback heap_object_callback,
+    const void* user_data);
+
+  /*   113 :  RESERVED */
+  void *reserved113;
+
+  /*   114 : Get Objects With Tags */
+  jvmtiError (JNICALL *GetObjectsWithTags) (jvmtiEnv* env,
+    jint tag_count,
+    const jlong* tags,
+    jint* count_ptr,
+    jobject** object_result_ptr,
+    jlong** tag_result_ptr);
+
+  /*   115 : Follow References */
+  jvmtiError (JNICALL *FollowReferences) (jvmtiEnv* env,
+    jint heap_filter,
+    jclass klass,
+    jobject initial_object,
+    const jvmtiHeapCallbacks* callbacks,
+    const void* user_data);
+
+  /*   116 : Iterate Through Heap */
+  jvmtiError (JNICALL *IterateThroughHeap) (jvmtiEnv* env,
+    jint heap_filter,
+    jclass klass,
+    const jvmtiHeapCallbacks* callbacks,
+    const void* user_data);
+
+  /*   117 :  RESERVED */
+  void *reserved117;
+
+  /*   118 :  RESERVED */
+  void *reserved118;
+
+  /*   119 :  RESERVED */
+  void *reserved119;
+
+  /*   120 : Set JNI Function Table */
+  jvmtiError (JNICALL *SetJNIFunctionTable) (jvmtiEnv* env,
+    const jniNativeInterface* function_table);
+
+  /*   121 : Get JNI Function Table */
+  jvmtiError (JNICALL *GetJNIFunctionTable) (jvmtiEnv* env,
+    jniNativeInterface** function_table);
+
+  /*   122 : Set Event Callbacks */
+  jvmtiError (JNICALL *SetEventCallbacks) (jvmtiEnv* env,
+    const jvmtiEventCallbacks* callbacks,
+    jint size_of_callbacks);
+
+  /*   123 : Generate Events */
+  jvmtiError (JNICALL *GenerateEvents) (jvmtiEnv* env,
+    jvmtiEvent event_type);
+
+  /*   124 : Get Extension Functions */
+  jvmtiError (JNICALL *GetExtensionFunctions) (jvmtiEnv* env,
+    jint* extension_count_ptr,
+    jvmtiExtensionFunctionInfo** extensions);
+
+  /*   125 : Get Extension Events */
+  jvmtiError (JNICALL *GetExtensionEvents) (jvmtiEnv* env,
+    jint* extension_count_ptr,
+    jvmtiExtensionEventInfo** extensions);
+
+  /*   126 : Set Extension Event Callback */
+  jvmtiError (JNICALL *SetExtensionEventCallback) (jvmtiEnv* env,
+    jint extension_event_index,
+    jvmtiExtensionEvent callback);
+
+  /*   127 : Dispose Environment */
+  jvmtiError (JNICALL *DisposeEnvironment) (jvmtiEnv* env);
+
+  /*   128 : Get Error Name */
+  jvmtiError (JNICALL *GetErrorName) (jvmtiEnv* env,
+    jvmtiError error,
+    char** name_ptr);
+
+  /*   129 : Get JLocation Format */
+  jvmtiError (JNICALL *GetJLocationFormat) (jvmtiEnv* env,
+    jvmtiJlocationFormat* format_ptr);
+
+  /*   130 : Get System Properties */
+  jvmtiError (JNICALL *GetSystemProperties) (jvmtiEnv* env,
+    jint* count_ptr,
+    char*** property_ptr);
+
+  /*   131 : Get System Property */
+  jvmtiError (JNICALL *GetSystemProperty) (jvmtiEnv* env,
+    const char* property,
+    char** value_ptr);
+
+  /*   132 : Set System Property */
+  jvmtiError (JNICALL *SetSystemProperty) (jvmtiEnv* env,
+    const char* property,
+    const char* value);
+
+  /*   133 : Get Phase */
+  jvmtiError (JNICALL *GetPhase) (jvmtiEnv* env,
+    jvmtiPhase* phase_ptr);
+
+  /*   134 : Get Current Thread CPU Timer Information */
+  jvmtiError (JNICALL *GetCurrentThreadCpuTimerInfo) (jvmtiEnv* env,
+    jvmtiTimerInfo* info_ptr);
+
+  /*   135 : Get Current Thread CPU Time */
+  jvmtiError (JNICALL *GetCurrentThreadCpuTime) (jvmtiEnv* env,
+    jlong* nanos_ptr);
+
+  /*   136 : Get Thread CPU Timer Information */
+  jvmtiError (JNICALL *GetThreadCpuTimerInfo) (jvmtiEnv* env,
+    jvmtiTimerInfo* info_ptr);
+
+  /*   137 : Get Thread CPU Time */
+  jvmtiError (JNICALL *GetThreadCpuTime) (jvmtiEnv* env,
+    jthread thread,
+    jlong* nanos_ptr);
+
+  /*   138 : Get Timer Information */
+  jvmtiError (JNICALL *GetTimerInfo) (jvmtiEnv* env,
+    jvmtiTimerInfo* info_ptr);
+
+  /*   139 : Get Time */
+  jvmtiError (JNICALL *GetTime) (jvmtiEnv* env,
+    jlong* nanos_ptr);
+
+  /*   140 : Get Potential Capabilities */
+  jvmtiError (JNICALL *GetPotentialCapabilities) (jvmtiEnv* env,
+    jvmtiCapabilities* capabilities_ptr);
+
+  /*   141 :  RESERVED */
+  void *reserved141;
+
+  /*   142 : Add Capabilities */
+  jvmtiError (JNICALL *AddCapabilities) (jvmtiEnv* env,
+    const jvmtiCapabilities* capabilities_ptr);
+
+  /*   143 : Relinquish Capabilities */
+  jvmtiError (JNICALL *RelinquishCapabilities) (jvmtiEnv* env,
+    const jvmtiCapabilities* capabilities_ptr);
+
+  /*   144 : Get Available Processors */
+  jvmtiError (JNICALL *GetAvailableProcessors) (jvmtiEnv* env,
+    jint* processor_count_ptr);
+
+  /*   145 : Get Class Version Numbers */
+  jvmtiError (JNICALL *GetClassVersionNumbers) (jvmtiEnv* env,
+    jclass klass,
+    jint* minor_version_ptr,
+    jint* major_version_ptr);
+
+  /*   146 : Get Constant Pool */
+  jvmtiError (JNICALL *GetConstantPool) (jvmtiEnv* env,
+    jclass klass,
+    jint* constant_pool_count_ptr,
+    jint* constant_pool_byte_count_ptr,
+    unsigned char** constant_pool_bytes_ptr);
+
+  /*   147 : Get Environment Local Storage */
+  jvmtiError (JNICALL *GetEnvironmentLocalStorage) (jvmtiEnv* env,
+    void** data_ptr);
+
+  /*   148 : Set Environment Local Storage */
+  jvmtiError (JNICALL *SetEnvironmentLocalStorage) (jvmtiEnv* env,
+    const void* data);
+
+  /*   149 : Add To Bootstrap Class Loader Search */
+  jvmtiError (JNICALL *AddToBootstrapClassLoaderSearch) (jvmtiEnv* env,
+    const char* segment);
+
+  /*   150 : Set Verbose Flag */
+  jvmtiError (JNICALL *SetVerboseFlag) (jvmtiEnv* env,
+    jvmtiVerboseFlag flag,
+    jboolean value);
+
+  /*   151 : Add To System Class Loader Search */
+  jvmtiError (JNICALL *AddToSystemClassLoaderSearch) (jvmtiEnv* env,
+    const char* segment);
+
+  /*   152 : Retransform Classes */
+  jvmtiError (JNICALL *RetransformClasses) (jvmtiEnv* env,
+    jint class_count,
+    const jclass* classes);
+
+  /*   153 : Get Owned Monitor Stack Depth Info */
+  jvmtiError (JNICALL *GetOwnedMonitorStackDepthInfo) (jvmtiEnv* env,
+    jthread thread,
+    jint* monitor_info_count_ptr,
+    jvmtiMonitorStackDepthInfo** monitor_info_ptr);
+
+  /*   154 : Get Object Size */
+  jvmtiError (JNICALL *GetObjectSize) (jvmtiEnv* env,
+    jobject object,
+    jlong* size_ptr);
+
+  /*   155 : Get Local Instance */
+  jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env,
+    jthread thread,
+    jint depth,
+    jobject* value_ptr);
+
+} jvmtiInterface_1;
+
+struct _jvmtiEnv {
+    const struct jvmtiInterface_1_ *functions;
+#ifdef __cplusplus
+
+
+  jvmtiError Allocate(jlong size,
+            unsigned char** mem_ptr) {
+    return functions->Allocate(this, size, mem_ptr);
+  }
+
+  jvmtiError Deallocate(unsigned char* mem) {
+    return functions->Deallocate(this, mem);
+  }
+
+  jvmtiError GetThreadState(jthread thread,
+            jint* thread_state_ptr) {
+    return functions->GetThreadState(this, thread, thread_state_ptr);
+  }
+
+  jvmtiError GetCurrentThread(jthread* thread_ptr) {
+    return functions->GetCurrentThread(this, thread_ptr);
+  }
+
+  jvmtiError GetAllThreads(jint* threads_count_ptr,
+            jthread** threads_ptr) {
+    return functions->GetAllThreads(this, threads_count_ptr, threads_ptr);
+  }
+
+  jvmtiError SuspendThread(jthread thread) {
+    return functions->SuspendThread(this, thread);
+  }
+
+  jvmtiError SuspendThreadList(jint request_count,
+            const jthread* request_list,
+            jvmtiError* results) {
+    return functions->SuspendThreadList(this, request_count, request_list, results);
+  }
+
+  jvmtiError ResumeThread(jthread thread) {
+    return functions->ResumeThread(this, thread);
+  }
+
+  jvmtiError ResumeThreadList(jint request_count,
+            const jthread* request_list,
+            jvmtiError* results) {
+    return functions->ResumeThreadList(this, request_count, request_list, results);
+  }
+
+  jvmtiError StopThread(jthread thread,
+            jobject exception) {
+    return functions->StopThread(this, thread, exception);
+  }
+
+  jvmtiError InterruptThread(jthread thread) {
+    return functions->InterruptThread(this, thread);
+  }
+
+  jvmtiError GetThreadInfo(jthread thread,
+            jvmtiThreadInfo* info_ptr) {
+    return functions->GetThreadInfo(this, thread, info_ptr);
+  }
+
+  jvmtiError GetOwnedMonitorInfo(jthread thread,
+            jint* owned_monitor_count_ptr,
+            jobject** owned_monitors_ptr) {
+    return functions->GetOwnedMonitorInfo(this, thread, owned_monitor_count_ptr, owned_monitors_ptr);
+  }
+
+  jvmtiError GetOwnedMonitorStackDepthInfo(jthread thread,
+            jint* monitor_info_count_ptr,
+            jvmtiMonitorStackDepthInfo** monitor_info_ptr) {
+    return functions->GetOwnedMonitorStackDepthInfo(this, thread, monitor_info_count_ptr, monitor_info_ptr);
+  }
+
+  jvmtiError GetCurrentContendedMonitor(jthread thread,
+            jobject* monitor_ptr) {
+    return functions->GetCurrentContendedMonitor(this, thread, monitor_ptr);
+  }
+
+  jvmtiError RunAgentThread(jthread thread,
+            jvmtiStartFunction proc,
+            const void* arg,
+            jint priority) {
+    return functions->RunAgentThread(this, thread, proc, arg, priority);
+  }
+
+  jvmtiError SetThreadLocalStorage(jthread thread,
+            const void* data) {
+    return functions->SetThreadLocalStorage(this, thread, data);
+  }
+
+  jvmtiError GetThreadLocalStorage(jthread thread,
+            void** data_ptr) {
+    return functions->GetThreadLocalStorage(this, thread, data_ptr);
+  }
+
+  jvmtiError GetTopThreadGroups(jint* group_count_ptr,
+            jthreadGroup** groups_ptr) {
+    return functions->GetTopThreadGroups(this, group_count_ptr, groups_ptr);
+  }
+
+  jvmtiError GetThreadGroupInfo(jthreadGroup group,
+            jvmtiThreadGroupInfo* info_ptr) {
+    return functions->GetThreadGroupInfo(this, group, info_ptr);
+  }
+
+  jvmtiError GetThreadGroupChildren(jthreadGroup group,
+            jint* thread_count_ptr,
+            jthread** threads_ptr,
+            jint* group_count_ptr,
+            jthreadGroup** groups_ptr) {
+    return functions->GetThreadGroupChildren(this, group, thread_count_ptr, threads_ptr, group_count_ptr, groups_ptr);
+  }
+
+  jvmtiError GetStackTrace(jthread thread,
+            jint start_depth,
+            jint max_frame_count,
+            jvmtiFrameInfo* frame_buffer,
+            jint* count_ptr) {
+    return functions->GetStackTrace(this, thread, start_depth, max_frame_count, frame_buffer, count_ptr);
+  }
+
+  jvmtiError GetAllStackTraces(jint max_frame_count,
+            jvmtiStackInfo** stack_info_ptr,
+            jint* thread_count_ptr) {
+    return functions->GetAllStackTraces(this, max_frame_count, stack_info_ptr, thread_count_ptr);
+  }
+
+  jvmtiError GetThreadListStackTraces(jint thread_count,
+            const jthread* thread_list,
+            jint max_frame_count,
+            jvmtiStackInfo** stack_info_ptr) {
+    return functions->GetThreadListStackTraces(this, thread_count, thread_list, max_frame_count, stack_info_ptr);
+  }
+
+  jvmtiError GetFrameCount(jthread thread,
+            jint* count_ptr) {
+    return functions->GetFrameCount(this, thread, count_ptr);
+  }
+
+  jvmtiError PopFrame(jthread thread) {
+    return functions->PopFrame(this, thread);
+  }
+
+  jvmtiError GetFrameLocation(jthread thread,
+            jint depth,
+            jmethodID* method_ptr,
+            jlocation* location_ptr) {
+    return functions->GetFrameLocation(this, thread, depth, method_ptr, location_ptr);
+  }
+
+  jvmtiError NotifyFramePop(jthread thread,
+            jint depth) {
+    return functions->NotifyFramePop(this, thread, depth);
+  }
+
+  jvmtiError ForceEarlyReturnObject(jthread thread,
+            jobject value) {
+    return functions->ForceEarlyReturnObject(this, thread, value);
+  }
+
+  jvmtiError ForceEarlyReturnInt(jthread thread,
+            jint value) {
+    return functions->ForceEarlyReturnInt(this, thread, value);
+  }
+
+  jvmtiError ForceEarlyReturnLong(jthread thread,
+            jlong value) {
+    return functions->ForceEarlyReturnLong(this, thread, value);
+  }
+
+  jvmtiError ForceEarlyReturnFloat(jthread thread,
+            jfloat value) {
+    return functions->ForceEarlyReturnFloat(this, thread, value);
+  }
+
+  jvmtiError ForceEarlyReturnDouble(jthread thread,
+            jdouble value) {
+    return functions->ForceEarlyReturnDouble(this, thread, value);
+  }
+
+  jvmtiError ForceEarlyReturnVoid(jthread thread) {
+    return functions->ForceEarlyReturnVoid(this, thread);
+  }
+
+  jvmtiError FollowReferences(jint heap_filter,
+            jclass klass,
+            jobject initial_object,
+            const jvmtiHeapCallbacks* callbacks,
+            const void* user_data) {
+    return functions->FollowReferences(this, heap_filter, klass, initial_object, callbacks, user_data);
+  }
+
+  jvmtiError IterateThroughHeap(jint heap_filter,
+            jclass klass,
+            const jvmtiHeapCallbacks* callbacks,
+            const void* user_data) {
+    return functions->IterateThroughHeap(this, heap_filter, klass, callbacks, user_data);
+  }
+
+  jvmtiError GetTag(jobject object,
+            jlong* tag_ptr) {
+    return functions->GetTag(this, object, tag_ptr);
+  }
+
+  jvmtiError SetTag(jobject object,
+            jlong tag) {
+    return functions->SetTag(this, object, tag);
+  }
+
+  jvmtiError GetObjectsWithTags(jint tag_count,
+            const jlong* tags,
+            jint* count_ptr,
+            jobject** object_result_ptr,
+            jlong** tag_result_ptr) {
+    return functions->GetObjectsWithTags(this, tag_count, tags, count_ptr, object_result_ptr, tag_result_ptr);
+  }
+
+  jvmtiError ForceGarbageCollection() {
+    return functions->ForceGarbageCollection(this);
+  }
+
+  jvmtiError IterateOverObjectsReachableFromObject(jobject object,
+            jvmtiObjectReferenceCallback object_reference_callback,
+            const void* user_data) {
+    return functions->IterateOverObjectsReachableFromObject(this, object, object_reference_callback, user_data);
+  }
+
+  jvmtiError IterateOverReachableObjects(jvmtiHeapRootCallback heap_root_callback,
+            jvmtiStackReferenceCallback stack_ref_callback,
+            jvmtiObjectReferenceCallback object_ref_callback,
+            const void* user_data) {
+    return functions->IterateOverReachableObjects(this, heap_root_callback, stack_ref_callback, object_ref_callback, user_data);
+  }
+
+  jvmtiError IterateOverHeap(jvmtiHeapObjectFilter object_filter,
+            jvmtiHeapObjectCallback heap_object_callback,
+            const void* user_data) {
+    return functions->IterateOverHeap(this, object_filter, heap_object_callback, user_data);
+  }
+
+  jvmtiError IterateOverInstancesOfClass(jclass klass,
+            jvmtiHeapObjectFilter object_filter,
+            jvmtiHeapObjectCallback heap_object_callback,
+            const void* user_data) {
+    return functions->IterateOverInstancesOfClass(this, klass, object_filter, heap_object_callback, user_data);
+  }
+
+  jvmtiError GetLocalObject(jthread thread,
+            jint depth,
+            jint slot,
+            jobject* value_ptr) {
+    return functions->GetLocalObject(this, thread, depth, slot, value_ptr);
+  }
+
+  jvmtiError GetLocalInstance(jthread thread,
+            jint depth,
+            jobject* value_ptr) {
+    return functions->GetLocalInstance(this, thread, depth, value_ptr);
+  }
+
+  jvmtiError GetLocalInt(jthread thread,
+            jint depth,
+            jint slot,
+            jint* value_ptr) {
+    return functions->GetLocalInt(this, thread, depth, slot, value_ptr);
+  }
+
+  jvmtiError GetLocalLong(jthread thread,
+            jint depth,
+            jint slot,
+            jlong* value_ptr) {
+    return functions->GetLocalLong(this, thread, depth, slot, value_ptr);
+  }
+
+  jvmtiError GetLocalFloat(jthread thread,
+            jint depth,
+            jint slot,
+            jfloat* value_ptr) {
+    return functions->GetLocalFloat(this, thread, depth, slot, value_ptr);
+  }
+
+  jvmtiError GetLocalDouble(jthread thread,
+            jint depth,
+            jint slot,
+            jdouble* value_ptr) {
+    return functions->GetLocalDouble(this, thread, depth, slot, value_ptr);
+  }
+
+  jvmtiError SetLocalObject(jthread thread,
+            jint depth,
+            jint slot,
+            jobject value) {
+    return functions->SetLocalObject(this, thread, depth, slot, value);
+  }
+
+  jvmtiError SetLocalInt(jthread thread,
+            jint depth,
+            jint slot,
+            jint value) {
+    return functions->SetLocalInt(this, thread, depth, slot, value);
+  }
+
+  jvmtiError SetLocalLong(jthread thread,
+            jint depth,
+            jint slot,
+            jlong value) {
+    return functions->SetLocalLong(this, thread, depth, slot, value);
+  }
+
+  jvmtiError SetLocalFloat(jthread thread,
+            jint depth,
+            jint slot,
+            jfloat value) {
+    return functions->SetLocalFloat(this, thread, depth, slot, value);
+  }
+
+  jvmtiError SetLocalDouble(jthread thread,
+            jint depth,
+            jint slot,
+            jdouble value) {
+    return functions->SetLocalDouble(this, thread, depth, slot, value);
+  }
+
+  jvmtiError SetBreakpoint(jmethodID method,
+            jlocation location) {
+    return functions->SetBreakpoint(this, method, location);
+  }
+
+  jvmtiError ClearBreakpoint(jmethodID method,
+            jlocation location) {
+    return functions->ClearBreakpoint(this, method, location);
+  }
+
+  jvmtiError SetFieldAccessWatch(jclass klass,
+            jfieldID field) {
+    return functions->SetFieldAccessWatch(this, klass, field);
+  }
+
+  jvmtiError ClearFieldAccessWatch(jclass klass,
+            jfieldID field) {
+    return functions->ClearFieldAccessWatch(this, klass, field);
+  }
+
+  jvmtiError SetFieldModificationWatch(jclass klass,
+            jfieldID field) {
+    return functions->SetFieldModificationWatch(this, klass, field);
+  }
+
+  jvmtiError ClearFieldModificationWatch(jclass klass,
+            jfieldID field) {
+    return functions->ClearFieldModificationWatch(this, klass, field);
+  }
+
+  jvmtiError GetLoadedClasses(jint* class_count_ptr,
+            jclass** classes_ptr) {
+    return functions->GetLoadedClasses(this, class_count_ptr, classes_ptr);
+  }
+
+  jvmtiError GetClassLoaderClasses(jobject initiating_loader,
+            jint* class_count_ptr,
+            jclass** classes_ptr) {
+    return functions->GetClassLoaderClasses(this, initiating_loader, class_count_ptr, classes_ptr);
+  }
+
+  jvmtiError GetClassSignature(jclass klass,
+            char** signature_ptr,
+            char** generic_ptr) {
+    return functions->GetClassSignature(this, klass, signature_ptr, generic_ptr);
+  }
+
+  jvmtiError GetClassStatus(jclass klass,
+            jint* status_ptr) {
+    return functions->GetClassStatus(this, klass, status_ptr);
+  }
+
+  jvmtiError GetSourceFileName(jclass klass,
+            char** source_name_ptr) {
+    return functions->GetSourceFileName(this, klass, source_name_ptr);
+  }
+
+  jvmtiError GetClassModifiers(jclass klass,
+            jint* modifiers_ptr) {
+    return functions->GetClassModifiers(this, klass, modifiers_ptr);
+  }
+
+  jvmtiError GetClassMethods(jclass klass,
+            jint* method_count_ptr,
+            jmethodID** methods_ptr) {
+    return functions->GetClassMethods(this, klass, method_count_ptr, methods_ptr);
+  }
+
+  jvmtiError GetClassFields(jclass klass,
+            jint* field_count_ptr,
+            jfieldID** fields_ptr) {
+    return functions->GetClassFields(this, klass, field_count_ptr, fields_ptr);
+  }
+
+  jvmtiError GetImplementedInterfaces(jclass klass,
+            jint* interface_count_ptr,
+            jclass** interfaces_ptr) {
+    return functions->GetImplementedInterfaces(this, klass, interface_count_ptr, interfaces_ptr);
+  }
+
+  jvmtiError GetClassVersionNumbers(jclass klass,
+            jint* minor_version_ptr,
+            jint* major_version_ptr) {
+    return functions->GetClassVersionNumbers(this, klass, minor_version_ptr, major_version_ptr);
+  }
+
+  jvmtiError GetConstantPool(jclass klass,
+            jint* constant_pool_count_ptr,
+            jint* constant_pool_byte_count_ptr,
+            unsigned char** constant_pool_bytes_ptr) {
+    return functions->GetConstantPool(this, klass, constant_pool_count_ptr, constant_pool_byte_count_ptr, constant_pool_bytes_ptr);
+  }
+
+  jvmtiError IsInterface(jclass klass,
+            jboolean* is_interface_ptr) {
+    return functions->IsInterface(this, klass, is_interface_ptr);
+  }
+
+  jvmtiError IsArrayClass(jclass klass,
+            jboolean* is_array_class_ptr) {
+    return functions->IsArrayClass(this, klass, is_array_class_ptr);
+  }
+
+  jvmtiError IsModifiableClass(jclass klass,
+            jboolean* is_modifiable_class_ptr) {
+    return functions->IsModifiableClass(this, klass, is_modifiable_class_ptr);
+  }
+
+  jvmtiError GetClassLoader(jclass klass,
+            jobject* classloader_ptr) {
+    return functions->GetClassLoader(this, klass, classloader_ptr);
+  }
+
+  jvmtiError GetSourceDebugExtension(jclass klass,
+            char** source_debug_extension_ptr) {
+    return functions->GetSourceDebugExtension(this, klass, source_debug_extension_ptr);
+  }
+
+  jvmtiError RetransformClasses(jint class_count,
+            const jclass* classes) {
+    return functions->RetransformClasses(this, class_count, classes);
+  }
+
+  jvmtiError RedefineClasses(jint class_count,
+            const jvmtiClassDefinition* class_definitions) {
+    return functions->RedefineClasses(this, class_count, class_definitions);
+  }
+
+  jvmtiError GetObjectSize(jobject object,
+            jlong* size_ptr) {
+    return functions->GetObjectSize(this, object, size_ptr);
+  }
+
+  jvmtiError GetObjectHashCode(jobject object,
+            jint* hash_code_ptr) {
+    return functions->GetObjectHashCode(this, object, hash_code_ptr);
+  }
+
+  jvmtiError GetObjectMonitorUsage(jobject object,
+            jvmtiMonitorUsage* info_ptr) {
+    return functions->GetObjectMonitorUsage(this, object, info_ptr);
+  }
+
+  jvmtiError GetFieldName(jclass klass,
+            jfieldID field,
+            char** name_ptr,
+            char** signature_ptr,
+            char** generic_ptr) {
+    return functions->GetFieldName(this, klass, field, name_ptr, signature_ptr, generic_ptr);
+  }
+
+  jvmtiError GetFieldDeclaringClass(jclass klass,
+            jfieldID field,
+            jclass* declaring_class_ptr) {
+    return functions->GetFieldDeclaringClass(this, klass, field, declaring_class_ptr);
+  }
+
+  jvmtiError GetFieldModifiers(jclass klass,
+            jfieldID field,
+            jint* modifiers_ptr) {
+    return functions->GetFieldModifiers(this, klass, field, modifiers_ptr);
+  }
+
+  jvmtiError IsFieldSynthetic(jclass klass,
+            jfieldID field,
+            jboolean* is_synthetic_ptr) {
+    return functions->IsFieldSynthetic(this, klass, field, is_synthetic_ptr);
+  }
+
+  jvmtiError GetMethodName(jmethodID method,
+            char** name_ptr,
+            char** signature_ptr,
+            char** generic_ptr) {
+    return functions->GetMethodName(this, method, name_ptr, signature_ptr, generic_ptr);
+  }
+
+  jvmtiError GetMethodDeclaringClass(jmethodID method,
+            jclass* declaring_class_ptr) {
+    return functions->GetMethodDeclaringClass(this, method, declaring_class_ptr);
+  }
+
+  jvmtiError GetMethodModifiers(jmethodID method,
+            jint* modifiers_ptr) {
+    return functions->GetMethodModifiers(this, method, modifiers_ptr);
+  }
+
+  jvmtiError GetMaxLocals(jmethodID method,
+            jint* max_ptr) {
+    return functions->GetMaxLocals(this, method, max_ptr);
+  }
+
+  jvmtiError GetArgumentsSize(jmethodID method,
+            jint* size_ptr) {
+    return functions->GetArgumentsSize(this, method, size_ptr);
+  }
+
+  jvmtiError GetLineNumberTable(jmethodID method,
+            jint* entry_count_ptr,
+            jvmtiLineNumberEntry** table_ptr) {
+    return functions->GetLineNumberTable(this, method, entry_count_ptr, table_ptr);
+  }
+
+  jvmtiError GetMethodLocation(jmethodID method,
+            jlocation* start_location_ptr,
+            jlocation* end_location_ptr) {
+    return functions->GetMethodLocation(this, method, start_location_ptr, end_location_ptr);
+  }
+
+  jvmtiError GetLocalVariableTable(jmethodID method,
+            jint* entry_count_ptr,
+            jvmtiLocalVariableEntry** table_ptr) {
+    return functions->GetLocalVariableTable(this, method, entry_count_ptr, table_ptr);
+  }
+
+  jvmtiError GetBytecodes(jmethodID method,
+            jint* bytecode_count_ptr,
+            unsigned char** bytecodes_ptr) {
+    return functions->GetBytecodes(this, method, bytecode_count_ptr, bytecodes_ptr);
+  }
+
+  jvmtiError IsMethodNative(jmethodID method,
+            jboolean* is_native_ptr) {
+    return functions->IsMethodNative(this, method, is_native_ptr);
+  }
+
+  jvmtiError IsMethodSynthetic(jmethodID method,
+            jboolean* is_synthetic_ptr) {
+    return functions->IsMethodSynthetic(this, method, is_synthetic_ptr);
+  }
+
+  jvmtiError IsMethodObsolete(jmethodID method,
+            jboolean* is_obsolete_ptr) {
+    return functions->IsMethodObsolete(this, method, is_obsolete_ptr);
+  }
+
+  jvmtiError SetNativeMethodPrefix(const char* prefix) {
+    return functions->SetNativeMethodPrefix(this, prefix);
+  }
+
+  jvmtiError SetNativeMethodPrefixes(jint prefix_count,
+            char** prefixes) {
+    return functions->SetNativeMethodPrefixes(this, prefix_count, prefixes);
+  }
+
+  jvmtiError CreateRawMonitor(const char* name,
+            jrawMonitorID* monitor_ptr) {
+    return functions->CreateRawMonitor(this, name, monitor_ptr);
+  }
+
+  jvmtiError DestroyRawMonitor(jrawMonitorID monitor) {
+    return functions->DestroyRawMonitor(this, monitor);
+  }
+
+  jvmtiError RawMonitorEnter(jrawMonitorID monitor) {
+    return functions->RawMonitorEnter(this, monitor);
+  }
+
+  jvmtiError RawMonitorExit(jrawMonitorID monitor) {
+    return functions->RawMonitorExit(this, monitor);
+  }
+
+  jvmtiError RawMonitorWait(jrawMonitorID monitor,
+            jlong millis) {
+    return functions->RawMonitorWait(this, monitor, millis);
+  }
+
+  jvmtiError RawMonitorNotify(jrawMonitorID monitor) {
+    return functions->RawMonitorNotify(this, monitor);
+  }
+
+  jvmtiError RawMonitorNotifyAll(jrawMonitorID monitor) {
+    return functions->RawMonitorNotifyAll(this, monitor);
+  }
+
+  jvmtiError SetJNIFunctionTable(const jniNativeInterface* function_table) {
+    return functions->SetJNIFunctionTable(this, function_table);
+  }
+
+  jvmtiError GetJNIFunctionTable(jniNativeInterface** function_table) {
+    return functions->GetJNIFunctionTable(this, function_table);
+  }
+
+  jvmtiError SetEventCallbacks(const jvmtiEventCallbacks* callbacks,
+            jint size_of_callbacks) {
+    return functions->SetEventCallbacks(this, callbacks, size_of_callbacks);
+  }
+
+  jvmtiError SetEventNotificationMode(jvmtiEventMode mode,
+            jvmtiEvent event_type,
+            jthread event_thread,
+             ...) {
+    return functions->SetEventNotificationMode(this, mode, event_type, event_thread);
+  }
+
+  jvmtiError GenerateEvents(jvmtiEvent event_type) {
+    return functions->GenerateEvents(this, event_type);
+  }
+
+  jvmtiError GetExtensionFunctions(jint* extension_count_ptr,
+            jvmtiExtensionFunctionInfo** extensions) {
+    return functions->GetExtensionFunctions(this, extension_count_ptr, extensions);
+  }
+
+  jvmtiError GetExtensionEvents(jint* extension_count_ptr,
+            jvmtiExtensionEventInfo** extensions) {
+    return functions->GetExtensionEvents(this, extension_count_ptr, extensions);
+  }
+
+  jvmtiError SetExtensionEventCallback(jint extension_event_index,
+            jvmtiExtensionEvent callback) {
+    return functions->SetExtensionEventCallback(this, extension_event_index, callback);
+  }
+
+  jvmtiError GetPotentialCapabilities(jvmtiCapabilities* capabilities_ptr) {
+    return functions->GetPotentialCapabilities(this, capabilities_ptr);
+  }
+
+  jvmtiError AddCapabilities(const jvmtiCapabilities* capabilities_ptr) {
+    return functions->AddCapabilities(this, capabilities_ptr);
+  }
+
+  jvmtiError RelinquishCapabilities(const jvmtiCapabilities* capabilities_ptr) {
+    return functions->RelinquishCapabilities(this, capabilities_ptr);
+  }
+
+  jvmtiError GetCapabilities(jvmtiCapabilities* capabilities_ptr) {
+    return functions->GetCapabilities(this, capabilities_ptr);
+  }
+
+  jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
+    return functions->GetCurrentThreadCpuTimerInfo(this, info_ptr);
+  }
+
+  jvmtiError GetCurrentThreadCpuTime(jlong* nanos_ptr) {
+    return functions->GetCurrentThreadCpuTime(this, nanos_ptr);
+  }
+
+  jvmtiError GetThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
+    return functions->GetThreadCpuTimerInfo(this, info_ptr);
+  }
+
+  jvmtiError GetThreadCpuTime(jthread thread,
+            jlong* nanos_ptr) {
+    return functions->GetThreadCpuTime(this, thread, nanos_ptr);
+  }
+
+  jvmtiError GetTimerInfo(jvmtiTimerInfo* info_ptr) {
+    return functions->GetTimerInfo(this, info_ptr);
+  }
+
+  jvmtiError GetTime(jlong* nanos_ptr) {
+    return functions->GetTime(this, nanos_ptr);
+  }
+
+  jvmtiError GetAvailableProcessors(jint* processor_count_ptr) {
+    return functions->GetAvailableProcessors(this, processor_count_ptr);
+  }
+
+  jvmtiError AddToBootstrapClassLoaderSearch(const char* segment) {
+    return functions->AddToBootstrapClassLoaderSearch(this, segment);
+  }
+
+  jvmtiError AddToSystemClassLoaderSearch(const char* segment) {
+    return functions->AddToSystemClassLoaderSearch(this, segment);
+  }
+
+  jvmtiError GetSystemProperties(jint* count_ptr,
+            char*** property_ptr) {
+    return functions->GetSystemProperties(this, count_ptr, property_ptr);
+  }
+
+  jvmtiError GetSystemProperty(const char* property,
+            char** value_ptr) {
+    return functions->GetSystemProperty(this, property, value_ptr);
+  }
+
+  jvmtiError SetSystemProperty(const char* property,
+            const char* value) {
+    return functions->SetSystemProperty(this, property, value);
+  }
+
+  jvmtiError GetPhase(jvmtiPhase* phase_ptr) {
+    return functions->GetPhase(this, phase_ptr);
+  }
+
+  jvmtiError DisposeEnvironment() {
+    return functions->DisposeEnvironment(this);
+  }
+
+  jvmtiError SetEnvironmentLocalStorage(const void* data) {
+    return functions->SetEnvironmentLocalStorage(this, data);
+  }
+
+  jvmtiError GetEnvironmentLocalStorage(void** data_ptr) {
+    return functions->GetEnvironmentLocalStorage(this, data_ptr);
+  }
+
+  jvmtiError GetVersionNumber(jint* version_ptr) {
+    return functions->GetVersionNumber(this, version_ptr);
+  }
+
+  jvmtiError GetErrorName(jvmtiError error,
+            char** name_ptr) {
+    return functions->GetErrorName(this, error, name_ptr);
+  }
+
+  jvmtiError SetVerboseFlag(jvmtiVerboseFlag flag,
+            jboolean value) {
+    return functions->SetVerboseFlag(this, flag, value);
+  }
+
+  jvmtiError GetJLocationFormat(jvmtiJlocationFormat* format_ptr) {
+    return functions->GetJLocationFormat(this, format_ptr);
+  }
+
+#endif /* __cplusplus */
+};
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVA_JVMTI_H_ */
+
diff --git a/openjdkjvmti/jvmti_allocator.h b/openjdkjvmti/jvmti_allocator.h
new file mode 100644
index 0000000..e29e034
--- /dev/null
+++ b/openjdkjvmti/jvmti_allocator.h
@@ -0,0 +1,174 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_JVMTI_ALLOCATOR_H_
+#define ART_OPENJDKJVMTI_JVMTI_ALLOCATOR_H_
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "jvmti.h"
+
+#include "ti_allocator.h"
+
+namespace openjdkjvmti {
+
+template <typename T> class JvmtiAllocator;
+
+template <>
+class JvmtiAllocator<void> {
+ public:
+  typedef void value_type;
+  typedef void* pointer;
+  typedef const void* const_pointer;
+
+  template <typename U>
+  struct rebind {
+    typedef JvmtiAllocator<U> other;
+  };
+
+  explicit JvmtiAllocator(jvmtiEnv* env) : env_(env) {}
+  explicit JvmtiAllocator() : env_(nullptr) {}
+
+  template <typename U>
+  JvmtiAllocator(const JvmtiAllocator<U>& other)  // NOLINT, implicit
+      : env_(other.env_) {}
+
+  JvmtiAllocator(const JvmtiAllocator& other) = default;
+  JvmtiAllocator& operator=(const JvmtiAllocator& other) = default;
+  ~JvmtiAllocator() = default;
+
+ private:
+  jvmtiEnv* env_;
+
+  template <typename U>
+  friend class JvmtiAllocator;
+
+  template <typename U>
+  friend bool operator==(const JvmtiAllocator<U>& lhs, const JvmtiAllocator<U>& rhs);
+};
+
+template <typename T>
+class JvmtiAllocator {
+ public:
+  typedef T value_type;
+  typedef T* pointer;
+  typedef T& reference;
+  typedef const T* const_pointer;
+  typedef const T& const_reference;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+
+  template <typename U>
+  struct rebind {
+    typedef JvmtiAllocator<U> other;
+  };
+
+  explicit JvmtiAllocator(jvmtiEnv* env) : env_(env) {}
+  explicit JvmtiAllocator() : env_(nullptr) {}
+
+  template <typename U>
+  JvmtiAllocator(const JvmtiAllocator<U>& other)  // NOLINT, implicit
+      : env_(other.env_) {}
+
+  JvmtiAllocator(const JvmtiAllocator& other) = default;
+  JvmtiAllocator& operator=(const JvmtiAllocator& other) = default;
+  ~JvmtiAllocator() = default;
+
+  size_type max_size() const {
+    return static_cast<size_type>(-1) / sizeof(T);
+  }
+
+  pointer address(reference x) const { return &x; }
+  const_pointer address(const_reference x) const { return &x; }
+
+  pointer allocate(size_type n, JvmtiAllocator<void>::pointer hint ATTRIBUTE_UNUSED = nullptr) {
+    DCHECK_LE(n, max_size());
+    if (env_ == nullptr) {
+      T* result = reinterpret_cast<T*>(AllocUtil::AllocateImpl(n * sizeof(T)));
+      CHECK(result != nullptr || n == 0u);  // Abort if AllocateImpl() fails.
+      return result;
+    } else {
+      unsigned char* result;
+      jvmtiError alloc_error = env_->Allocate(n * sizeof(T), &result);
+      CHECK(alloc_error == JVMTI_ERROR_NONE);
+      return reinterpret_cast<T*>(result);
+    }
+  }
+  void deallocate(pointer p, size_type n ATTRIBUTE_UNUSED) {
+    if (env_ == nullptr) {
+      AllocUtil::DeallocateImpl(reinterpret_cast<unsigned char*>(p));
+    } else {
+      jvmtiError dealloc_error = env_->Deallocate(reinterpret_cast<unsigned char*>(p));
+      CHECK(dealloc_error == JVMTI_ERROR_NONE);
+    }
+  }
+
+  void construct(pointer p, const_reference val) {
+    new (static_cast<void*>(p)) value_type(val);
+  }
+  template <class U, class... Args>
+  void construct(U* p, Args&&... args) {
+    ::new (static_cast<void*>(p)) U(std::forward<Args>(args)...);
+  }
+  void destroy(pointer p) {
+    p->~value_type();
+  }
+
+  inline bool operator==(JvmtiAllocator const& other) {
+    return env_ == other.env_;
+  }
+  inline bool operator!=(JvmtiAllocator const& other) {
+    return !operator==(other);
+  }
+
+ private:
+  jvmtiEnv* env_;
+
+  template <typename U>
+  friend class JvmtiAllocator;
+
+  template <typename U>
+  friend bool operator==(const JvmtiAllocator<U>& lhs, const JvmtiAllocator<U>& rhs);
+};
+
+template <typename T>
+inline bool operator==(const JvmtiAllocator<T>& lhs, const JvmtiAllocator<T>& rhs) {
+  return lhs.env_ == rhs.env_;
+}
+
+template <typename T>
+inline bool operator!=(const JvmtiAllocator<T>& lhs, const JvmtiAllocator<T>& rhs) {
+  return !(lhs == rhs);
+}
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_JVMTI_ALLOCATOR_H_
diff --git a/openjdkjvmti/jvmti_weak_table-inl.h b/openjdkjvmti/jvmti_weak_table-inl.h
new file mode 100644
index 0000000..1c82255
--- /dev/null
+++ b/openjdkjvmti/jvmti_weak_table-inl.h
@@ -0,0 +1,406 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_INL_H_
+#define ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_INL_H_
+
+#include "jvmti_weak_table.h"
+
+#include <limits>
+
+#include "art_jvmti.h"
+#include "base/logging.h"
+#include "gc/allocation_listener.h"
+#include "instrumentation.h"
+#include "jni_env_ext-inl.h"
+#include "jvmti_allocator.h"
+#include "mirror/class.h"
+#include "mirror/object.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "runtime.h"
+
+namespace openjdkjvmti {
+
+template <typename T>
+void JvmtiWeakTable<T>::Lock() {
+  allow_disallow_lock_.ExclusiveLock(art::Thread::Current());
+}
+template <typename T>
+void JvmtiWeakTable<T>::Unlock() {
+  allow_disallow_lock_.ExclusiveUnlock(art::Thread::Current());
+}
+template <typename T>
+void JvmtiWeakTable<T>::AssertLocked() {
+  allow_disallow_lock_.AssertHeld(art::Thread::Current());
+}
+
+template <typename T>
+void JvmtiWeakTable<T>::UpdateTableWithReadBarrier() {
+  update_since_last_sweep_ = true;
+
+  auto WithReadBarrierUpdater = [&](const art::GcRoot<art::mirror::Object>& original_root,
+                                    art::mirror::Object* original_obj ATTRIBUTE_UNUSED)
+     REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return original_root.Read<art::kWithReadBarrier>();
+  };
+
+  UpdateTableWith<decltype(WithReadBarrierUpdater), kIgnoreNull>(WithReadBarrierUpdater);
+}
+
+template <typename T>
+bool JvmtiWeakTable<T>::GetTagSlowPath(art::Thread* self, art::mirror::Object* obj, T* result) {
+  // Under concurrent GC, there is a window between moving objects and sweeping of system
+  // weaks in which mutators are active. We may receive a to-space object pointer in obj,
+  // but still have from-space pointers in the table. Explicitly update the table once.
+  // Note: this will keep *all* objects in the table live, but should be a rare occurrence.
+  UpdateTableWithReadBarrier();
+  return GetTagLocked(self, obj, result);
+}
+
+template <typename T>
+bool JvmtiWeakTable<T>::Remove(art::mirror::Object* obj, /* out */ T* tag) {
+  art::Thread* self = art::Thread::Current();
+  art::MutexLock mu(self, allow_disallow_lock_);
+  Wait(self);
+
+  return RemoveLocked(self, obj, tag);
+}
+template <typename T>
+bool JvmtiWeakTable<T>::RemoveLocked(art::mirror::Object* obj, T* tag) {
+  art::Thread* self = art::Thread::Current();
+  allow_disallow_lock_.AssertHeld(self);
+  Wait(self);
+
+  return RemoveLocked(self, obj, tag);
+}
+
+template <typename T>
+bool JvmtiWeakTable<T>::RemoveLocked(art::Thread* self, art::mirror::Object* obj, T* tag) {
+  auto it = tagged_objects_.find(art::GcRoot<art::mirror::Object>(obj));
+  if (it != tagged_objects_.end()) {
+    if (tag != nullptr) {
+      *tag = it->second;
+    }
+    tagged_objects_.erase(it);
+    return true;
+  }
+
+  if (art::kUseReadBarrier && self->GetIsGcMarking() && !update_since_last_sweep_) {
+    // Under concurrent GC, there is a window between moving objects and sweeping of system
+    // weaks in which mutators are active. We may receive a to-space object pointer in obj,
+    // but still have from-space pointers in the table. Explicitly update the table once.
+    // Note: this will keep *all* objects in the table live, but should be a rare occurrence.
+
+    // Update the table.
+    UpdateTableWithReadBarrier();
+
+    // And try again.
+    return RemoveLocked(self, obj, tag);
+  }
+
+  // Not in here.
+  return false;
+}
+
+template <typename T>
+bool JvmtiWeakTable<T>::Set(art::mirror::Object* obj, T new_tag) {
+  art::Thread* self = art::Thread::Current();
+  art::MutexLock mu(self, allow_disallow_lock_);
+  Wait(self);
+
+  return SetLocked(self, obj, new_tag);
+}
+template <typename T>
+bool JvmtiWeakTable<T>::SetLocked(art::mirror::Object* obj, T new_tag) {
+  art::Thread* self = art::Thread::Current();
+  allow_disallow_lock_.AssertHeld(self);
+  Wait(self);
+
+  return SetLocked(self, obj, new_tag);
+}
+
+template <typename T>
+bool JvmtiWeakTable<T>::SetLocked(art::Thread* self, art::mirror::Object* obj, T new_tag) {
+  auto it = tagged_objects_.find(art::GcRoot<art::mirror::Object>(obj));
+  if (it != tagged_objects_.end()) {
+    it->second = new_tag;
+    return true;
+  }
+
+  if (art::kUseReadBarrier && self->GetIsGcMarking() && !update_since_last_sweep_) {
+    // Under concurrent GC, there is a window between moving objects and sweeping of system
+    // weaks in which mutators are active. We may receive a to-space object pointer in obj,
+    // but still have from-space pointers in the table. Explicitly update the table once.
+    // Note: this will keep *all* objects in the table live, but should be a rare occurrence.
+
+    // Update the table.
+    UpdateTableWithReadBarrier();
+
+    // And try again.
+    return SetLocked(self, obj, new_tag);
+  }
+
+  // New element.
+  auto insert_it = tagged_objects_.emplace(art::GcRoot<art::mirror::Object>(obj), new_tag);
+  DCHECK(insert_it.second);
+  return false;
+}
+
+template <typename T>
+void JvmtiWeakTable<T>::Sweep(art::IsMarkedVisitor* visitor) {
+  if (DoesHandleNullOnSweep()) {
+    SweepImpl<true>(visitor);
+  } else {
+    SweepImpl<false>(visitor);
+  }
+
+  // Under concurrent GC, there is a window between moving objects and sweeping of system
+  // weaks in which mutators are active. We may receive a to-space object pointer in obj,
+  // but still have from-space pointers in the table. We explicitly update the table then
+  // to ensure we compare against to-space pointers. But we want to do this only once. Once
+  // sweeping is done, we know all objects are to-space pointers until the next GC cycle,
+  // so we re-enable the explicit update for the next marking.
+  update_since_last_sweep_ = false;
+}
+
+template <typename T>
+template <bool kHandleNull>
+void JvmtiWeakTable<T>::SweepImpl(art::IsMarkedVisitor* visitor) {
+  art::Thread* self = art::Thread::Current();
+  art::MutexLock mu(self, allow_disallow_lock_);
+
+  auto IsMarkedUpdater = [&](const art::GcRoot<art::mirror::Object>& original_root ATTRIBUTE_UNUSED,
+                             art::mirror::Object* original_obj) {
+    return visitor->IsMarked(original_obj);
+  };
+
+  UpdateTableWith<decltype(IsMarkedUpdater),
+                  kHandleNull ? kCallHandleNull : kRemoveNull>(IsMarkedUpdater);
+}
+
+template <typename T>
+template <typename Updater, typename JvmtiWeakTable<T>::TableUpdateNullTarget kTargetNull>
+ALWAYS_INLINE inline void JvmtiWeakTable<T>::UpdateTableWith(Updater& updater) {
+  // We optimistically hope that elements will still be well-distributed when re-inserting them.
+  // So play with the map mechanics, and postpone rehashing. This avoids the need of a side
+  // vector and two passes.
+  float original_max_load_factor = tagged_objects_.max_load_factor();
+  tagged_objects_.max_load_factor(std::numeric_limits<float>::max());
+  // For checking that a max load-factor actually does what we expect.
+  size_t original_bucket_count = tagged_objects_.bucket_count();
+
+  for (auto it = tagged_objects_.begin(); it != tagged_objects_.end();) {
+    DCHECK(!it->first.IsNull());
+    art::mirror::Object* original_obj = it->first.template Read<art::kWithoutReadBarrier>();
+    art::mirror::Object* target_obj = updater(it->first, original_obj);
+    if (original_obj != target_obj) {
+      if (kTargetNull == kIgnoreNull && target_obj == nullptr) {
+        // Ignore null target, don't do anything.
+      } else {
+        T tag = it->second;
+        it = tagged_objects_.erase(it);
+        if (target_obj != nullptr) {
+          tagged_objects_.emplace(art::GcRoot<art::mirror::Object>(target_obj), tag);
+          DCHECK_EQ(original_bucket_count, tagged_objects_.bucket_count());
+        } else if (kTargetNull == kCallHandleNull) {
+          HandleNullSweep(tag);
+        }
+        continue;  // Iterator was implicitly updated by erase.
+      }
+    }
+    it++;
+  }
+
+  tagged_objects_.max_load_factor(original_max_load_factor);
+  // TODO: consider rehash here.
+}
+
+template <typename T>
+template <typename Storage, class Allocator>
+struct JvmtiWeakTable<T>::ReleasableContainer {
+  using allocator_type = Allocator;
+
+  explicit ReleasableContainer(const allocator_type& alloc, size_t reserve = 10)
+      : allocator(alloc),
+        data(reserve > 0 ? allocator.allocate(reserve) : nullptr),
+        size(0),
+        capacity(reserve) {
+  }
+
+  ~ReleasableContainer() {
+    if (data != nullptr) {
+      allocator.deallocate(data, capacity);
+      capacity = 0;
+      size = 0;
+    }
+  }
+
+  Storage* Release() {
+    Storage* tmp = data;
+
+    data = nullptr;
+    size = 0;
+    capacity = 0;
+
+    return tmp;
+  }
+
+  void Resize(size_t new_capacity) {
+    CHECK_GT(new_capacity, capacity);
+
+    Storage* tmp = allocator.allocate(new_capacity);
+    DCHECK(tmp != nullptr);
+    if (data != nullptr) {
+      memcpy(tmp, data, sizeof(Storage) * size);
+    }
+    Storage* old = data;
+    data = tmp;
+    allocator.deallocate(old, capacity);
+    capacity = new_capacity;
+  }
+
+  void Pushback(const Storage& elem) {
+    if (size == capacity) {
+      size_t new_capacity = 2 * capacity + 1;
+      Resize(new_capacity);
+    }
+    data[size++] = elem;
+  }
+
+  Allocator allocator;
+  Storage* data;
+  size_t size;
+  size_t capacity;
+};
+
+template <typename T>
+jvmtiError JvmtiWeakTable<T>::GetTaggedObjects(jvmtiEnv* jvmti_env,
+                                               jint tag_count,
+                                               const T* tags,
+                                               jint* count_ptr,
+                                               jobject** object_result_ptr,
+                                               T** tag_result_ptr) {
+  if (tag_count < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  if (tag_count > 0) {
+    for (size_t i = 0; i != static_cast<size_t>(tag_count); ++i) {
+      if (tags[i] == 0) {
+        return ERR(ILLEGAL_ARGUMENT);
+      }
+    }
+  }
+  if (tags == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  if (count_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::Thread* self = art::Thread::Current();
+  art::MutexLock mu(self, allow_disallow_lock_);
+  Wait(self);
+
+  art::JNIEnvExt* jni_env = self->GetJniEnv();
+
+  constexpr size_t kDefaultSize = 10;
+  size_t initial_object_size;
+  size_t initial_tag_size;
+  if (tag_count == 0) {
+    initial_object_size = (object_result_ptr != nullptr) ? tagged_objects_.size() : 0;
+    initial_tag_size = (tag_result_ptr != nullptr) ? tagged_objects_.size() : 0;
+  } else {
+    initial_object_size = initial_tag_size = kDefaultSize;
+  }
+  JvmtiAllocator<void> allocator(jvmti_env);
+  ReleasableContainer<jobject, JvmtiAllocator<jobject>> selected_objects(allocator,
+                                                                         initial_object_size);
+  ReleasableContainer<T, JvmtiAllocator<T>> selected_tags(allocator, initial_tag_size);
+
+  size_t count = 0;
+  for (auto& pair : tagged_objects_) {
+    bool select;
+    if (tag_count > 0) {
+      select = false;
+      for (size_t i = 0; i != static_cast<size_t>(tag_count); ++i) {
+        if (tags[i] == pair.second) {
+          select = true;
+          break;
+        }
+      }
+    } else {
+      select = true;
+    }
+
+    if (select) {
+      art::mirror::Object* obj = pair.first.template Read<art::kWithReadBarrier>();
+      if (obj != nullptr) {
+        count++;
+        if (object_result_ptr != nullptr) {
+          selected_objects.Pushback(jni_env->AddLocalReference<jobject>(obj));
+        }
+        if (tag_result_ptr != nullptr) {
+          selected_tags.Pushback(pair.second);
+        }
+      }
+    }
+  }
+
+  if (object_result_ptr != nullptr) {
+    *object_result_ptr = selected_objects.Release();
+  }
+  if (tag_result_ptr != nullptr) {
+    *tag_result_ptr = selected_tags.Release();
+  }
+  *count_ptr = static_cast<jint>(count);
+  return ERR(NONE);
+}
+
+template <typename T>
+art::mirror::Object* JvmtiWeakTable<T>::Find(T tag) {
+  art::Thread* self = art::Thread::Current();
+  art::MutexLock mu(self, allow_disallow_lock_);
+  Wait(self);
+
+  for (auto& pair : tagged_objects_) {
+    if (tag == pair.second) {
+      art::mirror::Object* obj = pair.first.template Read<art::kWithReadBarrier>();
+      if (obj != nullptr) {
+        return obj;
+      }
+    }
+  }
+  return nullptr;
+}
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_INL_H_
diff --git a/openjdkjvmti/jvmti_weak_table.h b/openjdkjvmti/jvmti_weak_table.h
new file mode 100644
index 0000000..5a821c9
--- /dev/null
+++ b/openjdkjvmti/jvmti_weak_table.h
@@ -0,0 +1,227 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_H_
+#define ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_H_
+
+#include <unordered_map>
+
+#include "base/macros.h"
+#include "base/mutex.h"
+#include "gc/system_weak.h"
+#include "gc_root-inl.h"
+#include "globals.h"
+#include "jvmti.h"
+#include "jvmti_allocator.h"
+#include "mirror/object.h"
+#include "thread-current-inl.h"
+
+namespace openjdkjvmti {
+
+class EventHandler;
+
+// A system-weak container mapping objects to elements of the template type. This corresponds
+// to a weak hash map. For historical reasons the stored value is called "tag."
+template <typename T>
+class JvmtiWeakTable : public art::gc::SystemWeakHolder {
+ public:
+  JvmtiWeakTable()
+      : art::gc::SystemWeakHolder(art::kTaggingLockLevel),
+        update_since_last_sweep_(false) {
+  }
+
+  // Remove the mapping for the given object, returning whether such a mapping existed (and the old
+  // value).
+  ALWAYS_INLINE bool Remove(art::mirror::Object* obj, /* out */ T* tag)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_);
+  ALWAYS_INLINE bool RemoveLocked(art::mirror::Object* obj, /* out */ T* tag)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_);
+
+  // Set the mapping for the given object. Returns true if this overwrites an already existing
+  // mapping.
+  ALWAYS_INLINE virtual bool Set(art::mirror::Object* obj, T tag)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_);
+  ALWAYS_INLINE virtual bool SetLocked(art::mirror::Object* obj, T tag)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_);
+
+  // Return the value associated with the given object. Returns true if the mapping exists, false
+  // otherwise.
+  bool GetTag(art::mirror::Object* obj, /* out */ T* result)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    art::Thread* self = art::Thread::Current();
+    art::MutexLock mu(self, allow_disallow_lock_);
+    Wait(self);
+
+    return GetTagLocked(self, obj, result);
+  }
+  bool GetTagLocked(art::mirror::Object* obj, /* out */ T* result)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_) {
+    art::Thread* self = art::Thread::Current();
+    allow_disallow_lock_.AssertHeld(self);
+    Wait(self);
+
+    return GetTagLocked(self, obj, result);
+  }
+
+  // Sweep the container. DO NOT CALL MANUALLY.
+  ALWAYS_INLINE void Sweep(art::IsMarkedVisitor* visitor)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_);
+
+  // Return all objects that have a value mapping in tags.
+  ALWAYS_INLINE
+  jvmtiError GetTaggedObjects(jvmtiEnv* jvmti_env,
+                              jint tag_count,
+                              const T* tags,
+                              /* out */ jint* count_ptr,
+                              /* out */ jobject** object_result_ptr,
+                              /* out */ T** tag_result_ptr)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_);
+
+  // Locking functions, to allow coarse-grained locking and amortization.
+  ALWAYS_INLINE  void Lock() ACQUIRE(allow_disallow_lock_);
+  ALWAYS_INLINE void Unlock() RELEASE(allow_disallow_lock_);
+  ALWAYS_INLINE void AssertLocked() ASSERT_CAPABILITY(allow_disallow_lock_);
+
+  ALWAYS_INLINE art::mirror::Object* Find(T tag)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_);
+
+ protected:
+  // Should HandleNullSweep be called when Sweep detects the release of an object?
+  virtual bool DoesHandleNullOnSweep() {
+    return false;
+  }
+  // If DoesHandleNullOnSweep returns true, this function will be called.
+  virtual void HandleNullSweep(T tag ATTRIBUTE_UNUSED) {}
+
+ private:
+  ALWAYS_INLINE
+  bool SetLocked(art::Thread* self, art::mirror::Object* obj, T tag)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_);
+
+  ALWAYS_INLINE
+  bool RemoveLocked(art::Thread* self, art::mirror::Object* obj, /* out */ T* tag)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_);
+
+  bool GetTagLocked(art::Thread* self, art::mirror::Object* obj, /* out */ T* result)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_) {
+    auto it = tagged_objects_.find(art::GcRoot<art::mirror::Object>(obj));
+    if (it != tagged_objects_.end()) {
+      *result = it->second;
+      return true;
+    }
+
+    // Performance optimization: To avoid multiple table updates, ensure that during GC we
+    // only update once. See the comment on the implementation of GetTagSlowPath.
+    if (art::kUseReadBarrier &&
+        self != nullptr &&
+        self->GetIsGcMarking() &&
+        !update_since_last_sweep_) {
+      return GetTagSlowPath(self, obj, result);
+    }
+
+    return false;
+  }
+
+  // Slow-path for GetTag. We didn't find the object, but we might be storing from-pointers and
+  // are asked to retrieve with a to-pointer.
+  ALWAYS_INLINE
+  bool GetTagSlowPath(art::Thread* self, art::mirror::Object* obj, /* out */ T* result)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_);
+
+  // Update the table by doing read barriers on each element, ensuring that to-space pointers
+  // are stored.
+  ALWAYS_INLINE
+  void UpdateTableWithReadBarrier()
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_);
+
+  template <bool kHandleNull>
+  void SweepImpl(art::IsMarkedVisitor* visitor)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_);
+
+  enum TableUpdateNullTarget {
+    kIgnoreNull,
+    kRemoveNull,
+    kCallHandleNull
+  };
+
+  template <typename Updater, TableUpdateNullTarget kTargetNull>
+  void UpdateTableWith(Updater& updater)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_);
+
+  template <typename Storage, class Allocator = JvmtiAllocator<T>>
+  struct ReleasableContainer;
+
+  struct HashGcRoot {
+    size_t operator()(const art::GcRoot<art::mirror::Object>& r) const
+        REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      return reinterpret_cast<uintptr_t>(r.Read<art::kWithoutReadBarrier>());
+    }
+  };
+
+  struct EqGcRoot {
+    bool operator()(const art::GcRoot<art::mirror::Object>& r1,
+                    const art::GcRoot<art::mirror::Object>& r2) const
+        REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      return r1.Read<art::kWithoutReadBarrier>() == r2.Read<art::kWithoutReadBarrier>();
+    }
+  };
+
+  using TagAllocator = JvmtiAllocator<std::pair<const art::GcRoot<art::mirror::Object>, T>>;
+  std::unordered_map<art::GcRoot<art::mirror::Object>,
+                     T,
+                     HashGcRoot,
+                     EqGcRoot,
+                     TagAllocator> tagged_objects_
+      GUARDED_BY(allow_disallow_lock_)
+      GUARDED_BY(art::Locks::mutator_lock_);
+  // To avoid repeatedly scanning the whole table, remember if we did that since the last sweep.
+  bool update_since_last_sweep_;
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_H_
diff --git a/openjdkjvmti/object_tagging.cc b/openjdkjvmti/object_tagging.cc
new file mode 100644
index 0000000..dcdd3ed
--- /dev/null
+++ b/openjdkjvmti/object_tagging.cc
@@ -0,0 +1,67 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "object_tagging.h"
+
+#include <limits>
+
+#include "art_jvmti.h"
+#include "events-inl.h"
+#include "jvmti_weak_table-inl.h"
+
+namespace openjdkjvmti {
+
+// Instantiate for jlong = JVMTI tags.
+template class JvmtiWeakTable<jlong>;
+
+bool ObjectTagTable::Set(art::mirror::Object* obj, jlong new_tag) {
+  if (new_tag == 0) {
+    jlong tmp;
+    return Remove(obj, &tmp);
+  }
+  return JvmtiWeakTable<jlong>::Set(obj, new_tag);
+}
+bool ObjectTagTable::SetLocked(art::mirror::Object* obj, jlong new_tag) {
+  if (new_tag == 0) {
+    jlong tmp;
+    return RemoveLocked(obj, &tmp);
+  }
+  return JvmtiWeakTable<jlong>::SetLocked(obj, new_tag);
+}
+
+bool ObjectTagTable::DoesHandleNullOnSweep() {
+  return event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kObjectFree);
+}
+void ObjectTagTable::HandleNullSweep(jlong tag) {
+  event_handler_->DispatchEvent<ArtJvmtiEvent::kObjectFree>(jvmti_env_, nullptr, tag);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/object_tagging.h b/openjdkjvmti/object_tagging.h
new file mode 100644
index 0000000..b474845
--- /dev/null
+++ b/openjdkjvmti/object_tagging.h
@@ -0,0 +1,86 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_OBJECT_TAGGING_H_
+#define ART_OPENJDKJVMTI_OBJECT_TAGGING_H_
+
+#include <unordered_map>
+
+#include "base/mutex.h"
+#include "globals.h"
+#include "jvmti.h"
+#include "jvmti_weak_table.h"
+#include "mirror/object.h"
+
+namespace openjdkjvmti {
+
+struct ArtJvmTiEnv;
+class EventHandler;
+
+class ObjectTagTable FINAL : public JvmtiWeakTable<jlong> {
+ public:
+  ObjectTagTable(EventHandler* event_handler, ArtJvmTiEnv* env)
+      : event_handler_(event_handler), jvmti_env_(env) {}
+
+  bool Set(art::mirror::Object* obj, jlong tag) OVERRIDE
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_);
+  bool SetLocked(art::mirror::Object* obj, jlong tag) OVERRIDE
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_);
+
+  jlong GetTagOrZero(art::mirror::Object* obj)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    jlong tmp = 0;
+    GetTag(obj, &tmp);
+    return tmp;
+  }
+  jlong GetTagOrZeroLocked(art::mirror::Object* obj)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(allow_disallow_lock_) {
+    jlong tmp = 0;
+    GetTagLocked(obj, &tmp);
+    return tmp;
+  }
+
+ protected:
+  bool DoesHandleNullOnSweep() OVERRIDE;
+  void HandleNullSweep(jlong tag) OVERRIDE;
+
+ private:
+  EventHandler* event_handler_;
+  ArtJvmTiEnv* jvmti_env_;
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_OBJECT_TAGGING_H_
diff --git a/openjdkjvmti/ti_allocator.cc b/openjdkjvmti/ti_allocator.cc
new file mode 100644
index 0000000..575558d
--- /dev/null
+++ b/openjdkjvmti/ti_allocator.cc
@@ -0,0 +1,95 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_allocator.h"
+
+#if defined(__APPLE__)
+// Apple doesn't have malloc.h. Just give this function a non-functional definition.
+#define malloc_usable_size(P) 0
+#else
+#include <malloc.h>
+#endif
+
+#include <atomic>
+
+#include "art_jvmti.h"
+#include "base/enums.h"
+
+namespace openjdkjvmti {
+
+std::atomic<jlong> AllocUtil::allocated;
+
+jvmtiError AllocUtil::GetGlobalJvmtiAllocationState(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                                    jlong* allocated_ptr) {
+  if (allocated_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  *allocated_ptr = allocated.load();
+  return OK;
+}
+
+jvmtiError AllocUtil::Allocate(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                               jlong size,
+                               unsigned char** mem_ptr) {
+  if (size < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  } else if (size == 0) {
+    *mem_ptr = nullptr;
+    return OK;
+  }
+  *mem_ptr = AllocateImpl(size);
+  if (UNLIKELY(*mem_ptr == nullptr)) {
+    return ERR(OUT_OF_MEMORY);
+  }
+  return OK;
+}
+
+unsigned char* AllocUtil::AllocateImpl(jlong size) {
+  unsigned char* ret = size != 0 ? reinterpret_cast<unsigned char*>(malloc(size)) : nullptr;
+  if (LIKELY(ret != nullptr)) {
+    allocated += malloc_usable_size(ret);
+  }
+  return ret;
+}
+
+jvmtiError AllocUtil::Deallocate(jvmtiEnv* env ATTRIBUTE_UNUSED, unsigned char* mem) {
+  DeallocateImpl(mem);
+  return OK;
+}
+
+void AllocUtil::DeallocateImpl(unsigned char* mem) {
+  if (mem != nullptr) {
+    allocated -= malloc_usable_size(mem);
+    free(mem);
+  }
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_allocator.h b/openjdkjvmti/ti_allocator.h
new file mode 100644
index 0000000..776cc5e
--- /dev/null
+++ b/openjdkjvmti/ti_allocator.h
@@ -0,0 +1,65 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_ALLOCATOR_H_
+#define ART_OPENJDKJVMTI_TI_ALLOCATOR_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+#include <atomic>
+#include <memory>
+
+namespace openjdkjvmti {
+
+template<typename T>
+class JvmtiAllocator;
+
+class AllocUtil {
+ public:
+  static jvmtiError Allocate(jvmtiEnv* env, jlong size, unsigned char** mem_ptr);
+  static jvmtiError Deallocate(jvmtiEnv* env, unsigned char* mem);
+  static jvmtiError GetGlobalJvmtiAllocationState(jvmtiEnv* env, jlong* total_allocated);
+
+ private:
+  static void DeallocateImpl(unsigned char* mem);
+  static unsigned char* AllocateImpl(jlong size);
+
+  static std::atomic<jlong> allocated;
+
+  template <typename T>
+  friend class JvmtiAllocator;
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_ALLOCATOR_H_
+
diff --git a/openjdkjvmti/ti_breakpoint.cc b/openjdkjvmti/ti_breakpoint.cc
new file mode 100644
index 0000000..f5116a8
--- /dev/null
+++ b/openjdkjvmti/ti_breakpoint.cc
@@ -0,0 +1,114 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <functional>
+
+#include "ti_breakpoint.h"
+
+#include "art_jvmti.h"
+#include "art_method-inl.h"
+#include "base/enums.h"
+#include "dex_file_annotations.h"
+#include "events-inl.h"
+#include "jni_internal.h"
+#include "mirror/class-inl.h"
+#include "mirror/object_array-inl.h"
+#include "modifiers.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "runtime_callbacks.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+#include "thread_list.h"
+#include "ti_phase.h"
+
+namespace openjdkjvmti {
+
+size_t Breakpoint::hash() const {
+  return std::hash<uintptr_t> {}(reinterpret_cast<uintptr_t>(method_))
+      ^ std::hash<jlocation> {}(location_);
+}
+
+Breakpoint::Breakpoint(art::ArtMethod* m, jlocation loc) : method_(m), location_(loc) {
+  DCHECK(!m->IsDefault() || !m->IsCopied() || !m->IsInvokable())
+      << "Flags are: 0x" << std::hex << m->GetAccessFlags();
+}
+
+void BreakpointUtil::RemoveBreakpointsInClass(ArtJvmTiEnv* env, art::mirror::Class* klass) {
+  std::vector<Breakpoint> to_remove;
+  for (const Breakpoint& b : env->breakpoints) {
+    if (b.GetMethod()->GetDeclaringClass() == klass) {
+      to_remove.push_back(b);
+    }
+  }
+  for (const Breakpoint& b : to_remove) {
+    auto it = env->breakpoints.find(b);
+    DCHECK(it != env->breakpoints.end());
+    env->breakpoints.erase(it);
+  }
+}
+
+jvmtiError BreakpointUtil::SetBreakpoint(jvmtiEnv* jenv, jmethodID method, jlocation location) {
+  ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
+  if (method == nullptr) {
+    return ERR(INVALID_METHODID);
+  }
+  // Need to get mutator_lock_ so we can find the interface version of any default methods.
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method)->GetCanonicalMethod();
+  if (location < 0 || static_cast<uint32_t>(location) >=
+      art_method->GetCodeItem()->insns_size_in_code_units_) {
+    return ERR(INVALID_LOCATION);
+  }
+  auto res_pair = env->breakpoints.insert(/* Breakpoint */ {art_method, location});
+  if (!res_pair.second) {
+    // Didn't get inserted because it's already present!
+    return ERR(DUPLICATE);
+  }
+  return OK;
+}
+
+jvmtiError BreakpointUtil::ClearBreakpoint(jvmtiEnv* jenv, jmethodID method, jlocation location) {
+  ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
+  if (method == nullptr) {
+    return ERR(INVALID_METHODID);
+  }
+  // Need to get mutator_lock_ so we can find the interface version of any default methods.
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  auto pos = env->breakpoints.find(
+      /* Breakpoint */ {art::jni::DecodeArtMethod(method)->GetCanonicalMethod(), location});
+  if (pos == env->breakpoints.end()) {
+    return ERR(NOT_FOUND);
+  }
+  env->breakpoints.erase(pos);
+  return OK;
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_breakpoint.h b/openjdkjvmti/ti_breakpoint.h
new file mode 100644
index 0000000..9b08b42
--- /dev/null
+++ b/openjdkjvmti/ti_breakpoint.h
@@ -0,0 +1,94 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_BREAKPOINT_H_
+#define ART_OPENJDKJVMTI_TI_BREAKPOINT_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+#include "base/mutex.h"
+
+namespace art {
+class ArtMethod;
+namespace mirror {
+class Class;
+}  // namespace mirror
+}  // namespace art
+
+namespace openjdkjvmti {
+
+struct ArtJvmTiEnv;
+
+class Breakpoint {
+ public:
+  Breakpoint(art::ArtMethod* m, jlocation loc);
+
+  // Get the hash code of this breakpoint.
+  size_t hash() const;
+
+  bool operator==(const Breakpoint& other) const {
+    return method_ == other.method_ && location_ == other.location_;
+  }
+
+  art::ArtMethod* GetMethod() const {
+    return method_;
+  }
+
+  jlocation GetLocation() const {
+    return location_;
+  }
+
+ private:
+  art::ArtMethod* method_;
+  jlocation location_;
+};
+
+class BreakpointUtil {
+ public:
+  static jvmtiError SetBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location);
+  static jvmtiError ClearBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location);
+  // Used by class redefinition to remove breakpoints on redefined classes.
+  static void RemoveBreakpointsInClass(ArtJvmTiEnv* env, art::mirror::Class* klass)
+      REQUIRES(art::Locks::mutator_lock_);
+};
+
+}  // namespace openjdkjvmti
+
+namespace std {
+template<> struct hash<openjdkjvmti::Breakpoint> {
+  size_t operator()(const openjdkjvmti::Breakpoint& b) const {
+    return b.hash();
+  }
+};
+
+}  // namespace std
+#endif  // ART_OPENJDKJVMTI_TI_BREAKPOINT_H_
diff --git a/openjdkjvmti/ti_class.cc b/openjdkjvmti/ti_class.cc
new file mode 100644
index 0000000..954b5d1
--- /dev/null
+++ b/openjdkjvmti/ti_class.cc
@@ -0,0 +1,1086 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_class.h"
+
+#include "android-base/stringprintf.h"
+
+#include <mutex>
+#include <unordered_set>
+
+#include "art_jvmti.h"
+#include "base/array_ref.h"
+#include "base/macros.h"
+#include "class_linker.h"
+#include "class_table-inl.h"
+#include "common_throws.h"
+#include "dex_file_annotations.h"
+#include "events-inl.h"
+#include "fixed_up_dex_file.h"
+#include "gc/heap-visit-objects-inl.h"
+#include "gc/heap.h"
+#include "gc_root.h"
+#include "handle.h"
+#include "jni_env_ext-inl.h"
+#include "jni_internal.h"
+#include "mirror/array-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_ext.h"
+#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/object_reference.h"
+#include "mirror/reference.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "primitive.h"
+#include "reflection.h"
+#include "runtime.h"
+#include "runtime_callbacks.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+#include "thread_list.h"
+#include "ti_class_loader.h"
+#include "ti_phase.h"
+#include "ti_redefine.h"
+#include "utils.h"
+#include "well_known_classes.h"
+
+namespace openjdkjvmti {
+
+using android::base::StringPrintf;
+
+static std::unique_ptr<const art::DexFile> MakeSingleDexFile(art::Thread* self,
+                                                             const char* descriptor,
+                                                             const std::string& orig_location,
+                                                             jint final_len,
+                                                             const unsigned char* final_dex_data)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  // Make the mmap
+  std::string error_msg;
+  art::ArrayRef<const unsigned char> final_data(final_dex_data, final_len);
+  std::unique_ptr<art::MemMap> map(Redefiner::MoveDataToMemMap(orig_location,
+                                                               final_data,
+                                                               &error_msg));
+  if (map.get() == nullptr) {
+    LOG(WARNING) << "Unable to allocate mmap for redefined dex file! Error was: " << error_msg;
+    self->ThrowOutOfMemoryError(StringPrintf(
+        "Unable to allocate dex file for transformation of %s", descriptor).c_str());
+    return nullptr;
+  }
+
+  // Make a dex-file
+  if (map->Size() < sizeof(art::DexFile::Header)) {
+    LOG(WARNING) << "Could not read dex file header because dex_data was too short";
+    art::ThrowClassFormatError(nullptr,
+                               "Unable to read transformed dex file of %s",
+                               descriptor);
+    return nullptr;
+  }
+  uint32_t checksum = reinterpret_cast<const art::DexFile::Header*>(map->Begin())->checksum_;
+  std::string map_name = map->GetName();
+  std::unique_ptr<const art::DexFile> dex_file(art::DexFile::Open(map_name,
+                                                                  checksum,
+                                                                  std::move(map),
+                                                                  /*verify*/true,
+                                                                  /*verify_checksum*/true,
+                                                                  &error_msg));
+  if (dex_file.get() == nullptr) {
+    LOG(WARNING) << "Unable to load modified dex file for " << descriptor << ": " << error_msg;
+    art::ThrowClassFormatError(nullptr,
+                               "Unable to read transformed dex file of %s because %s",
+                               descriptor,
+                               error_msg.c_str());
+    return nullptr;
+  }
+  if (dex_file->NumClassDefs() != 1) {
+    LOG(WARNING) << "Dex file contains more than 1 class_def. Ignoring.";
+    // TODO Throw some other sort of error here maybe?
+    art::ThrowClassFormatError(
+        nullptr,
+        "Unable to use transformed dex file of %s because it contained too many classes",
+        descriptor);
+    return nullptr;
+  }
+  return dex_file;
+}
+
+// A deleter that acts like the jvmtiEnv->Deallocate so that asan does not get tripped up.
+// TODO We should everything use the actual jvmtiEnv->Allocate/Deallocate functions once we can
+// figure out which env to use.
+template <typename T>
+class FakeJvmtiDeleter {
+ public:
+  FakeJvmtiDeleter() {}
+
+  FakeJvmtiDeleter(FakeJvmtiDeleter&) = default;
+  FakeJvmtiDeleter(FakeJvmtiDeleter&&) = default;
+  FakeJvmtiDeleter& operator=(const FakeJvmtiDeleter&) = default;
+
+  template <typename U> void operator()(const U* ptr) const {
+    if (ptr != nullptr) {
+      free(const_cast<U*>(ptr));
+    }
+  }
+};
+
+struct ClassCallback : public art::ClassLoadCallback {
+  void ClassPreDefine(const char* descriptor,
+                      art::Handle<art::mirror::Class> klass,
+                      art::Handle<art::mirror::ClassLoader> class_loader,
+                      const art::DexFile& initial_dex_file,
+                      const art::DexFile::ClassDef& initial_class_def ATTRIBUTE_UNUSED,
+                      /*out*/art::DexFile const** final_dex_file,
+                      /*out*/art::DexFile::ClassDef const** final_class_def)
+      OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    bool is_enabled =
+        event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kClassFileLoadHookRetransformable) ||
+        event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kClassFileLoadHookNonRetransformable);
+    if (!is_enabled) {
+      return;
+    }
+    if (descriptor[0] != 'L') {
+      // It is a primitive or array. Just return
+      return;
+    }
+    jvmtiPhase phase = PhaseUtil::GetPhaseUnchecked();
+    if (UNLIKELY(phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE)) {
+      // We want to wait until we are at least in the START phase so that all WellKnownClasses and
+      // mirror classes have been initialized and loaded. The runtime relies on these classes having
+      // specific fields and methods present. Since PreDefine hooks don't need to abide by this
+      // restriction we will simply not send the event for these classes.
+      LOG(WARNING) << "Ignoring load of class <" << descriptor << "> as it is being loaded during "
+                   << "runtime initialization.";
+      return;
+    }
+
+    // Strip the 'L' and ';' from the descriptor
+    std::string name(std::string(descriptor).substr(1, strlen(descriptor) - 2));
+
+    art::Thread* self = art::Thread::Current();
+    art::JNIEnvExt* env = self->GetJniEnv();
+    ScopedLocalRef<jobject> loader(
+        env, class_loader.IsNull() ? nullptr : env->AddLocalReference<jobject>(class_loader.Get()));
+    std::unique_ptr<FixedUpDexFile> dex_file_copy(FixedUpDexFile::Create(initial_dex_file));
+
+    // Go back to native.
+    art::ScopedThreadSuspension sts(self, art::ThreadState::kNative);
+    // Call all Non-retransformable agents.
+    jint post_no_redefine_len = 0;
+    unsigned char* post_no_redefine_dex_data = nullptr;
+    std::unique_ptr<const unsigned char, FakeJvmtiDeleter<const unsigned char>>
+        post_no_redefine_unique_ptr(nullptr, FakeJvmtiDeleter<const unsigned char>());
+    event_handler->DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookNonRetransformable>(
+        self,
+        static_cast<JNIEnv*>(env),
+        static_cast<jclass>(nullptr),  // The class doesn't really exist yet so send null.
+        loader.get(),
+        name.c_str(),
+        static_cast<jobject>(nullptr),  // Android doesn't seem to have protection domains
+        static_cast<jint>(dex_file_copy->Size()),
+        static_cast<const unsigned char*>(dex_file_copy->Begin()),
+        static_cast<jint*>(&post_no_redefine_len),
+        static_cast<unsigned char**>(&post_no_redefine_dex_data));
+    if (post_no_redefine_dex_data == nullptr) {
+      DCHECK_EQ(post_no_redefine_len, 0);
+      post_no_redefine_dex_data = const_cast<unsigned char*>(dex_file_copy->Begin());
+      post_no_redefine_len = dex_file_copy->Size();
+    } else {
+      post_no_redefine_unique_ptr =
+          std::unique_ptr<const unsigned char, FakeJvmtiDeleter<const unsigned char>>(
+              post_no_redefine_dex_data, FakeJvmtiDeleter<const unsigned char>());
+      DCHECK_GT(post_no_redefine_len, 0);
+    }
+    // Call all retransformable agents.
+    jint final_len = 0;
+    unsigned char* final_dex_data = nullptr;
+    std::unique_ptr<const unsigned char, FakeJvmtiDeleter<const unsigned char>>
+        final_dex_unique_ptr(nullptr, FakeJvmtiDeleter<const unsigned char>());
+    event_handler->DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookRetransformable>(
+        self,
+        static_cast<JNIEnv*>(env),
+        static_cast<jclass>(nullptr),  // The class doesn't really exist yet so send null.
+        loader.get(),
+        name.c_str(),
+        static_cast<jobject>(nullptr),  // Android doesn't seem to have protection domains
+        static_cast<jint>(post_no_redefine_len),
+        static_cast<const unsigned char*>(post_no_redefine_dex_data),
+        static_cast<jint*>(&final_len),
+        static_cast<unsigned char**>(&final_dex_data));
+    if (final_dex_data == nullptr) {
+      DCHECK_EQ(final_len, 0);
+      final_dex_data = post_no_redefine_dex_data;
+      final_len = post_no_redefine_len;
+    } else {
+      final_dex_unique_ptr =
+          std::unique_ptr<const unsigned char, FakeJvmtiDeleter<const unsigned char>>(
+              final_dex_data, FakeJvmtiDeleter<const unsigned char>());
+      DCHECK_GT(final_len, 0);
+    }
+
+    if (final_dex_data != dex_file_copy->Begin()) {
+      LOG(WARNING) << "Changing class " << descriptor;
+      art::ScopedObjectAccess soa(self);
+      art::StackHandleScope<2> hs(self);
+      // Save the results of all the non-retransformable agents.
+      // First allocate the ClassExt
+      art::Handle<art::mirror::ClassExt> ext(hs.NewHandle(klass->EnsureExtDataPresent(self)));
+      // Make sure we have a ClassExt. This is fine even though we are a temporary since it will
+      // get copied.
+      if (ext.IsNull()) {
+        // We will just return failure if we fail to allocate
+        LOG(WARNING) << "Could not allocate ext-data for class '" << descriptor << "'. "
+                     << "Aborting transformation since we will be unable to store it.";
+        self->AssertPendingOOMException();
+        return;
+      }
+
+      // Allocate the byte array to store the dex file bytes in.
+      art::MutableHandle<art::mirror::Object> arr(hs.NewHandle<art::mirror::Object>(nullptr));
+      if (post_no_redefine_dex_data == dex_file_copy->Begin() && name != "java/lang/Long") {
+        // we didn't have any non-retransformable agents. We can just cache a pointer to the
+        // initial_dex_file. It will be kept live by the class_loader.
+        jlong dex_ptr = reinterpret_cast<uintptr_t>(&initial_dex_file);
+        art::JValue val;
+        val.SetJ(dex_ptr);
+        arr.Assign(art::BoxPrimitive(art::Primitive::kPrimLong, val));
+      } else {
+        arr.Assign(art::mirror::ByteArray::AllocateAndFill(
+            self,
+            reinterpret_cast<const signed char*>(post_no_redefine_dex_data),
+            post_no_redefine_len));
+      }
+      if (arr.IsNull()) {
+        LOG(WARNING) << "Unable to allocate memory for initial dex-file. Aborting transformation";
+        self->AssertPendingOOMException();
+        return;
+      }
+
+      std::unique_ptr<const art::DexFile> dex_file(MakeSingleDexFile(self,
+                                                                     descriptor,
+                                                                     initial_dex_file.GetLocation(),
+                                                                     final_len,
+                                                                     final_dex_data));
+      if (dex_file.get() == nullptr) {
+        return;
+      }
+
+      // TODO Check Redefined dex file for all invariants.
+      LOG(WARNING) << "Dex file created by class-definition time transformation of "
+                   << descriptor << " is not checked for all retransformation invariants.";
+
+      if (!ClassLoaderHelper::AddToClassLoader(self, class_loader, dex_file.get())) {
+        LOG(ERROR) << "Unable to add " << descriptor << " to class loader!";
+        return;
+      }
+
+      // Actually set the ClassExt's original bytes once we have actually succeeded.
+      ext->SetOriginalDexFile(arr.Get());
+      // Set the return values
+      *final_class_def = &dex_file->GetClassDef(0);
+      *final_dex_file = dex_file.release();
+    }
+  }
+
+  void ClassLoad(art::Handle<art::mirror::Class> klass) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kClassLoad)) {
+      art::Thread* thread = art::Thread::Current();
+      ScopedLocalRef<jclass> jklass(thread->GetJniEnv(),
+                                    thread->GetJniEnv()->AddLocalReference<jclass>(klass.Get()));
+      art::ObjPtr<art::mirror::Object> peer(thread->GetPeer());
+      ScopedLocalRef<jthread> thread_jni(
+          thread->GetJniEnv(),
+          peer.IsNull() ? nullptr : thread->GetJniEnv()->AddLocalReference<jthread>(peer));
+      {
+        art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative);
+        event_handler->DispatchEvent<ArtJvmtiEvent::kClassLoad>(
+            thread,
+            static_cast<JNIEnv*>(thread->GetJniEnv()),
+            thread_jni.get(),
+            jklass.get());
+      }
+      if (klass->IsTemp()) {
+        AddTempClass(thread, jklass.get());
+      }
+    }
+  }
+
+  void ClassPrepare(art::Handle<art::mirror::Class> temp_klass,
+                    art::Handle<art::mirror::Class> klass)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kClassPrepare)) {
+      art::Thread* thread = art::Thread::Current();
+      if (temp_klass.Get() != klass.Get()) {
+        DCHECK(temp_klass->IsTemp());
+        DCHECK(temp_klass->IsRetired());
+        HandleTempClass(thread, temp_klass, klass);
+      }
+      ScopedLocalRef<jclass> jklass(thread->GetJniEnv(),
+                                    thread->GetJniEnv()->AddLocalReference<jclass>(klass.Get()));
+      art::ObjPtr<art::mirror::Object> peer(thread->GetPeer());
+      ScopedLocalRef<jthread> thread_jni(
+          thread->GetJniEnv(),
+          peer.IsNull() ? nullptr : thread->GetJniEnv()->AddLocalReference<jthread>(peer));
+      art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative);
+      event_handler->DispatchEvent<ArtJvmtiEvent::kClassPrepare>(
+          thread,
+          static_cast<JNIEnv*>(thread->GetJniEnv()),
+          thread_jni.get(),
+          jklass.get());
+    }
+  }
+
+  // To support parallel class-loading, we need to perform some locking dances here. Namely,
+  // the fixup stage must not be holding the temp_classes lock when it fixes up the system
+  // (as that requires suspending all mutators).
+
+  void AddTempClass(art::Thread* self, jclass klass) {
+    std::unique_lock<std::mutex> mu(temp_classes_lock);
+    jclass global_klass = reinterpret_cast<jclass>(self->GetJniEnv()->NewGlobalRef(klass));
+    temp_classes.push_back(global_klass);
+  }
+
+  void HandleTempClass(art::Thread* self,
+                       art::Handle<art::mirror::Class> temp_klass,
+                       art::Handle<art::mirror::Class> klass)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    bool requires_fixup = false;
+    {
+      std::unique_lock<std::mutex> mu(temp_classes_lock);
+      if (temp_classes.empty()) {
+        return;
+      }
+
+      for (auto it = temp_classes.begin(); it != temp_classes.end(); ++it) {
+        if (temp_klass.Get() == art::ObjPtr<art::mirror::Class>::DownCast(self->DecodeJObject(*it))) {
+          self->GetJniEnv()->DeleteGlobalRef(*it);
+          temp_classes.erase(it);
+          requires_fixup = true;
+          break;
+        }
+      }
+    }
+    if (requires_fixup) {
+      FixupTempClass(self, temp_klass, klass);
+    }
+  }
+
+  void FixupTempClass(art::Thread* self,
+                      art::Handle<art::mirror::Class> temp_klass,
+                      art::Handle<art::mirror::Class> klass)
+     REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    // Suspend everything.
+    art::gc::Heap* heap = art::Runtime::Current()->GetHeap();
+    if (heap->IsGcConcurrentAndMoving()) {
+      // Need to take a heap dump while GC isn't running. See the
+      // comment in Heap::VisitObjects().
+      heap->IncrementDisableMovingGC(self);
+    }
+    {
+      art::ScopedThreadSuspension sts(self, art::kWaitingForVisitObjects);
+      art::ScopedSuspendAll ssa("FixupTempClass");
+
+      art::mirror::Class* input = temp_klass.Get();
+      art::mirror::Class* output = klass.Get();
+
+      FixupGlobalReferenceTables(input, output);
+      FixupLocalReferenceTables(self, input, output);
+      FixupHeap(input, output);
+    }
+    if (heap->IsGcConcurrentAndMoving()) {
+      heap->DecrementDisableMovingGC(self);
+    }
+  }
+
+  class RootUpdater : public art::RootVisitor {
+   public:
+    RootUpdater(const art::mirror::Class* input, art::mirror::Class* output)
+        : input_(input), output_(output) {}
+
+    void VisitRoots(art::mirror::Object*** roots,
+                    size_t count,
+                    const art::RootInfo& info ATTRIBUTE_UNUSED)
+        OVERRIDE {
+      for (size_t i = 0; i != count; ++i) {
+        if (*roots[i] == input_) {
+          *roots[i] = output_;
+        }
+      }
+    }
+
+    void VisitRoots(art::mirror::CompressedReference<art::mirror::Object>** roots,
+                    size_t count,
+                    const art::RootInfo& info ATTRIBUTE_UNUSED)
+        OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      for (size_t i = 0; i != count; ++i) {
+        if (roots[i]->AsMirrorPtr() == input_) {
+          roots[i]->Assign(output_);
+        }
+      }
+    }
+
+   private:
+    const art::mirror::Class* input_;
+    art::mirror::Class* output_;
+  };
+
+  void FixupGlobalReferenceTables(art::mirror::Class* input, art::mirror::Class* output)
+      REQUIRES(art::Locks::mutator_lock_) {
+    art::JavaVMExt* java_vm = art::Runtime::Current()->GetJavaVM();
+
+    // Fix up the global table with a root visitor.
+    RootUpdater global_update(input, output);
+    java_vm->VisitRoots(&global_update);
+
+    class WeakGlobalUpdate : public art::IsMarkedVisitor {
+     public:
+      WeakGlobalUpdate(art::mirror::Class* root_input, art::mirror::Class* root_output)
+          : input_(root_input), output_(root_output) {}
+
+      art::mirror::Object* IsMarked(art::mirror::Object* obj) OVERRIDE {
+        if (obj == input_) {
+          return output_;
+        }
+        return obj;
+      }
+
+     private:
+      const art::mirror::Class* input_;
+      art::mirror::Class* output_;
+    };
+    WeakGlobalUpdate weak_global_update(input, output);
+    java_vm->SweepJniWeakGlobals(&weak_global_update);
+  }
+
+  void FixupLocalReferenceTables(art::Thread* self,
+                                 art::mirror::Class* input,
+                                 art::mirror::Class* output)
+      REQUIRES(art::Locks::mutator_lock_) {
+    class LocalUpdate {
+     public:
+      LocalUpdate(const art::mirror::Class* root_input, art::mirror::Class* root_output)
+          : input_(root_input), output_(root_output) {}
+
+      static void Callback(art::Thread* t, void* arg) REQUIRES(art::Locks::mutator_lock_) {
+        LocalUpdate* local = reinterpret_cast<LocalUpdate*>(arg);
+
+        // Fix up the local table with a root visitor.
+        RootUpdater local_update(local->input_, local->output_);
+        t->GetJniEnv()->locals.VisitRoots(
+            &local_update, art::RootInfo(art::kRootJNILocal, t->GetThreadId()));
+      }
+
+     private:
+      const art::mirror::Class* input_;
+      art::mirror::Class* output_;
+    };
+    LocalUpdate local_upd(input, output);
+    art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+    art::Runtime::Current()->GetThreadList()->ForEach(LocalUpdate::Callback, &local_upd);
+  }
+
+  void FixupHeap(art::mirror::Class* input, art::mirror::Class* output)
+        REQUIRES(art::Locks::mutator_lock_) {
+    class HeapFixupVisitor {
+     public:
+      HeapFixupVisitor(const art::mirror::Class* root_input, art::mirror::Class* root_output)
+                : input_(root_input), output_(root_output) {}
+
+      void operator()(art::mirror::Object* src,
+                      art::MemberOffset field_offset,
+                      bool is_static ATTRIBUTE_UNUSED) const
+          REQUIRES_SHARED(art::Locks::mutator_lock_) {
+        art::mirror::HeapReference<art::mirror::Object>* trg =
+          src->GetFieldObjectReferenceAddr(field_offset);
+        if (trg->AsMirrorPtr() == input_) {
+          DCHECK_NE(field_offset.Uint32Value(), 0u);  // This shouldn't be the class field of
+                                                      // an object.
+          trg->Assign(output_);
+        }
+      }
+
+      void operator()(art::ObjPtr<art::mirror::Class> klass ATTRIBUTE_UNUSED,
+                      art::ObjPtr<art::mirror::Reference> reference) const
+          REQUIRES_SHARED(art::Locks::mutator_lock_) {
+        art::mirror::Object* val = reference->GetReferent();
+        if (val == input_) {
+          reference->SetReferent<false>(output_);
+        }
+      }
+
+      void VisitRoot(art::mirror::CompressedReference<art::mirror::Object>* root ATTRIBUTE_UNUSED)
+          const {
+        LOG(FATAL) << "Unreachable";
+      }
+
+      void VisitRootIfNonNull(
+          art::mirror::CompressedReference<art::mirror::Object>* root ATTRIBUTE_UNUSED) const {
+        LOG(FATAL) << "Unreachable";
+      }
+
+     private:
+      const art::mirror::Class* input_;
+      art::mirror::Class* output_;
+    };
+    HeapFixupVisitor hfv(input, output);
+    auto object_visitor = [&](art::mirror::Object* obj) {
+      obj->VisitReferences<false>(hfv, hfv);  // Visit references, not native roots.
+    };
+    art::Runtime::Current()->GetHeap()->VisitObjectsPaused(object_visitor);
+  }
+
+  // A set of all the temp classes we have handed out. We have to fix up references to these.
+  // For simplicity, we store the temp classes as JNI global references in a vector. Normally a
+  // Prepare event will closely follow, so the vector should be small.
+  std::mutex temp_classes_lock;
+  std::vector<jclass> temp_classes;
+
+  EventHandler* event_handler = nullptr;
+};
+
+ClassCallback gClassCallback;
+
+void ClassUtil::Register(EventHandler* handler) {
+  gClassCallback.event_handler = handler;
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Add load callback");
+  art::Runtime::Current()->GetRuntimeCallbacks()->AddClassLoadCallback(&gClassCallback);
+}
+
+void ClassUtil::Unregister() {
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Remove thread callback");
+  art::Runtime* runtime = art::Runtime::Current();
+  runtime->GetRuntimeCallbacks()->RemoveClassLoadCallback(&gClassCallback);
+}
+
+jvmtiError ClassUtil::GetClassFields(jvmtiEnv* env,
+                                     jclass jklass,
+                                     jint* field_count_ptr,
+                                     jfieldID** fields_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Class> klass = soa.Decode<art::mirror::Class>(jklass);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+
+  // Check if this class is a temporary class object used for loading. Since we are seeing it the
+  // class must not have been prepared yet since otherwise the fixup would have gotten the jobject
+  // to point to the final class object.
+  if (klass->IsTemp() || klass->IsRetired()) {
+    return ERR(CLASS_NOT_PREPARED);
+  }
+
+  if (field_count_ptr == nullptr || fields_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::IterationRange<art::StrideIterator<art::ArtField>> ifields = klass->GetIFields();
+  art::IterationRange<art::StrideIterator<art::ArtField>> sfields = klass->GetSFields();
+  size_t array_size = klass->NumInstanceFields() + klass->NumStaticFields();
+
+  unsigned char* out_ptr;
+  jvmtiError allocError = env->Allocate(array_size * sizeof(jfieldID), &out_ptr);
+  if (allocError != ERR(NONE)) {
+    return allocError;
+  }
+  jfieldID* field_array = reinterpret_cast<jfieldID*>(out_ptr);
+
+  size_t array_idx = 0;
+  for (art::ArtField& field : sfields) {
+    field_array[array_idx] = art::jni::EncodeArtField(&field);
+    ++array_idx;
+  }
+  for (art::ArtField& field : ifields) {
+    field_array[array_idx] = art::jni::EncodeArtField(&field);
+    ++array_idx;
+  }
+
+  *field_count_ptr = static_cast<jint>(array_size);
+  *fields_ptr = field_array;
+
+  return ERR(NONE);
+}
+
+jvmtiError ClassUtil::GetClassMethods(jvmtiEnv* env,
+                                      jclass jklass,
+                                      jint* method_count_ptr,
+                                      jmethodID** methods_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Class> klass = soa.Decode<art::mirror::Class>(jklass);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+
+  // Check if this class is a temporary class object used for loading. Since we are seeing it the
+  // class must not have been prepared yet since otherwise the fixup would have gotten the jobject
+  // to point to the final class object.
+  if (klass->IsTemp() || klass->IsRetired()) {
+    return ERR(CLASS_NOT_PREPARED);
+  }
+
+  if (method_count_ptr == nullptr || methods_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  size_t array_size = klass->NumDeclaredVirtualMethods() + klass->NumDirectMethods();
+  unsigned char* out_ptr;
+  jvmtiError allocError = env->Allocate(array_size * sizeof(jmethodID), &out_ptr);
+  if (allocError != ERR(NONE)) {
+    return allocError;
+  }
+  jmethodID* method_array = reinterpret_cast<jmethodID*>(out_ptr);
+
+  if (art::kIsDebugBuild) {
+    size_t count = 0;
+    for (auto& m ATTRIBUTE_UNUSED : klass->GetDeclaredMethods(art::kRuntimePointerSize)) {
+      count++;
+    }
+    CHECK_EQ(count, klass->NumDirectMethods() + klass->NumDeclaredVirtualMethods());
+  }
+
+  size_t array_idx = 0;
+  for (auto& m : klass->GetDeclaredMethods(art::kRuntimePointerSize)) {
+    method_array[array_idx] = art::jni::EncodeArtMethod(&m);
+    ++array_idx;
+  }
+
+  *method_count_ptr = static_cast<jint>(array_size);
+  *methods_ptr = method_array;
+
+  return ERR(NONE);
+}
+
+jvmtiError ClassUtil::GetImplementedInterfaces(jvmtiEnv* env,
+                                               jclass jklass,
+                                               jint* interface_count_ptr,
+                                               jclass** interfaces_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Class> klass = soa.Decode<art::mirror::Class>(jklass);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+
+  if (interface_count_ptr == nullptr || interfaces_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  // Need to handle array specifically. Arrays implement Serializable and Cloneable, but the
+  // spec says these should not be reported.
+  if (klass->IsArrayClass()) {
+    *interface_count_ptr = 0;
+    *interfaces_ptr = nullptr;  // TODO: Should we allocate a dummy here?
+    return ERR(NONE);
+  }
+
+  size_t array_size = klass->NumDirectInterfaces();
+  unsigned char* out_ptr;
+  jvmtiError allocError = env->Allocate(array_size * sizeof(jclass), &out_ptr);
+  if (allocError != ERR(NONE)) {
+    return allocError;
+  }
+  jclass* interface_array = reinterpret_cast<jclass*>(out_ptr);
+
+  art::StackHandleScope<1> hs(soa.Self());
+  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(klass));
+
+  for (uint32_t idx = 0; idx != array_size; ++idx) {
+    art::ObjPtr<art::mirror::Class> inf_klass =
+        art::mirror::Class::ResolveDirectInterface(soa.Self(), h_klass, idx);
+    if (inf_klass == nullptr) {
+      soa.Self()->ClearException();
+      env->Deallocate(out_ptr);
+      // TODO: What is the right error code here?
+      return ERR(INTERNAL);
+    }
+    interface_array[idx] = soa.AddLocalReference<jclass>(inf_klass);
+  }
+
+  *interface_count_ptr = static_cast<jint>(array_size);
+  *interfaces_ptr = interface_array;
+
+  return ERR(NONE);
+}
+
+jvmtiError ClassUtil::GetClassSignature(jvmtiEnv* env,
+                                         jclass jklass,
+                                         char** signature_ptr,
+                                         char** generic_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Class> klass = soa.Decode<art::mirror::Class>(jklass);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+
+  JvmtiUniquePtr<char[]> sig_copy;
+  if (signature_ptr != nullptr) {
+    std::string storage;
+    const char* descriptor = klass->GetDescriptor(&storage);
+
+    jvmtiError ret;
+    sig_copy = CopyString(env, descriptor, &ret);
+    if (sig_copy == nullptr) {
+      return ret;
+    }
+    *signature_ptr = sig_copy.get();
+  }
+
+  if (generic_ptr != nullptr) {
+    *generic_ptr = nullptr;
+    if (!klass->IsProxyClass() && klass->GetDexCache() != nullptr) {
+      art::StackHandleScope<1> hs(soa.Self());
+      art::Handle<art::mirror::Class> h_klass = hs.NewHandle(klass);
+      art::mirror::ObjectArray<art::mirror::String>* str_array =
+          art::annotations::GetSignatureAnnotationForClass(h_klass);
+      if (str_array != nullptr) {
+        std::ostringstream oss;
+        for (int32_t i = 0; i != str_array->GetLength(); ++i) {
+          oss << str_array->Get(i)->ToModifiedUtf8();
+        }
+        std::string output_string = oss.str();
+        jvmtiError ret;
+        JvmtiUniquePtr<char[]> copy = CopyString(env, output_string.c_str(), &ret);
+        if (copy == nullptr) {
+          return ret;
+        }
+        *generic_ptr = copy.release();
+      } else if (soa.Self()->IsExceptionPending()) {
+        // TODO: Should we report an error here?
+        soa.Self()->ClearException();
+      }
+    }
+  }
+
+  // Everything is fine, release the buffers.
+  sig_copy.release();
+
+  return ERR(NONE);
+}
+
+jvmtiError ClassUtil::GetClassStatus(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                     jclass jklass,
+                                     jint* status_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Class> klass = soa.Decode<art::mirror::Class>(jklass);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+
+  if (status_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  if (klass->IsArrayClass()) {
+    *status_ptr = JVMTI_CLASS_STATUS_ARRAY;
+  } else if (klass->IsPrimitive()) {
+    *status_ptr = JVMTI_CLASS_STATUS_PRIMITIVE;
+  } else {
+    *status_ptr = JVMTI_CLASS_STATUS_VERIFIED;  // All loaded classes are structurally verified.
+    // This is finicky. If there's an error, we'll say it wasn't prepared.
+    if (klass->IsResolved()) {
+      *status_ptr |= JVMTI_CLASS_STATUS_PREPARED;
+    }
+    if (klass->IsInitialized()) {
+      *status_ptr |= JVMTI_CLASS_STATUS_INITIALIZED;
+    }
+    // Technically the class may be erroneous for other reasons, but we do not have enough info.
+    if (klass->IsErroneous()) {
+      *status_ptr |= JVMTI_CLASS_STATUS_ERROR;
+    }
+  }
+
+  return ERR(NONE);
+}
+
+template <typename T>
+static jvmtiError ClassIsT(jclass jklass, T test, jboolean* is_t_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Class> klass = soa.Decode<art::mirror::Class>(jklass);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+
+  if (is_t_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  *is_t_ptr = test(klass) ? JNI_TRUE : JNI_FALSE;
+  return ERR(NONE);
+}
+
+jvmtiError ClassUtil::IsInterface(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                  jclass jklass,
+                                  jboolean* is_interface_ptr) {
+  auto test = [](art::ObjPtr<art::mirror::Class> klass) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return klass->IsInterface();
+  };
+  return ClassIsT(jklass, test, is_interface_ptr);
+}
+
+jvmtiError ClassUtil::IsArrayClass(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                   jclass jklass,
+                                   jboolean* is_array_class_ptr) {
+  auto test = [](art::ObjPtr<art::mirror::Class> klass) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return klass->IsArrayClass();
+  };
+  return ClassIsT(jklass, test, is_array_class_ptr);
+}
+
+// Keep this in sync with Class.getModifiers().
+static uint32_t ClassGetModifiers(art::Thread* self, art::ObjPtr<art::mirror::Class> klass)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  if (klass->IsArrayClass()) {
+    uint32_t component_modifiers = ClassGetModifiers(self, klass->GetComponentType());
+    if ((component_modifiers & art::kAccInterface) != 0) {
+      component_modifiers &= ~(art::kAccInterface | art::kAccStatic);
+    }
+    return art::kAccAbstract | art::kAccFinal | component_modifiers;
+  }
+
+  uint32_t modifiers = klass->GetAccessFlags() & art::kAccJavaFlagsMask;
+
+  art::StackHandleScope<1> hs(self);
+  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(klass));
+  return art::mirror::Class::GetInnerClassFlags(h_klass, modifiers);
+}
+
+jvmtiError ClassUtil::GetClassModifiers(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                        jclass jklass,
+                                        jint* modifiers_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Class> klass = soa.Decode<art::mirror::Class>(jklass);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+
+  if (modifiers_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  *modifiers_ptr = ClassGetModifiers(soa.Self(), klass);
+
+  return ERR(NONE);
+}
+
+jvmtiError ClassUtil::GetClassLoader(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                     jclass jklass,
+                                     jobject* classloader_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Class> klass = soa.Decode<art::mirror::Class>(jklass);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+
+  if (classloader_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  *classloader_ptr = soa.AddLocalReference<jobject>(klass->GetClassLoader());
+
+  return ERR(NONE);
+}
+
+jvmtiError ClassUtil::GetClassLoaderClasses(jvmtiEnv* env,
+                                            jobject initiating_loader,
+                                            jint* class_count_ptr,
+                                            jclass** classes_ptr) {
+  UNUSED(env, initiating_loader, class_count_ptr, classes_ptr);
+
+  if (class_count_ptr == nullptr || classes_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  art::Thread* self = art::Thread::Current();
+  if (!self->GetJniEnv()->IsInstanceOf(initiating_loader,
+                                       art::WellKnownClasses::java_lang_ClassLoader)) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  if (self->GetJniEnv()->IsInstanceOf(initiating_loader,
+                                      art::WellKnownClasses::java_lang_BootClassLoader)) {
+    // Need to use null for the BootClassLoader.
+    initiating_loader = nullptr;
+  }
+
+  art::ScopedObjectAccess soa(self);
+  art::ObjPtr<art::mirror::ClassLoader> class_loader =
+      soa.Decode<art::mirror::ClassLoader>(initiating_loader);
+
+  art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
+
+  art::ReaderMutexLock mu(self, *art::Locks::classlinker_classes_lock_);
+
+  art::ClassTable* class_table = class_linker->ClassTableForClassLoader(class_loader);
+  if (class_table == nullptr) {
+    // Nothing loaded.
+    *class_count_ptr = 0;
+    *classes_ptr = nullptr;
+    return ERR(NONE);
+  }
+
+  struct ClassTableCount {
+    bool operator()(art::ObjPtr<art::mirror::Class> klass) {
+      DCHECK(klass != nullptr);
+      ++count;
+      return true;
+    }
+
+    size_t count = 0;
+  };
+  ClassTableCount ctc;
+  class_table->Visit(ctc);
+
+  if (ctc.count == 0) {
+    // Nothing loaded.
+    *class_count_ptr = 0;
+    *classes_ptr = nullptr;
+    return ERR(NONE);
+  }
+
+  unsigned char* data;
+  jvmtiError data_result = env->Allocate(ctc.count * sizeof(jclass), &data);
+  if (data_result != ERR(NONE)) {
+    return data_result;
+  }
+  jclass* class_array = reinterpret_cast<jclass*>(data);
+
+  struct ClassTableFill {
+    bool operator()(art::ObjPtr<art::mirror::Class> klass)
+        REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      DCHECK(klass != nullptr);
+      DCHECK_LT(count, ctc_ref.count);
+      local_class_array[count++] = soa_ptr->AddLocalReference<jclass>(klass);
+      return true;
+    }
+
+    jclass* local_class_array;
+    const ClassTableCount& ctc_ref;
+    art::ScopedObjectAccess* soa_ptr;
+    size_t count;
+  };
+  ClassTableFill ctf = { class_array, ctc, &soa, 0 };
+  class_table->Visit(ctf);
+  DCHECK_EQ(ctc.count, ctf.count);
+
+  *class_count_ptr = ctc.count;
+  *classes_ptr = class_array;
+
+  return ERR(NONE);
+}
+
+jvmtiError ClassUtil::GetClassVersionNumbers(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                             jclass jklass,
+                                             jint* minor_version_ptr,
+                                             jint* major_version_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  if (jklass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  art::ObjPtr<art::mirror::Object> jklass_obj = soa.Decode<art::mirror::Object>(jklass);
+  if (!jklass_obj->IsClass()) {
+    return ERR(INVALID_CLASS);
+  }
+  art::ObjPtr<art::mirror::Class> klass = jklass_obj->AsClass();
+  if (klass->IsPrimitive() || klass->IsArrayClass()) {
+    return ERR(INVALID_CLASS);
+  }
+
+  if (minor_version_ptr == nullptr || major_version_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  // Note: proxies will show the dex file version of java.lang.reflect.Proxy, as that is
+  //       what their dex cache copies from.
+  uint32_t version = klass->GetDexFile().GetHeader().GetVersion();
+
+  *major_version_ptr = static_cast<jint>(version);
+  *minor_version_ptr = 0;
+
+  return ERR(NONE);
+}
+
+jvmtiError ClassUtil::GetSourceFileName(jvmtiEnv* env, jclass jklass, char** source_name_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  if (jklass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  art::ObjPtr<art::mirror::Object> jklass_obj = soa.Decode<art::mirror::Object>(jklass);
+  if (!jklass_obj->IsClass()) {
+    return ERR(INVALID_CLASS);
+  }
+  art::ObjPtr<art::mirror::Class> klass = jklass_obj->AsClass();
+  if (klass->IsPrimitive() || klass->IsArrayClass()) {
+    return ERR(ABSENT_INFORMATION);
+  }
+  JvmtiUniquePtr<char[]> source_copy;
+  const char* file_name = klass->GetSourceFile();
+  if (file_name == nullptr) {
+    return ERR(ABSENT_INFORMATION);
+  }
+  jvmtiError ret;
+  source_copy = CopyString(env, file_name, &ret);
+  if (source_copy == nullptr) {
+    return ret;
+  }
+  *source_name_ptr = source_copy.release();
+  return OK;
+}
+
+jvmtiError ClassUtil::GetSourceDebugExtension(jvmtiEnv* env,
+                                              jclass jklass,
+                                              char** source_debug_extension_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  if (jklass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  art::ObjPtr<art::mirror::Object> jklass_obj = soa.Decode<art::mirror::Object>(jklass);
+  if (!jklass_obj->IsClass()) {
+    return ERR(INVALID_CLASS);
+  }
+  art::StackHandleScope<1> hs(art::Thread::Current());
+  art::Handle<art::mirror::Class> klass(hs.NewHandle(jklass_obj->AsClass()));
+  if (klass->IsPrimitive() || klass->IsArrayClass()) {
+    return ERR(ABSENT_INFORMATION);
+  }
+  JvmtiUniquePtr<char[]> ext_copy;
+  const char* data = art::annotations::GetSourceDebugExtension(klass);
+  if (data == nullptr) {
+    return ERR(ABSENT_INFORMATION);
+  }
+  jvmtiError ret;
+  ext_copy = CopyString(env, data, &ret);
+  if (ext_copy == nullptr) {
+    return ret;
+  }
+  *source_debug_extension_ptr = ext_copy.release();
+  return OK;
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_class.h b/openjdkjvmti/ti_class.h
new file mode 100644
index 0000000..dd99e36
--- /dev/null
+++ b/openjdkjvmti/ti_class.h
@@ -0,0 +1,95 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_CLASS_H_
+#define ART_OPENJDKJVMTI_TI_CLASS_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class EventHandler;
+
+class ClassUtil {
+ public:
+  static void Register(EventHandler* event_handler);
+  static void Unregister();
+
+  static jvmtiError GetClassFields(jvmtiEnv* env,
+                                   jclass klass,
+                                   jint* field_count_ptr,
+                                   jfieldID** fields_ptr);
+
+  static jvmtiError GetClassMethods(jvmtiEnv* env,
+                                    jclass klass,
+                                    jint* method_count_ptr,
+                                    jmethodID** methods_ptr);
+
+  static jvmtiError GetImplementedInterfaces(jvmtiEnv* env,
+                                             jclass klass,
+                                             jint* interface_count_ptr,
+                                             jclass** interfaces_ptr);
+
+  static jvmtiError GetClassModifiers(jvmtiEnv* env, jclass klass, jint* modifiers_ptr);
+
+  static jvmtiError GetClassSignature(jvmtiEnv* env,
+                                      jclass klass,
+                                      char** signature_ptr,
+                                      char** generic_ptr);
+
+  static jvmtiError GetClassStatus(jvmtiEnv* env, jclass klass, jint* status_ptr);
+
+  static jvmtiError GetClassLoader(jvmtiEnv* env, jclass klass, jobject* classloader_ptr);
+
+  static jvmtiError GetClassLoaderClasses(jvmtiEnv* env,
+                                          jobject initiating_loader,
+                                          jint* class_count_ptr,
+                                          jclass** classes_ptr);
+
+  static jvmtiError IsInterface(jvmtiEnv* env, jclass klass, jboolean* is_interface_ptr);
+  static jvmtiError IsArrayClass(jvmtiEnv* env, jclass klass, jboolean* is_array_class_ptr);
+
+  static jvmtiError GetClassVersionNumbers(jvmtiEnv* env,
+                                           jclass klass,
+                                           jint* minor_version_ptr,
+                                           jint* major_version_ptr);
+
+  static jvmtiError GetSourceFileName(jvmtiEnv* env, jclass klass, char** source_name_ptr);
+
+  static jvmtiError GetSourceDebugExtension(jvmtiEnv* env,
+                                            jclass klass,
+                                            char** source_debug_extension_ptr);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_CLASS_H_
diff --git a/openjdkjvmti/ti_class_definition.cc b/openjdkjvmti/ti_class_definition.cc
new file mode 100644
index 0000000..c73ef0d
--- /dev/null
+++ b/openjdkjvmti/ti_class_definition.cc
@@ -0,0 +1,179 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_class_definition.h"
+
+#include "base/array_slice.h"
+#include "class_linker-inl.h"
+#include "dex_file.h"
+#include "fixed_up_dex_file.h"
+#include "handle.h"
+#include "handle_scope-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_ext.h"
+#include "mirror/object-inl.h"
+#include "reflection.h"
+#include "thread.h"
+
+namespace openjdkjvmti {
+
+bool ArtClassDefinition::IsModified() const {
+  // RedefineClasses calls always are 'modified' since they need to change the original_dex_file of
+  // the class.
+  if (redefined_) {
+    return true;
+  }
+  // Check if the dex file we want to set is the same as the current one.
+  // Unfortunately we need to do this check even if no modifications have been done since it could
+  // be that agents were removed in the mean-time so we still have a different dex file. The dex
+  // checksum means this is likely to be fairly fast.
+  return static_cast<jint>(original_dex_file_.size()) != dex_len_ ||
+      memcmp(original_dex_file_.data(), dex_data_.get(), dex_len_) != 0;
+}
+
+jvmtiError ArtClassDefinition::InitCommon(ArtJvmTiEnv* env, jclass klass) {
+  JNIEnv* jni_env = GetJniEnv(env);
+  if (jni_env == nullptr) {
+    return ERR(INTERNAL);
+  }
+  art::ScopedObjectAccess soa(jni_env);
+  art::ObjPtr<art::mirror::Class> m_klass(soa.Decode<art::mirror::Class>(klass));
+  if (m_klass.IsNull()) {
+    return ERR(INVALID_CLASS);
+  }
+  klass_ = klass;
+  loader_ = soa.AddLocalReference<jobject>(m_klass->GetClassLoader());
+  std::string descriptor_store;
+  std::string descriptor(m_klass->GetDescriptor(&descriptor_store));
+  name_ = descriptor.substr(1, descriptor.size() - 2);
+  // Android doesn't really have protection domains.
+  protection_domain_ = nullptr;
+  return OK;
+}
+
+// Gets the data surrounding the given class.
+static jvmtiError GetDexDataForRetransformation(ArtJvmTiEnv* env,
+                                                art::Handle<art::mirror::Class> klass,
+                                                /*out*/jint* dex_data_len,
+                                                /*out*/unsigned char** dex_data)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  art::StackHandleScope<3> hs(art::Thread::Current());
+  art::Handle<art::mirror::ClassExt> ext(hs.NewHandle(klass->GetExtData()));
+  const art::DexFile* dex_file = nullptr;
+  if (!ext.IsNull()) {
+    art::Handle<art::mirror::Object> orig_dex(hs.NewHandle(ext->GetOriginalDexFile()));
+    if (!orig_dex.IsNull()) {
+      if (orig_dex->IsArrayInstance()) {
+        DCHECK(orig_dex->GetClass()->GetComponentType()->IsPrimitiveByte());
+        art::Handle<art::mirror::ByteArray> orig_dex_bytes(
+            hs.NewHandle(art::down_cast<art::mirror::ByteArray*>(orig_dex->AsArray())));
+        *dex_data_len = static_cast<jint>(orig_dex_bytes->GetLength());
+        return CopyDataIntoJvmtiBuffer(
+            env,
+            reinterpret_cast<const unsigned char*>(orig_dex_bytes->GetData()),
+            *dex_data_len,
+            /*out*/dex_data);
+      } else if (orig_dex->IsDexCache()) {
+        dex_file = orig_dex->AsDexCache()->GetDexFile();
+      } else {
+        DCHECK(orig_dex->GetClass()->DescriptorEquals("Ljava/lang/Long;"))
+            << "Expected java/lang/Long but found object of type "
+            << orig_dex->GetClass()->PrettyClass();
+        art::ObjPtr<art::mirror::Class> prim_long_class(
+            art::Runtime::Current()->GetClassLinker()->GetClassRoot(
+                art::ClassLinker::kPrimitiveLong));
+        art::JValue val;
+        if (!art::UnboxPrimitiveForResult(orig_dex.Get(), prim_long_class, &val)) {
+          // This should never happen.
+          return ERR(INTERNAL);
+        }
+        dex_file = reinterpret_cast<const art::DexFile*>(static_cast<uintptr_t>(val.GetJ()));
+      }
+    }
+  }
+  if (dex_file == nullptr) {
+    dex_file = &klass->GetDexFile();
+  }
+  std::unique_ptr<FixedUpDexFile> fixed_dex_file(FixedUpDexFile::Create(*dex_file));
+  *dex_data_len = static_cast<jint>(fixed_dex_file->Size());
+  return CopyDataIntoJvmtiBuffer(env,
+                                 fixed_dex_file->Begin(),
+                                 fixed_dex_file->Size(),
+                                 /*out*/dex_data);
+}
+
+jvmtiError ArtClassDefinition::Init(ArtJvmTiEnv* env, jclass klass) {
+  jvmtiError res = InitCommon(env, klass);
+  if (res != OK) {
+    return res;
+  }
+  unsigned char* new_data = nullptr;
+  art::Thread* self = art::Thread::Current();
+  art::ScopedObjectAccess soa(self);
+  art::StackHandleScope<1> hs(self);
+  art::Handle<art::mirror::Class> m_klass(hs.NewHandle(self->DecodeJObject(klass)->AsClass()));
+  res = GetDexDataForRetransformation(env, m_klass, &dex_len_, &new_data);
+  if (res != OK) {
+    return res;
+  }
+  dex_data_ = MakeJvmtiUniquePtr(env, new_data);
+  if (m_klass->GetExtData() == nullptr || m_klass->GetExtData()->GetOriginalDexFile() == nullptr) {
+    // We have never redefined class this yet. Keep track of what the (de-quickened) dex file looks
+    // like so we can tell if anything has changed. Really we would like to just always do the
+    // 'else' block but the fact that we de-quickened stuff screws us over.
+    unsigned char* original_data_memory = nullptr;
+    res = CopyDataIntoJvmtiBuffer(env, dex_data_.get(), dex_len_, &original_data_memory);
+    original_dex_file_memory_ = MakeJvmtiUniquePtr(env, original_data_memory);
+    original_dex_file_ = art::ArrayRef<const unsigned char>(original_data_memory, dex_len_);
+  } else {
+    // We know that we have been redefined at least once (there is an original_dex_file set in
+    // the class) so we can just use the current dex file directly.
+    const art::DexFile& dex_file = m_klass->GetDexFile();
+    original_dex_file_ = art::ArrayRef<const unsigned char>(dex_file.Begin(), dex_file.Size());
+  }
+  return res;
+}
+
+jvmtiError ArtClassDefinition::Init(ArtJvmTiEnv* env, const jvmtiClassDefinition& def) {
+  jvmtiError res = InitCommon(env, def.klass);
+  if (res != OK) {
+    return res;
+  }
+  unsigned char* new_data = nullptr;
+  original_dex_file_ = art::ArrayRef<const unsigned char>(def.class_bytes, def.class_byte_count);
+  redefined_ = true;
+  dex_len_ = def.class_byte_count;
+  res = CopyDataIntoJvmtiBuffer(env, def.class_bytes, def.class_byte_count, /*out*/ &new_data);
+  dex_data_ = MakeJvmtiUniquePtr(env, new_data);
+  return res;
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_class_definition.h b/openjdkjvmti/ti_class_definition.h
new file mode 100644
index 0000000..accc456
--- /dev/null
+++ b/openjdkjvmti/ti_class_definition.h
@@ -0,0 +1,131 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_CLASS_DEFINITION_H_
+#define ART_OPENJDKJVMTI_TI_CLASS_DEFINITION_H_
+
+#include "art_jvmti.h"
+
+#include "base/array_ref.h"
+
+namespace openjdkjvmti {
+
+// A struct that stores data needed for redefining/transforming classes. This structure should only
+// even be accessed from a single thread and must not survive past the completion of the
+// redefinition/retransformation function that created it.
+class ArtClassDefinition {
+ public:
+  ArtClassDefinition()
+      : klass_(nullptr),
+        loader_(nullptr),
+        name_(),
+        protection_domain_(nullptr),
+        dex_len_(0),
+        dex_data_(nullptr),
+        original_dex_file_memory_(nullptr),
+        original_dex_file_(),
+        redefined_(false) {}
+
+  jvmtiError Init(ArtJvmTiEnv* env, jclass klass);
+  jvmtiError Init(ArtJvmTiEnv* env, const jvmtiClassDefinition& def);
+
+  ArtClassDefinition(ArtClassDefinition&& o) = default;
+  ArtClassDefinition& operator=(ArtClassDefinition&& o) = default;
+
+  void SetNewDexData(ArtJvmTiEnv* env, jint new_dex_len, unsigned char* new_dex_data) {
+    DCHECK(IsInitialized());
+    if (new_dex_data == nullptr) {
+      return;
+    } else if (new_dex_data != dex_data_.get() || new_dex_len != dex_len_) {
+      dex_len_ = new_dex_len;
+      dex_data_ = MakeJvmtiUniquePtr(env, new_dex_data);
+    }
+  }
+
+  art::ArrayRef<const unsigned char> GetNewOriginalDexFile() const {
+    DCHECK(IsInitialized());
+    if (redefined_) {
+      return original_dex_file_;
+    } else {
+      return art::ArrayRef<const unsigned char>();
+    }
+  }
+
+  bool IsModified() const;
+
+  bool IsInitialized() const {
+    return klass_ != nullptr;
+  }
+
+  jclass GetClass() const {
+    DCHECK(IsInitialized());
+    return klass_;
+  }
+
+  jobject GetLoader() const {
+    DCHECK(IsInitialized());
+    return loader_;
+  }
+
+  const std::string& GetName() const {
+    DCHECK(IsInitialized());
+    return name_;
+  }
+
+  jobject GetProtectionDomain() const {
+    DCHECK(IsInitialized());
+    return protection_domain_;
+  }
+
+  art::ArrayRef<const unsigned char> GetDexData() const {
+    DCHECK(IsInitialized());
+    return art::ArrayRef<const unsigned char>(dex_data_.get(), dex_len_);
+  }
+
+ private:
+  jvmtiError InitCommon(ArtJvmTiEnv* env, jclass klass);
+
+  jclass klass_;
+  jobject loader_;
+  std::string name_;
+  jobject protection_domain_;
+  jint dex_len_;
+  JvmtiUniquePtr<unsigned char> dex_data_;
+  JvmtiUniquePtr<unsigned char> original_dex_file_memory_;
+  art::ArrayRef<const unsigned char> original_dex_file_;
+  bool redefined_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArtClassDefinition);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_CLASS_DEFINITION_H_
diff --git a/openjdkjvmti/ti_class_loader.cc b/openjdkjvmti/ti_class_loader.cc
new file mode 100644
index 0000000..e81e4bc
--- /dev/null
+++ b/openjdkjvmti/ti_class_loader.cc
@@ -0,0 +1,207 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_class_loader.h"
+
+#include <limits>
+
+#include "android-base/stringprintf.h"
+
+#include "art_field-inl.h"
+#include "art_jvmti.h"
+#include "base/logging.h"
+#include "dex_file.h"
+#include "dex_file_types.h"
+#include "events-inl.h"
+#include "gc/allocation_listener.h"
+#include "gc/heap.h"
+#include "instrumentation.h"
+#include "jit/jit.h"
+#include "jit/jit_code_cache.h"
+#include "jni_env_ext-inl.h"
+#include "jvmti_allocator.h"
+#include "mirror/class.h"
+#include "mirror/class_ext.h"
+#include "mirror/object.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "object_lock.h"
+#include "runtime.h"
+#include "transform.h"
+
+namespace openjdkjvmti {
+
+bool ClassLoaderHelper::AddToClassLoader(art::Thread* self,
+                                         art::Handle<art::mirror::ClassLoader> loader,
+                                         const art::DexFile* dex_file) {
+  art::ScopedObjectAccessUnchecked soa(self);
+  art::StackHandleScope<3> hs(self);
+  if (art::ClassLinker::IsBootClassLoader(soa, loader.Get())) {
+    art::Runtime::Current()->GetClassLinker()->AppendToBootClassPath(self, *dex_file);
+    return true;
+  }
+  art::Handle<art::mirror::Object> java_dex_file_obj(
+      hs.NewHandle(FindSourceDexFileObject(self, loader)));
+  if (java_dex_file_obj.IsNull()) {
+    return false;
+  }
+  art::Handle<art::mirror::LongArray> old_cookie(hs.NewHandle(GetDexFileCookie(java_dex_file_obj)));
+  art::Handle<art::mirror::LongArray> cookie(hs.NewHandle(
+      AllocateNewDexFileCookie(self, old_cookie, dex_file)));
+  if (cookie.IsNull()) {
+    return false;
+  }
+  art::ScopedAssertNoThreadSuspension nts("Replacing cookie fields in j.l.DexFile object");
+  UpdateJavaDexFile(java_dex_file_obj.Get(), cookie.Get());
+  return true;
+}
+
+void ClassLoaderHelper::UpdateJavaDexFile(art::ObjPtr<art::mirror::Object> java_dex_file,
+                                          art::ObjPtr<art::mirror::LongArray> new_cookie) {
+  art::ArtField* internal_cookie_field = java_dex_file->GetClass()->FindDeclaredInstanceField(
+      "mInternalCookie", "Ljava/lang/Object;");
+  art::ArtField* cookie_field = java_dex_file->GetClass()->FindDeclaredInstanceField(
+      "mCookie", "Ljava/lang/Object;");
+  CHECK(internal_cookie_field != nullptr);
+  art::ObjPtr<art::mirror::LongArray> orig_internal_cookie(
+      internal_cookie_field->GetObject(java_dex_file)->AsLongArray());
+  art::ObjPtr<art::mirror::LongArray> orig_cookie(
+      cookie_field->GetObject(java_dex_file)->AsLongArray());
+  internal_cookie_field->SetObject<false>(java_dex_file, new_cookie);
+  if (!orig_cookie.IsNull()) {
+    cookie_field->SetObject<false>(java_dex_file, new_cookie);
+  }
+}
+
+art::ObjPtr<art::mirror::LongArray> ClassLoaderHelper::GetDexFileCookie(
+    art::Handle<art::mirror::Object> java_dex_file_obj) {
+  // mCookie is nulled out if the DexFile has been closed but mInternalCookie sticks around until
+  // the object is finalized. Since they always point to the same array if mCookie is not null we
+  // just use the mInternalCookie field. We will update one or both of these fields later.
+  art::ArtField* internal_cookie_field = java_dex_file_obj->GetClass()->FindDeclaredInstanceField(
+      "mInternalCookie", "Ljava/lang/Object;");
+  // TODO Add check that mCookie is either null or same as mInternalCookie
+  CHECK(internal_cookie_field != nullptr);
+  return internal_cookie_field->GetObject(java_dex_file_obj.Get())->AsLongArray();
+}
+
+art::ObjPtr<art::mirror::LongArray> ClassLoaderHelper::AllocateNewDexFileCookie(
+    art::Thread* self,
+    art::Handle<art::mirror::LongArray> cookie,
+    const art::DexFile* dex_file) {
+  art::StackHandleScope<1> hs(self);
+  CHECK(cookie != nullptr);
+  CHECK_GE(cookie->GetLength(), 1);
+  art::Handle<art::mirror::LongArray> new_cookie(
+      hs.NewHandle(art::mirror::LongArray::Alloc(self, cookie->GetLength() + 1)));
+  if (new_cookie == nullptr) {
+    self->AssertPendingOOMException();
+    return nullptr;
+  }
+  // Copy the oat-dex field at the start.
+  new_cookie->SetWithoutChecks<false>(0, cookie->GetWithoutChecks(0));
+  // This must match the casts in runtime/native/dalvik_system_DexFile.cc:ConvertDexFilesToJavaArray
+  new_cookie->SetWithoutChecks<false>(
+      1, static_cast<int64_t>(reinterpret_cast<uintptr_t>(dex_file)));
+  new_cookie->Memcpy(2, cookie.Get(), 1, cookie->GetLength() - 1);
+  return new_cookie.Get();
+}
+
+// TODO This should return the actual source java.lang.DexFile object for the klass being loaded.
+art::ObjPtr<art::mirror::Object> ClassLoaderHelper::FindSourceDexFileObject(
+    art::Thread* self, art::Handle<art::mirror::ClassLoader> loader) {
+  const char* dex_path_list_element_array_name = "[Ldalvik/system/DexPathList$Element;";
+  const char* dex_path_list_element_name = "Ldalvik/system/DexPathList$Element;";
+  const char* dex_file_name = "Ldalvik/system/DexFile;";
+  const char* dex_path_list_name = "Ldalvik/system/DexPathList;";
+  const char* dex_class_loader_name = "Ldalvik/system/BaseDexClassLoader;";
+
+  CHECK(!self->IsExceptionPending());
+  art::StackHandleScope<5> hs(self);
+  art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
+
+  art::Handle<art::mirror::ClassLoader> null_loader(hs.NewHandle<art::mirror::ClassLoader>(
+      nullptr));
+  art::Handle<art::mirror::Class> base_dex_loader_class(hs.NewHandle(class_linker->FindClass(
+      self, dex_class_loader_name, null_loader)));
+
+  // Get all the ArtFields so we can look in the BaseDexClassLoader
+  art::ArtField* path_list_field = base_dex_loader_class->FindDeclaredInstanceField(
+      "pathList", dex_path_list_name);
+  CHECK(path_list_field != nullptr);
+
+  art::ArtField* dex_path_list_element_field =
+      class_linker->FindClass(self, dex_path_list_name, null_loader)
+        ->FindDeclaredInstanceField("dexElements", dex_path_list_element_array_name);
+  CHECK(dex_path_list_element_field != nullptr);
+
+  art::ArtField* element_dex_file_field =
+      class_linker->FindClass(self, dex_path_list_element_name, null_loader)
+        ->FindDeclaredInstanceField("dexFile", dex_file_name);
+  CHECK(element_dex_file_field != nullptr);
+
+  // Check if loader is a BaseDexClassLoader
+  art::Handle<art::mirror::Class> loader_class(hs.NewHandle(loader->GetClass()));
+  // Currently only base_dex_loader is allowed to actually define classes but if this changes in the
+  // future we should make sure to support all class loader types.
+  if (!loader_class->IsSubClass(base_dex_loader_class.Get())) {
+    LOG(ERROR) << "The classloader is not a BaseDexClassLoader which is currently the only "
+               << "supported class loader type!";
+    return nullptr;
+  }
+  // Start navigating the fields of the loader (now known to be a BaseDexClassLoader derivative)
+  art::Handle<art::mirror::Object> path_list(
+      hs.NewHandle(path_list_field->GetObject(loader.Get())));
+  CHECK(path_list != nullptr);
+  CHECK(!self->IsExceptionPending());
+  art::Handle<art::mirror::ObjectArray<art::mirror::Object>> dex_elements_list(hs.NewHandle(
+      dex_path_list_element_field->GetObject(path_list.Get())->
+      AsObjectArray<art::mirror::Object>()));
+  CHECK(!self->IsExceptionPending());
+  CHECK(dex_elements_list != nullptr);
+  size_t num_elements = dex_elements_list->GetLength();
+  // Iterate over the DexPathList$Element to find the right one
+  for (size_t i = 0; i < num_elements; i++) {
+    art::ObjPtr<art::mirror::Object> current_element = dex_elements_list->Get(i);
+    CHECK(!current_element.IsNull());
+    // TODO It would be cleaner to put the art::DexFile into the dalvik.system.DexFile the class
+    // comes from but it is more annoying because we would need to find this class. It is not
+    // necessary for proper function since we just need to be in front of the classes old dex file
+    // in the path.
+    art::ObjPtr<art::mirror::Object> first_dex_file(
+        element_dex_file_field->GetObject(current_element));
+    if (!first_dex_file.IsNull()) {
+      return first_dex_file;
+    }
+  }
+  return nullptr;
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_class_loader.h b/openjdkjvmti/ti_class_loader.h
new file mode 100644
index 0000000..767e258
--- /dev/null
+++ b/openjdkjvmti/ti_class_loader.h
@@ -0,0 +1,99 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_CLASS_LOADER_H_
+#define ART_OPENJDKJVMTI_TI_CLASS_LOADER_H_
+
+#include <string>
+
+#include <jni.h>
+
+#include "art_jvmti.h"
+#include "art_method.h"
+#include "base/array_slice.h"
+#include "class_linker.h"
+#include "dex_file.h"
+#include "gc_root-inl.h"
+#include "globals.h"
+#include "jni_env_ext-inl.h"
+#include "jvmti.h"
+#include "linear_alloc.h"
+#include "mem_map.h"
+#include "mirror/array-inl.h"
+#include "mirror/array.h"
+#include "mirror/class-inl.h"
+#include "mirror/class.h"
+#include "mirror/class_loader-inl.h"
+#include "mirror/string-inl.h"
+#include "oat_file.h"
+#include "obj_ptr.h"
+#include "scoped_thread_state_change-inl.h"
+#include "stack.h"
+#include "thread_list.h"
+#include "ti_class_definition.h"
+#include "transform.h"
+#include "utf.h"
+#include "utils/dex_cache_arrays_layout-inl.h"
+
+namespace openjdkjvmti {
+
+// Class that can redefine a single class's methods.
+// TODO We should really make this be driven by an outside class so we can do multiple classes at
+// the same time and have less required cleanup.
+class ClassLoaderHelper {
+ public:
+  static bool AddToClassLoader(art::Thread* self,
+                               art::Handle<art::mirror::ClassLoader> loader,
+                               const art::DexFile* dex_file)
+      REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+  // Finds a java.lang.DexFile object that is associated with the given ClassLoader. Each of these
+  // j.l.DexFile objects holds several art::DexFile*s in it.
+  // TODO This should return the actual source java.lang.DexFile object for the klass being loaded.
+  static art::ObjPtr<art::mirror::Object> FindSourceDexFileObject(
+      art::Thread* self, art::Handle<art::mirror::ClassLoader> loader)
+      REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+  static art::ObjPtr<art::mirror::LongArray> GetDexFileCookie(
+      art::Handle<art::mirror::Object> java_dex_file) REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+  static art::ObjPtr<art::mirror::LongArray> AllocateNewDexFileCookie(
+      art::Thread* self,
+      art::Handle<art::mirror::LongArray> old_dex_file_cookie,
+      const art::DexFile* new_dex_file) REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+  static void UpdateJavaDexFile(art::ObjPtr<art::mirror::Object> java_dex_file,
+                                art::ObjPtr<art::mirror::LongArray> new_cookie)
+      REQUIRES(art::Roles::uninterruptible_) REQUIRES_SHARED(art::Locks::mutator_lock_);
+};
+
+}  // namespace openjdkjvmti
+#endif  // ART_OPENJDKJVMTI_TI_CLASS_LOADER_H_
diff --git a/openjdkjvmti/ti_dump.cc b/openjdkjvmti/ti_dump.cc
new file mode 100644
index 0000000..809a5e4
--- /dev/null
+++ b/openjdkjvmti/ti_dump.cc
@@ -0,0 +1,73 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_dump.h"
+
+#include <limits>
+
+#include "art_jvmti.h"
+#include "base/mutex.h"
+#include "events-inl.h"
+#include "runtime_callbacks.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+#include "thread_list.h"
+
+namespace openjdkjvmti {
+
+struct DumpCallback : public art::RuntimeSigQuitCallback {
+  void SigQuit() OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    art::Thread* thread = art::Thread::Current();
+    art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative);
+    event_handler->DispatchEvent<ArtJvmtiEvent::kDataDumpRequest>(nullptr);
+  }
+
+  EventHandler* event_handler = nullptr;
+};
+
+static DumpCallback gDumpCallback;
+
+void DumpUtil::Register(EventHandler* handler) {
+  gDumpCallback.event_handler = handler;
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Add sigquit callback");
+  art::Runtime::Current()->GetRuntimeCallbacks()->AddRuntimeSigQuitCallback(&gDumpCallback);
+}
+
+void DumpUtil::Unregister() {
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Remove sigquit callback");
+  art::Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimeSigQuitCallback(&gDumpCallback);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_dump.h b/openjdkjvmti/ti_dump.h
new file mode 100644
index 0000000..323bf56
--- /dev/null
+++ b/openjdkjvmti/ti_dump.h
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_DUMP_H_
+#define ART_OPENJDKJVMTI_TI_DUMP_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class EventHandler;
+
+class DumpUtil {
+ public:
+  static void Register(EventHandler* event_handler);
+  static void Unregister();
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_DUMP_H_
diff --git a/openjdkjvmti/ti_field.cc b/openjdkjvmti/ti_field.cc
new file mode 100644
index 0000000..c45b926
--- /dev/null
+++ b/openjdkjvmti/ti_field.cc
@@ -0,0 +1,254 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_field.h"
+
+#include "art_field-inl.h"
+#include "art_jvmti.h"
+#include "base/enums.h"
+#include "dex_file_annotations.h"
+#include "jni_internal.h"
+#include "mirror/object_array-inl.h"
+#include "modifiers.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+
+namespace openjdkjvmti {
+
+// Note: For all these functions, we could do a check that the field actually belongs to the given
+//       class. But the spec seems to assume a certain encoding of the field ID, and so doesn't
+//       specify any errors.
+
+jvmtiError FieldUtil::GetFieldName(jvmtiEnv* env,
+                                   jclass klass,
+                                   jfieldID field,
+                                   char** name_ptr,
+                                   char** signature_ptr,
+                                   char** generic_ptr) {
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  if (field == nullptr) {
+    return ERR(INVALID_FIELDID);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ArtField* art_field = art::jni::DecodeArtField(field);
+
+  JvmtiUniquePtr<char[]> name_copy;
+  if (name_ptr != nullptr) {
+    const char* field_name = art_field->GetName();
+    if (field_name == nullptr) {
+      field_name = "<error>";
+    }
+    jvmtiError ret;
+    name_copy = CopyString(env, field_name, &ret);
+    if (name_copy == nullptr) {
+      return ret;
+    }
+    *name_ptr = name_copy.get();
+  }
+
+  JvmtiUniquePtr<char[]> signature_copy;
+  if (signature_ptr != nullptr) {
+    const char* sig = art_field->GetTypeDescriptor();
+    jvmtiError ret;
+    signature_copy = CopyString(env, sig, &ret);
+    if (signature_copy == nullptr) {
+      return ret;
+    }
+    *signature_ptr = signature_copy.get();
+  }
+
+  if (generic_ptr != nullptr) {
+    *generic_ptr = nullptr;
+    if (!art_field->GetDeclaringClass()->IsProxyClass()) {
+      art::mirror::ObjectArray<art::mirror::String>* str_array =
+          art::annotations::GetSignatureAnnotationForField(art_field);
+      if (str_array != nullptr) {
+        std::ostringstream oss;
+        for (int32_t i = 0; i != str_array->GetLength(); ++i) {
+          oss << str_array->Get(i)->ToModifiedUtf8();
+        }
+        std::string output_string = oss.str();
+        jvmtiError ret;
+        JvmtiUniquePtr<char[]> copy = CopyString(env, output_string.c_str(), &ret);
+        if (copy == nullptr) {
+          return ret;
+        }
+        *generic_ptr = copy.release();
+      } else if (soa.Self()->IsExceptionPending()) {
+        // TODO: Should we report an error here?
+        soa.Self()->ClearException();
+      }
+    }
+  }
+
+  // Everything is fine, release the buffers.
+  name_copy.release();
+  signature_copy.release();
+
+  return ERR(NONE);
+}
+
+jvmtiError FieldUtil::GetFieldDeclaringClass(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                             jclass klass,
+                                             jfieldID field,
+                                             jclass* declaring_class_ptr) {
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  if (field == nullptr) {
+    return ERR(INVALID_FIELDID);
+  }
+  if (declaring_class_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ArtField* art_field = art::jni::DecodeArtField(field);
+  art::ObjPtr<art::mirror::Class> field_klass = art_field->GetDeclaringClass();
+
+  *declaring_class_ptr = soa.AddLocalReference<jclass>(field_klass);
+
+  return ERR(NONE);
+}
+
+jvmtiError FieldUtil::GetFieldModifiers(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                        jclass klass,
+                                        jfieldID field,
+                                        jint* modifiers_ptr) {
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  if (field == nullptr) {
+    return ERR(INVALID_FIELDID);
+  }
+  if (modifiers_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ArtField* art_field = art::jni::DecodeArtField(field);
+  // Note: Keep this code in sync with Field.getModifiers.
+  uint32_t modifiers = art_field->GetAccessFlags() & 0xFFFF;
+
+  *modifiers_ptr = modifiers;
+  return ERR(NONE);
+}
+
+jvmtiError FieldUtil::IsFieldSynthetic(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                       jclass klass,
+                                       jfieldID field,
+                                       jboolean* is_synthetic_ptr) {
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  if (field == nullptr) {
+    return ERR(INVALID_FIELDID);
+  }
+  if (is_synthetic_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ArtField* art_field = art::jni::DecodeArtField(field);
+  uint32_t modifiers = art_field->GetAccessFlags();
+
+  *is_synthetic_ptr = ((modifiers & art::kAccSynthetic) != 0) ? JNI_TRUE : JNI_FALSE;
+  return ERR(NONE);
+}
+
+jvmtiError FieldUtil::SetFieldModificationWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) {
+  ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  if (field == nullptr) {
+    return ERR(INVALID_FIELDID);
+  }
+  auto res_pair = env->modify_watched_fields.insert(art::jni::DecodeArtField(field));
+  if (!res_pair.second) {
+    // Didn't get inserted because it's already present!
+    return ERR(DUPLICATE);
+  }
+  return OK;
+}
+
+jvmtiError FieldUtil::ClearFieldModificationWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) {
+  ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  if (field == nullptr) {
+    return ERR(INVALID_FIELDID);
+  }
+  auto pos = env->modify_watched_fields.find(art::jni::DecodeArtField(field));
+  if (pos == env->modify_watched_fields.end()) {
+    return ERR(NOT_FOUND);
+  }
+  env->modify_watched_fields.erase(pos);
+  return OK;
+}
+
+jvmtiError FieldUtil::SetFieldAccessWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) {
+  ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  if (field == nullptr) {
+    return ERR(INVALID_FIELDID);
+  }
+  auto res_pair = env->access_watched_fields.insert(art::jni::DecodeArtField(field));
+  if (!res_pair.second) {
+    // Didn't get inserted because it's already present!
+    return ERR(DUPLICATE);
+  }
+  return OK;
+}
+
+jvmtiError FieldUtil::ClearFieldAccessWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) {
+  ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
+  if (klass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  if (field == nullptr) {
+    return ERR(INVALID_FIELDID);
+  }
+  auto pos = env->access_watched_fields.find(art::jni::DecodeArtField(field));
+  if (pos == env->access_watched_fields.end()) {
+    return ERR(NOT_FOUND);
+  }
+  env->access_watched_fields.erase(pos);
+  return OK;
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_field.h b/openjdkjvmti/ti_field.h
new file mode 100644
index 0000000..8a229ed
--- /dev/null
+++ b/openjdkjvmti/ti_field.h
@@ -0,0 +1,72 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_FIELD_H_
+#define ART_OPENJDKJVMTI_TI_FIELD_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class FieldUtil {
+ public:
+  static jvmtiError GetFieldName(jvmtiEnv* env,
+                                 jclass klass,
+                                 jfieldID field,
+                                 char** name_ptr,
+                                 char** signature_ptr,
+                                 char** generic_ptr);
+
+  static jvmtiError GetFieldDeclaringClass(jvmtiEnv* env,
+                                           jclass klass,
+                                           jfieldID field,
+                                           jclass* declaring_class_ptr);
+
+  static jvmtiError GetFieldModifiers(jvmtiEnv* env,
+                                      jclass klass,
+                                      jfieldID field,
+                                      jint* modifiers_ptr);
+
+  static jvmtiError IsFieldSynthetic(jvmtiEnv* env,
+                                     jclass klass,
+                                     jfieldID field,
+                                     jboolean* is_synthetic_ptr);
+
+  static jvmtiError SetFieldModificationWatch(jvmtiEnv* env, jclass klass, jfieldID field);
+  static jvmtiError ClearFieldModificationWatch(jvmtiEnv* env, jclass klass, jfieldID field);
+  static jvmtiError SetFieldAccessWatch(jvmtiEnv* env, jclass klass, jfieldID field);
+  static jvmtiError ClearFieldAccessWatch(jvmtiEnv* env, jclass klass, jfieldID field);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_FIELD_H_
diff --git a/openjdkjvmti/ti_heap.cc b/openjdkjvmti/ti_heap.cc
new file mode 100644
index 0000000..3397210
--- /dev/null
+++ b/openjdkjvmti/ti_heap.cc
@@ -0,0 +1,1522 @@
+/*
+ * Copyright (C) 2016 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 "ti_heap.h"
+
+#include "art_field-inl.h"
+#include "art_jvmti.h"
+#include "base/macros.h"
+#include "base/mutex.h"
+#include "class_linker.h"
+#include "gc/heap-visit-objects-inl.h"
+#include "gc/heap.h"
+#include "gc_root-inl.h"
+#include "java_frame_root_info.h"
+#include "jni_env_ext.h"
+#include "jni_internal.h"
+#include "jvmti_weak_table-inl.h"
+#include "mirror/class.h"
+#include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "obj_ptr-inl.h"
+#include "object_tagging.h"
+#include "primitive.h"
+#include "runtime.h"
+#include "scoped_thread_state_change-inl.h"
+#include "stack.h"
+#include "thread-inl.h"
+#include "thread_list.h"
+
+namespace openjdkjvmti {
+
+namespace {
+
+struct IndexCache {
+  // The number of interface fields implemented by the class. This is a prefix to all assigned
+  // field indices.
+  size_t interface_fields;
+
+  // It would be nice to also cache the following, but it is complicated to wire up into the
+  // generic visit:
+  // The number of fields in interfaces and superclasses. This is the first index assigned to
+  // fields of the class.
+  // size_t superclass_fields;
+};
+using IndexCachingTable = JvmtiWeakTable<IndexCache>;
+
+static IndexCachingTable gIndexCachingTable;
+
+// Report the contents of a string, if a callback is set.
+jint ReportString(art::ObjPtr<art::mirror::Object> obj,
+                  jvmtiEnv* env,
+                  ObjectTagTable* tag_table,
+                  const jvmtiHeapCallbacks* cb,
+                  const void* user_data) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  if (UNLIKELY(cb->string_primitive_value_callback != nullptr) && obj->IsString()) {
+    art::ObjPtr<art::mirror::String> str = obj->AsString();
+    int32_t string_length = str->GetLength();
+    JvmtiUniquePtr<uint16_t[]> data;
+
+    if (string_length > 0) {
+      jvmtiError alloc_error;
+      data = AllocJvmtiUniquePtr<uint16_t[]>(env, string_length, &alloc_error);
+      if (data == nullptr) {
+        // TODO: Not really sure what to do here. Should we abort the iteration and go all the way
+        //       back? For now just warn.
+        LOG(WARNING) << "Unable to allocate buffer for string reporting! Silently dropping value."
+                     << " >" << str->ToModifiedUtf8() << "<";
+        return 0;
+      }
+
+      if (str->IsCompressed()) {
+        uint8_t* compressed_data = str->GetValueCompressed();
+        for (int32_t i = 0; i != string_length; ++i) {
+          data[i] = compressed_data[i];
+        }
+      } else {
+        // Can copy directly.
+        memcpy(data.get(), str->GetValue(), string_length * sizeof(uint16_t));
+      }
+    }
+
+    const jlong class_tag = tag_table->GetTagOrZero(obj->GetClass());
+    jlong string_tag = tag_table->GetTagOrZero(obj.Ptr());
+    const jlong saved_string_tag = string_tag;
+
+    jint result = cb->string_primitive_value_callback(class_tag,
+                                                      obj->SizeOf(),
+                                                      &string_tag,
+                                                      data.get(),
+                                                      string_length,
+                                                      const_cast<void*>(user_data));
+    if (string_tag != saved_string_tag) {
+      tag_table->Set(obj.Ptr(), string_tag);
+    }
+
+    return result;
+  }
+  return 0;
+}
+
+// Report the contents of a primitive array, if a callback is set.
+jint ReportPrimitiveArray(art::ObjPtr<art::mirror::Object> obj,
+                          jvmtiEnv* env,
+                          ObjectTagTable* tag_table,
+                          const jvmtiHeapCallbacks* cb,
+                          const void* user_data) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  if (UNLIKELY(cb->array_primitive_value_callback != nullptr) &&
+      obj->IsArrayInstance() &&
+      !obj->IsObjectArray()) {
+    art::ObjPtr<art::mirror::Array> array = obj->AsArray();
+    int32_t array_length = array->GetLength();
+    size_t component_size = array->GetClass()->GetComponentSize();
+    art::Primitive::Type art_prim_type = array->GetClass()->GetComponentType()->GetPrimitiveType();
+    jvmtiPrimitiveType prim_type =
+        static_cast<jvmtiPrimitiveType>(art::Primitive::Descriptor(art_prim_type)[0]);
+    DCHECK(prim_type == JVMTI_PRIMITIVE_TYPE_BOOLEAN ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_BYTE ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_CHAR ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_SHORT ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_INT ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_LONG ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_FLOAT ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_DOUBLE);
+
+    const jlong class_tag = tag_table->GetTagOrZero(obj->GetClass());
+    jlong array_tag = tag_table->GetTagOrZero(obj.Ptr());
+    const jlong saved_array_tag = array_tag;
+
+    jint result;
+    if (array_length == 0) {
+      result = cb->array_primitive_value_callback(class_tag,
+                                                  obj->SizeOf(),
+                                                  &array_tag,
+                                                  0,
+                                                  prim_type,
+                                                  nullptr,
+                                                  const_cast<void*>(user_data));
+    } else {
+      jvmtiError alloc_error;
+      JvmtiUniquePtr<char[]> data = AllocJvmtiUniquePtr<char[]>(env,
+                                                                array_length * component_size,
+                                                                &alloc_error);
+      if (data == nullptr) {
+        // TODO: Not really sure what to do here. Should we abort the iteration and go all the way
+        //       back? For now just warn.
+        LOG(WARNING) << "Unable to allocate buffer for array reporting! Silently dropping value.";
+        return 0;
+      }
+
+      memcpy(data.get(), array->GetRawData(component_size, 0), array_length * component_size);
+
+      result = cb->array_primitive_value_callback(class_tag,
+                                                  obj->SizeOf(),
+                                                  &array_tag,
+                                                  array_length,
+                                                  prim_type,
+                                                  data.get(),
+                                                  const_cast<void*>(user_data));
+    }
+
+    if (array_tag != saved_array_tag) {
+      tag_table->Set(obj.Ptr(), array_tag);
+    }
+
+    return result;
+  }
+  return 0;
+}
+
+template <typename UserData>
+bool VisitorFalse(art::ObjPtr<art::mirror::Object> obj ATTRIBUTE_UNUSED,
+                  art::ObjPtr<art::mirror::Class> klass ATTRIBUTE_UNUSED,
+                  art::ArtField& field ATTRIBUTE_UNUSED,
+                  size_t field_index ATTRIBUTE_UNUSED,
+                  UserData* user_data ATTRIBUTE_UNUSED) {
+  return false;
+}
+
+template <typename UserData, bool kCallVisitorOnRecursion>
+class FieldVisitor {
+ public:
+  // Report the contents of a primitive fields of the given object, if a callback is set.
+  template <typename StaticPrimitiveVisitor,
+            typename StaticReferenceVisitor,
+            typename InstancePrimitiveVisitor,
+            typename InstanceReferenceVisitor>
+  static bool ReportFields(art::ObjPtr<art::mirror::Object> obj,
+                           UserData* user_data,
+                           StaticPrimitiveVisitor& static_prim_visitor,
+                           StaticReferenceVisitor& static_ref_visitor,
+                           InstancePrimitiveVisitor& instance_prim_visitor,
+                           InstanceReferenceVisitor& instance_ref_visitor)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    FieldVisitor fv(user_data);
+
+    if (obj->IsClass()) {
+      // When visiting a class, we only visit the static fields of the given class. No field of
+      // superclasses is visited.
+      art::ObjPtr<art::mirror::Class> klass = obj->AsClass();
+      // Only report fields on resolved classes. We need valid field data.
+      if (!klass->IsResolved()) {
+        return false;
+      }
+      return fv.ReportFieldsImpl(nullptr,
+                                 obj->AsClass(),
+                                 obj->AsClass()->IsInterface(),
+                                 static_prim_visitor,
+                                 static_ref_visitor,
+                                 instance_prim_visitor,
+                                 instance_ref_visitor);
+    } else {
+      // See comment above. Just double-checking here, but an instance *should* mean the class was
+      // resolved.
+      DCHECK(obj->GetClass()->IsResolved() || obj->GetClass()->IsErroneousResolved());
+      return fv.ReportFieldsImpl(obj,
+                                 obj->GetClass(),
+                                 false,
+                                 static_prim_visitor,
+                                 static_ref_visitor,
+                                 instance_prim_visitor,
+                                 instance_ref_visitor);
+    }
+  }
+
+ private:
+  explicit FieldVisitor(UserData* user_data) : user_data_(user_data) {}
+
+  // Report the contents of fields of the given object. If obj is null, report the static fields,
+  // otherwise the instance fields.
+  template <typename StaticPrimitiveVisitor,
+            typename StaticReferenceVisitor,
+            typename InstancePrimitiveVisitor,
+            typename InstanceReferenceVisitor>
+  bool ReportFieldsImpl(art::ObjPtr<art::mirror::Object> obj,
+                        art::ObjPtr<art::mirror::Class> klass,
+                        bool skip_java_lang_object,
+                        StaticPrimitiveVisitor& static_prim_visitor,
+                        StaticReferenceVisitor& static_ref_visitor,
+                        InstancePrimitiveVisitor& instance_prim_visitor,
+                        InstanceReferenceVisitor& instance_ref_visitor)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    // Compute the offset of field indices.
+    size_t interface_field_count = CountInterfaceFields(klass);
+
+    size_t tmp;
+    bool aborted = ReportFieldsRecursive(obj,
+                                         klass,
+                                         interface_field_count,
+                                         skip_java_lang_object,
+                                         static_prim_visitor,
+                                         static_ref_visitor,
+                                         instance_prim_visitor,
+                                         instance_ref_visitor,
+                                         &tmp);
+    return aborted;
+  }
+
+  // Visit primitive fields in an object (instance). Return true if the visit was aborted.
+  template <typename StaticPrimitiveVisitor,
+            typename StaticReferenceVisitor,
+            typename InstancePrimitiveVisitor,
+            typename InstanceReferenceVisitor>
+  bool ReportFieldsRecursive(art::ObjPtr<art::mirror::Object> obj,
+                             art::ObjPtr<art::mirror::Class> klass,
+                             size_t interface_fields,
+                             bool skip_java_lang_object,
+                             StaticPrimitiveVisitor& static_prim_visitor,
+                             StaticReferenceVisitor& static_ref_visitor,
+                             InstancePrimitiveVisitor& instance_prim_visitor,
+                             InstanceReferenceVisitor& instance_ref_visitor,
+                             size_t* field_index_out)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    DCHECK(klass != nullptr);
+    size_t field_index;
+    if (klass->GetSuperClass() == nullptr) {
+      // j.l.Object. Start with the fields from interfaces.
+      field_index = interface_fields;
+      if (skip_java_lang_object) {
+        *field_index_out = field_index;
+        return false;
+      }
+    } else {
+      // Report superclass fields.
+      if (kCallVisitorOnRecursion) {
+        if (ReportFieldsRecursive(obj,
+                                  klass->GetSuperClass(),
+                                  interface_fields,
+                                  skip_java_lang_object,
+                                  static_prim_visitor,
+                                  static_ref_visitor,
+                                  instance_prim_visitor,
+                                  instance_ref_visitor,
+                                  &field_index)) {
+          return true;
+        }
+      } else {
+        // Still call, but with empty visitor. This is required for correct counting.
+        ReportFieldsRecursive(obj,
+                              klass->GetSuperClass(),
+                              interface_fields,
+                              skip_java_lang_object,
+                              VisitorFalse<UserData>,
+                              VisitorFalse<UserData>,
+                              VisitorFalse<UserData>,
+                              VisitorFalse<UserData>,
+                              &field_index);
+      }
+    }
+
+    // Now visit fields for the current klass.
+
+    for (auto& static_field : klass->GetSFields()) {
+      if (static_field.IsPrimitiveType()) {
+        if (static_prim_visitor(obj,
+                                klass,
+                                static_field,
+                                field_index,
+                                user_data_)) {
+          return true;
+        }
+      } else {
+        if (static_ref_visitor(obj,
+                               klass,
+                               static_field,
+                               field_index,
+                               user_data_)) {
+          return true;
+        }
+      }
+      field_index++;
+    }
+
+    for (auto& instance_field : klass->GetIFields()) {
+      if (instance_field.IsPrimitiveType()) {
+        if (instance_prim_visitor(obj,
+                                  klass,
+                                  instance_field,
+                                  field_index,
+                                  user_data_)) {
+          return true;
+        }
+      } else {
+        if (instance_ref_visitor(obj,
+                                 klass,
+                                 instance_field,
+                                 field_index,
+                                 user_data_)) {
+          return true;
+        }
+      }
+      field_index++;
+    }
+
+    *field_index_out = field_index;
+    return false;
+  }
+
+  // Implements a visit of the implemented interfaces of a given class.
+  template <typename T>
+  struct RecursiveInterfaceVisit {
+    static void VisitStatic(art::Thread* self, art::ObjPtr<art::mirror::Class> klass, T& visitor)
+        REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      RecursiveInterfaceVisit rv;
+      rv.Visit(self, klass, visitor);
+    }
+
+    void Visit(art::Thread* self, art::ObjPtr<art::mirror::Class> klass, T& visitor)
+        REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      // First visit the parent, to get the order right.
+      // (We do this in preparation for actual visiting of interface fields.)
+      if (klass->GetSuperClass() != nullptr) {
+        Visit(self, klass->GetSuperClass(), visitor);
+      }
+      for (uint32_t i = 0; i != klass->NumDirectInterfaces(); ++i) {
+        art::ObjPtr<art::mirror::Class> inf_klass =
+            art::mirror::Class::GetDirectInterface(self, klass, i);
+        DCHECK(inf_klass != nullptr);
+        VisitInterface(self, inf_klass, visitor);
+      }
+    }
+
+    void VisitInterface(art::Thread* self, art::ObjPtr<art::mirror::Class> inf_klass, T& visitor)
+        REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      auto it = visited_interfaces.find(inf_klass.Ptr());
+      if (it != visited_interfaces.end()) {
+        return;
+      }
+      visited_interfaces.insert(inf_klass.Ptr());
+
+      // Let the visitor know about this one. Note that this order is acceptable, as the ordering
+      // of these fields never matters for known visitors.
+      visitor(inf_klass);
+
+      // Now visit the superinterfaces.
+      for (uint32_t i = 0; i != inf_klass->NumDirectInterfaces(); ++i) {
+        art::ObjPtr<art::mirror::Class> super_inf_klass =
+            art::mirror::Class::GetDirectInterface(self, inf_klass, i);
+        DCHECK(super_inf_klass != nullptr);
+        VisitInterface(self, super_inf_klass, visitor);
+      }
+    }
+
+    std::unordered_set<art::mirror::Class*> visited_interfaces;
+  };
+
+  // Counting interface fields. Note that we cannot use the interface table, as that only contains
+  // "non-marker" interfaces (= interfaces with methods).
+  static size_t CountInterfaceFields(art::ObjPtr<art::mirror::Class> klass)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    // Do we have a cached value?
+    IndexCache tmp;
+    if (gIndexCachingTable.GetTag(klass.Ptr(), &tmp)) {
+      return tmp.interface_fields;
+    }
+
+    size_t count = 0;
+    auto visitor = [&count](art::ObjPtr<art::mirror::Class> inf_klass)
+        REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      DCHECK(inf_klass->IsInterface());
+      DCHECK_EQ(0u, inf_klass->NumInstanceFields());
+      count += inf_klass->NumStaticFields();
+    };
+    RecursiveInterfaceVisit<decltype(visitor)>::VisitStatic(art::Thread::Current(), klass, visitor);
+
+    // Store this into the cache.
+    tmp.interface_fields = count;
+    gIndexCachingTable.Set(klass.Ptr(), tmp);
+
+    return count;
+  }
+
+  UserData* user_data_;
+};
+
+// Debug helper. Prints the structure of an object.
+template <bool kStatic, bool kRef>
+struct DumpVisitor {
+  static bool Callback(art::ObjPtr<art::mirror::Object> obj ATTRIBUTE_UNUSED,
+                       art::ObjPtr<art::mirror::Class> klass ATTRIBUTE_UNUSED,
+                       art::ArtField& field,
+                       size_t field_index,
+                       void* user_data ATTRIBUTE_UNUSED)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    LOG(ERROR) << (kStatic ? "static " : "instance ")
+               << (kRef ? "ref " : "primitive ")
+               << field.PrettyField()
+               << " @ "
+               << field_index;
+    return false;
+  }
+};
+ATTRIBUTE_UNUSED
+void DumpObjectFields(art::ObjPtr<art::mirror::Object> obj)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  if (obj->IsClass()) {
+    FieldVisitor<void, false>:: ReportFields(obj,
+                                             nullptr,
+                                             DumpVisitor<true, false>::Callback,
+                                             DumpVisitor<true, true>::Callback,
+                                             DumpVisitor<false, false>::Callback,
+                                             DumpVisitor<false, true>::Callback);
+  } else {
+    FieldVisitor<void, true>::ReportFields(obj,
+                                           nullptr,
+                                           DumpVisitor<true, false>::Callback,
+                                           DumpVisitor<true, true>::Callback,
+                                           DumpVisitor<false, false>::Callback,
+                                           DumpVisitor<false, true>::Callback);
+  }
+}
+
+class ReportPrimitiveField {
+ public:
+  static bool Report(art::ObjPtr<art::mirror::Object> obj,
+                     ObjectTagTable* tag_table,
+                     const jvmtiHeapCallbacks* cb,
+                     const void* user_data)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    if (UNLIKELY(cb->primitive_field_callback != nullptr)) {
+      jlong class_tag = tag_table->GetTagOrZero(obj->GetClass());
+      ReportPrimitiveField rpf(tag_table, class_tag, cb, user_data);
+      if (obj->IsClass()) {
+        return FieldVisitor<ReportPrimitiveField, false>::ReportFields(
+            obj,
+            &rpf,
+            ReportPrimitiveFieldCallback<true>,
+            VisitorFalse<ReportPrimitiveField>,
+            VisitorFalse<ReportPrimitiveField>,
+            VisitorFalse<ReportPrimitiveField>);
+      } else {
+        return FieldVisitor<ReportPrimitiveField, true>::ReportFields(
+            obj,
+            &rpf,
+            VisitorFalse<ReportPrimitiveField>,
+            VisitorFalse<ReportPrimitiveField>,
+            ReportPrimitiveFieldCallback<false>,
+            VisitorFalse<ReportPrimitiveField>);
+      }
+    }
+    return false;
+  }
+
+
+ private:
+  ReportPrimitiveField(ObjectTagTable* tag_table,
+                       jlong class_tag,
+                       const jvmtiHeapCallbacks* cb,
+                       const void* user_data)
+      : tag_table_(tag_table), class_tag_(class_tag), cb_(cb), user_data_(user_data) {}
+
+  template <bool kReportStatic>
+  static bool ReportPrimitiveFieldCallback(art::ObjPtr<art::mirror::Object> obj,
+                                           art::ObjPtr<art::mirror::Class> klass,
+                                           art::ArtField& field,
+                                           size_t field_index,
+                                           ReportPrimitiveField* user_data)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    art::Primitive::Type art_prim_type = field.GetTypeAsPrimitiveType();
+    jvmtiPrimitiveType prim_type =
+        static_cast<jvmtiPrimitiveType>(art::Primitive::Descriptor(art_prim_type)[0]);
+    DCHECK(prim_type == JVMTI_PRIMITIVE_TYPE_BOOLEAN ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_BYTE ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_CHAR ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_SHORT ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_INT ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_LONG ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_FLOAT ||
+           prim_type == JVMTI_PRIMITIVE_TYPE_DOUBLE);
+    jvmtiHeapReferenceInfo info;
+    info.field.index = field_index;
+
+    jvalue value;
+    memset(&value, 0, sizeof(jvalue));
+    art::ObjPtr<art::mirror::Object> src = kReportStatic ? klass : obj;
+    switch (art_prim_type) {
+      case art::Primitive::Type::kPrimBoolean:
+        value.z = field.GetBoolean(src) == 0 ? JNI_FALSE : JNI_TRUE;
+        break;
+      case art::Primitive::Type::kPrimByte:
+        value.b = field.GetByte(src);
+        break;
+      case art::Primitive::Type::kPrimChar:
+        value.c = field.GetChar(src);
+        break;
+      case art::Primitive::Type::kPrimShort:
+        value.s = field.GetShort(src);
+        break;
+      case art::Primitive::Type::kPrimInt:
+        value.i = field.GetInt(src);
+        break;
+      case art::Primitive::Type::kPrimLong:
+        value.j = field.GetLong(src);
+        break;
+      case art::Primitive::Type::kPrimFloat:
+        value.f = field.GetFloat(src);
+        break;
+      case art::Primitive::Type::kPrimDouble:
+        value.d = field.GetDouble(src);
+        break;
+      case art::Primitive::Type::kPrimVoid:
+      case art::Primitive::Type::kPrimNot: {
+        LOG(FATAL) << "Should not reach here";
+        UNREACHABLE();
+      }
+    }
+
+    jlong obj_tag = user_data->tag_table_->GetTagOrZero(src.Ptr());
+    const jlong saved_obj_tag = obj_tag;
+
+    jint ret = user_data->cb_->primitive_field_callback(kReportStatic
+                                                            ? JVMTI_HEAP_REFERENCE_STATIC_FIELD
+                                                            : JVMTI_HEAP_REFERENCE_FIELD,
+                                                        &info,
+                                                        user_data->class_tag_,
+                                                        &obj_tag,
+                                                        value,
+                                                        prim_type,
+                                                        const_cast<void*>(user_data->user_data_));
+
+    if (saved_obj_tag != obj_tag) {
+      user_data->tag_table_->Set(src.Ptr(), obj_tag);
+    }
+
+    if ((ret & JVMTI_VISIT_ABORT) != 0) {
+      return true;
+    }
+
+    return false;
+  }
+
+  ObjectTagTable* tag_table_;
+  jlong class_tag_;
+  const jvmtiHeapCallbacks* cb_;
+  const void* user_data_;
+};
+
+struct HeapFilter {
+  explicit HeapFilter(jint heap_filter)
+      : filter_out_tagged((heap_filter & JVMTI_HEAP_FILTER_TAGGED) != 0),
+        filter_out_untagged((heap_filter & JVMTI_HEAP_FILTER_UNTAGGED) != 0),
+        filter_out_class_tagged((heap_filter & JVMTI_HEAP_FILTER_CLASS_TAGGED) != 0),
+        filter_out_class_untagged((heap_filter & JVMTI_HEAP_FILTER_CLASS_UNTAGGED) != 0),
+        any_filter(filter_out_tagged ||
+                   filter_out_untagged ||
+                   filter_out_class_tagged ||
+                   filter_out_class_untagged) {
+  }
+
+  bool ShouldReportByHeapFilter(jlong tag, jlong class_tag) const {
+    if (!any_filter) {
+      return true;
+    }
+
+    if ((tag == 0 && filter_out_untagged) || (tag != 0 && filter_out_tagged)) {
+      return false;
+    }
+
+    if ((class_tag == 0 && filter_out_class_untagged) ||
+        (class_tag != 0 && filter_out_class_tagged)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  const bool filter_out_tagged;
+  const bool filter_out_untagged;
+  const bool filter_out_class_tagged;
+  const bool filter_out_class_untagged;
+  const bool any_filter;
+};
+
+}  // namespace
+
+void HeapUtil::Register() {
+  art::Runtime::Current()->AddSystemWeakHolder(&gIndexCachingTable);
+}
+
+void HeapUtil::Unregister() {
+  art::Runtime::Current()->RemoveSystemWeakHolder(&gIndexCachingTable);
+}
+
+template <typename T>
+static jvmtiError DoIterateThroughHeap(T fn,
+                                       jvmtiEnv* env,
+                                       ObjectTagTable* tag_table,
+                                       jint heap_filter_int,
+                                       jclass klass,
+                                       const jvmtiHeapCallbacks* callbacks,
+                                       const void* user_data) {
+  if (callbacks == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::Thread* self = art::Thread::Current();
+  art::ScopedObjectAccess soa(self);      // Now we know we have the shared lock.
+
+  bool stop_reports = false;
+  const HeapFilter heap_filter(heap_filter_int);
+  art::ObjPtr<art::mirror::Class> filter_klass = soa.Decode<art::mirror::Class>(klass);
+  auto visitor = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    // Early return, as we can't really stop visiting.
+    if (stop_reports) {
+      return;
+    }
+
+    art::ScopedAssertNoThreadSuspension no_suspension("IterateThroughHeapCallback");
+
+    jlong tag = 0;
+    tag_table->GetTag(obj, &tag);
+
+    jlong class_tag = 0;
+    art::ObjPtr<art::mirror::Class> klass = obj->GetClass();
+    tag_table->GetTag(klass.Ptr(), &class_tag);
+    // For simplicity, even if we find a tag = 0, assume 0 = not tagged.
+
+    if (!heap_filter.ShouldReportByHeapFilter(tag, class_tag)) {
+      return;
+    }
+
+    if (filter_klass != nullptr) {
+      if (filter_klass != klass) {
+        return;
+      }
+    }
+
+    jlong size = obj->SizeOf();
+
+    jint length = -1;
+    if (obj->IsArrayInstance()) {
+      length = obj->AsArray()->GetLength();
+    }
+
+    jlong saved_tag = tag;
+    jint ret = fn(obj, callbacks, class_tag, size, &tag, length, const_cast<void*>(user_data));
+
+    if (tag != saved_tag) {
+      tag_table->Set(obj, tag);
+    }
+
+    stop_reports = (ret & JVMTI_VISIT_ABORT) != 0;
+
+    if (!stop_reports) {
+      jint string_ret = ReportString(obj, env, tag_table, callbacks, user_data);
+      stop_reports = (string_ret & JVMTI_VISIT_ABORT) != 0;
+    }
+
+    if (!stop_reports) {
+      jint array_ret = ReportPrimitiveArray(obj, env, tag_table, callbacks, user_data);
+      stop_reports = (array_ret & JVMTI_VISIT_ABORT) != 0;
+    }
+
+    if (!stop_reports) {
+      stop_reports = ReportPrimitiveField::Report(obj, tag_table, callbacks, user_data);
+    }
+  };
+  art::Runtime::Current()->GetHeap()->VisitObjects(visitor);
+
+  return ERR(NONE);
+}
+
+jvmtiError HeapUtil::IterateThroughHeap(jvmtiEnv* env,
+                                        jint heap_filter,
+                                        jclass klass,
+                                        const jvmtiHeapCallbacks* callbacks,
+                                        const void* user_data) {
+  auto JvmtiIterateHeap = [](art::mirror::Object* obj ATTRIBUTE_UNUSED,
+                             const jvmtiHeapCallbacks* cb_callbacks,
+                             jlong class_tag,
+                             jlong size,
+                             jlong* tag,
+                             jint length,
+                             void* cb_user_data)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return cb_callbacks->heap_iteration_callback(class_tag,
+                                                 size,
+                                                 tag,
+                                                 length,
+                                                 cb_user_data);
+  };
+  return DoIterateThroughHeap(JvmtiIterateHeap,
+                              env,
+                              ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get(),
+                              heap_filter,
+                              klass,
+                              callbacks,
+                              user_data);
+}
+
+class FollowReferencesHelper FINAL {
+ public:
+  FollowReferencesHelper(HeapUtil* h,
+                         jvmtiEnv* jvmti_env,
+                         art::ObjPtr<art::mirror::Object> initial_object,
+                         const jvmtiHeapCallbacks* callbacks,
+                         art::ObjPtr<art::mirror::Class> class_filter,
+                         jint heap_filter,
+                         const void* user_data)
+      : env(jvmti_env),
+        tag_table_(h->GetTags()),
+        initial_object_(initial_object),
+        callbacks_(callbacks),
+        class_filter_(class_filter),
+        heap_filter_(heap_filter),
+        user_data_(user_data),
+        start_(0),
+        stop_reports_(false) {
+  }
+
+  void Init()
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+    if (initial_object_.IsNull()) {
+      CollectAndReportRootsVisitor carrv(this, tag_table_, &worklist_, &visited_);
+
+      // We need precise info (e.g., vregs).
+      constexpr art::VisitRootFlags kRootFlags = static_cast<art::VisitRootFlags>(
+          art::VisitRootFlags::kVisitRootFlagAllRoots | art::VisitRootFlags::kVisitRootFlagPrecise);
+      art::Runtime::Current()->VisitRoots(&carrv, kRootFlags);
+
+      art::Runtime::Current()->VisitImageRoots(&carrv);
+      stop_reports_ = carrv.IsStopReports();
+
+      if (stop_reports_) {
+        worklist_.clear();
+      }
+    } else {
+      visited_.insert(initial_object_.Ptr());
+      worklist_.push_back(initial_object_.Ptr());
+    }
+  }
+
+  void Work()
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+    // Currently implemented as a BFS. To lower overhead, we don't erase elements immediately
+    // from the head of the work list, instead postponing until there's a gap that's "large."
+    //
+    // Alternatively, we can implement a DFS and use the work list as a stack.
+    while (start_ < worklist_.size()) {
+      art::mirror::Object* cur_obj = worklist_[start_];
+      start_++;
+
+      if (start_ >= kMaxStart) {
+        worklist_.erase(worklist_.begin(), worklist_.begin() + start_);
+        start_ = 0;
+      }
+
+      VisitObject(cur_obj);
+
+      if (stop_reports_) {
+        break;
+      }
+    }
+  }
+
+ private:
+  class CollectAndReportRootsVisitor FINAL : public art::RootVisitor {
+   public:
+    CollectAndReportRootsVisitor(FollowReferencesHelper* helper,
+                                 ObjectTagTable* tag_table,
+                                 std::vector<art::mirror::Object*>* worklist,
+                                 std::unordered_set<art::mirror::Object*>* visited)
+        : helper_(helper),
+          tag_table_(tag_table),
+          worklist_(worklist),
+          visited_(visited),
+          stop_reports_(false) {}
+
+    void VisitRoots(art::mirror::Object*** roots, size_t count, const art::RootInfo& info)
+        OVERRIDE
+        REQUIRES_SHARED(art::Locks::mutator_lock_)
+        REQUIRES(!*helper_->tag_table_->GetAllowDisallowLock()) {
+      for (size_t i = 0; i != count; ++i) {
+        AddRoot(*roots[i], info);
+      }
+    }
+
+    void VisitRoots(art::mirror::CompressedReference<art::mirror::Object>** roots,
+                    size_t count,
+                    const art::RootInfo& info)
+        OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_)
+        REQUIRES(!*helper_->tag_table_->GetAllowDisallowLock()) {
+      for (size_t i = 0; i != count; ++i) {
+        AddRoot(roots[i]->AsMirrorPtr(), info);
+      }
+    }
+
+    bool IsStopReports() {
+      return stop_reports_;
+    }
+
+   private:
+    void AddRoot(art::mirror::Object* root_obj, const art::RootInfo& info)
+        REQUIRES_SHARED(art::Locks::mutator_lock_)
+        REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+      if (stop_reports_) {
+        return;
+      }
+      bool add_to_worklist = ReportRoot(root_obj, info);
+      // We use visited_ to mark roots already so we do not need another set.
+      if (visited_->find(root_obj) == visited_->end()) {
+        if (add_to_worklist) {
+          visited_->insert(root_obj);
+          worklist_->push_back(root_obj);
+        }
+      }
+    }
+
+    // Remove NO_THREAD_SAFETY_ANALYSIS once ASSERT_CAPABILITY works correctly.
+    art::Thread* FindThread(const art::RootInfo& info) NO_THREAD_SAFETY_ANALYSIS {
+      art::Locks::thread_list_lock_->AssertExclusiveHeld(art::Thread::Current());
+      return art::Runtime::Current()->GetThreadList()->FindThreadByThreadId(info.GetThreadId());
+    }
+
+    jvmtiHeapReferenceKind GetReferenceKind(const art::RootInfo& info,
+                                            jvmtiHeapReferenceInfo* ref_info)
+        REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      // TODO: Fill in ref_info.
+      memset(ref_info, 0, sizeof(jvmtiHeapReferenceInfo));
+
+      switch (info.GetType()) {
+        case art::RootType::kRootJNIGlobal:
+          return JVMTI_HEAP_REFERENCE_JNI_GLOBAL;
+
+        case art::RootType::kRootJNILocal:
+        {
+          uint32_t thread_id = info.GetThreadId();
+          ref_info->jni_local.thread_id = thread_id;
+
+          art::Thread* thread = FindThread(info);
+          if (thread != nullptr) {
+            art::mirror::Object* thread_obj;
+            if (thread->IsStillStarting()) {
+              thread_obj = nullptr;
+            } else {
+              thread_obj = thread->GetPeerFromOtherThread();
+            }
+            if (thread_obj != nullptr) {
+              ref_info->jni_local.thread_tag = tag_table_->GetTagOrZero(thread_obj);
+            }
+          }
+
+          // TODO: We don't have this info.
+          if (thread != nullptr) {
+            ref_info->jni_local.depth = 0;
+            art::ArtMethod* method = thread->GetCurrentMethod(nullptr, false /* abort_on_error */);
+            if (method != nullptr) {
+              ref_info->jni_local.method = art::jni::EncodeArtMethod(method);
+            }
+          }
+
+          return JVMTI_HEAP_REFERENCE_JNI_LOCAL;
+        }
+
+        case art::RootType::kRootJavaFrame:
+        {
+          uint32_t thread_id = info.GetThreadId();
+          ref_info->stack_local.thread_id = thread_id;
+
+          art::Thread* thread = FindThread(info);
+          if (thread != nullptr) {
+            art::mirror::Object* thread_obj;
+            if (thread->IsStillStarting()) {
+              thread_obj = nullptr;
+            } else {
+              thread_obj = thread->GetPeerFromOtherThread();
+            }
+            if (thread_obj != nullptr) {
+              ref_info->stack_local.thread_tag = tag_table_->GetTagOrZero(thread_obj);
+            }
+          }
+
+          auto& java_info = static_cast<const art::JavaFrameRootInfo&>(info);
+          ref_info->stack_local.slot = static_cast<jint>(java_info.GetVReg());
+          const art::StackVisitor* visitor = java_info.GetVisitor();
+          ref_info->stack_local.location =
+              static_cast<jlocation>(visitor->GetDexPc(false /* abort_on_failure */));
+          ref_info->stack_local.depth = static_cast<jint>(visitor->GetFrameDepth());
+          art::ArtMethod* method = visitor->GetMethod();
+          if (method != nullptr) {
+            ref_info->stack_local.method = art::jni::EncodeArtMethod(method);
+          }
+
+          return JVMTI_HEAP_REFERENCE_STACK_LOCAL;
+        }
+
+        case art::RootType::kRootNativeStack:
+        case art::RootType::kRootThreadBlock:
+        case art::RootType::kRootThreadObject:
+          return JVMTI_HEAP_REFERENCE_THREAD;
+
+        case art::RootType::kRootStickyClass:
+        case art::RootType::kRootInternedString:
+          // Note: this isn't a root in the RI.
+          return JVMTI_HEAP_REFERENCE_SYSTEM_CLASS;
+
+        case art::RootType::kRootMonitorUsed:
+        case art::RootType::kRootJNIMonitor:
+          return JVMTI_HEAP_REFERENCE_MONITOR;
+
+        case art::RootType::kRootFinalizing:
+        case art::RootType::kRootDebugger:
+        case art::RootType::kRootReferenceCleanup:
+        case art::RootType::kRootVMInternal:
+        case art::RootType::kRootUnknown:
+          return JVMTI_HEAP_REFERENCE_OTHER;
+      }
+      LOG(FATAL) << "Unreachable";
+      UNREACHABLE();
+    }
+
+    bool ReportRoot(art::mirror::Object* root_obj, const art::RootInfo& info)
+        REQUIRES_SHARED(art::Locks::mutator_lock_)
+        REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+      jvmtiHeapReferenceInfo ref_info;
+      jvmtiHeapReferenceKind kind = GetReferenceKind(info, &ref_info);
+      jint result = helper_->ReportReference(kind, &ref_info, nullptr, root_obj);
+      if ((result & JVMTI_VISIT_ABORT) != 0) {
+        stop_reports_ = true;
+      }
+      return (result & JVMTI_VISIT_OBJECTS) != 0;
+    }
+
+   private:
+    FollowReferencesHelper* helper_;
+    ObjectTagTable* tag_table_;
+    std::vector<art::mirror::Object*>* worklist_;
+    std::unordered_set<art::mirror::Object*>* visited_;
+    bool stop_reports_;
+  };
+
+  void VisitObject(art::mirror::Object* obj)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+    if (obj->IsClass()) {
+      VisitClass(obj->AsClass());
+      return;
+    }
+    if (obj->IsArrayInstance()) {
+      VisitArray(obj);
+      return;
+    }
+
+    // All instance fields.
+    auto report_instance_field = [&](art::ObjPtr<art::mirror::Object> src,
+                                     art::ObjPtr<art::mirror::Class> obj_klass ATTRIBUTE_UNUSED,
+                                     art::ArtField& field,
+                                     size_t field_index,
+                                     void* user_data ATTRIBUTE_UNUSED)
+        REQUIRES_SHARED(art::Locks::mutator_lock_)
+        REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+      art::ObjPtr<art::mirror::Object> field_value = field.GetObject(src);
+      if (field_value != nullptr) {
+        jvmtiHeapReferenceInfo reference_info;
+        memset(&reference_info, 0, sizeof(reference_info));
+
+        reference_info.field.index = field_index;
+
+        jvmtiHeapReferenceKind kind =
+            field.GetOffset().Int32Value() == art::mirror::Object::ClassOffset().Int32Value()
+                ? JVMTI_HEAP_REFERENCE_CLASS
+                : JVMTI_HEAP_REFERENCE_FIELD;
+        const jvmtiHeapReferenceInfo* reference_info_ptr =
+            kind == JVMTI_HEAP_REFERENCE_CLASS ? nullptr : &reference_info;
+
+        return !ReportReferenceMaybeEnqueue(kind, reference_info_ptr, src.Ptr(), field_value.Ptr());
+      }
+      return false;
+    };
+    stop_reports_ = FieldVisitor<void, true>::ReportFields(obj,
+                                                           nullptr,
+                                                           VisitorFalse<void>,
+                                                           VisitorFalse<void>,
+                                                           VisitorFalse<void>,
+                                                           report_instance_field);
+    if (stop_reports_) {
+      return;
+    }
+
+    jint string_ret = ReportString(obj, env, tag_table_, callbacks_, user_data_);
+    stop_reports_ = (string_ret & JVMTI_VISIT_ABORT) != 0;
+    if (stop_reports_) {
+      return;
+    }
+
+    stop_reports_ = ReportPrimitiveField::Report(obj, tag_table_, callbacks_, user_data_);
+  }
+
+  void VisitArray(art::mirror::Object* array)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+    stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_CLASS,
+                                                 nullptr,
+                                                 array,
+                                                 array->GetClass());
+    if (stop_reports_) {
+      return;
+    }
+
+    if (array->IsObjectArray()) {
+      art::mirror::ObjectArray<art::mirror::Object>* obj_array =
+          array->AsObjectArray<art::mirror::Object>();
+      int32_t length = obj_array->GetLength();
+      for (int32_t i = 0; i != length; ++i) {
+        art::mirror::Object* elem = obj_array->GetWithoutChecks(i);
+        if (elem != nullptr) {
+          jvmtiHeapReferenceInfo reference_info;
+          reference_info.array.index = i;
+          stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT,
+                                                       &reference_info,
+                                                       array,
+                                                       elem);
+          if (stop_reports_) {
+            break;
+          }
+        }
+      }
+    } else {
+      if (!stop_reports_) {
+        jint array_ret = ReportPrimitiveArray(array, env, tag_table_, callbacks_, user_data_);
+        stop_reports_ = (array_ret & JVMTI_VISIT_ABORT) != 0;
+      }
+    }
+  }
+
+  void VisitClass(art::mirror::Class* klass)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+    // TODO: Are erroneous classes reported? Are non-prepared ones? For now, just use resolved ones.
+    if (!klass->IsResolved()) {
+      return;
+    }
+
+    // Superclass.
+    stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_SUPERCLASS,
+                                                 nullptr,
+                                                 klass,
+                                                 klass->GetSuperClass());
+    if (stop_reports_) {
+      return;
+    }
+
+    // Directly implemented or extended interfaces.
+    art::Thread* self = art::Thread::Current();
+    art::StackHandleScope<1> hs(self);
+    art::Handle<art::mirror::Class> h_klass(hs.NewHandle<art::mirror::Class>(klass));
+    for (size_t i = 0; i < h_klass->NumDirectInterfaces(); ++i) {
+      art::ObjPtr<art::mirror::Class> inf_klass =
+          art::mirror::Class::ResolveDirectInterface(self, h_klass, i);
+      if (inf_klass == nullptr) {
+        // TODO: With a resolved class this should not happen...
+        self->ClearException();
+        break;
+      }
+
+      stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_INTERFACE,
+                                                   nullptr,
+                                                   klass,
+                                                   inf_klass.Ptr());
+      if (stop_reports_) {
+        return;
+      }
+    }
+
+    // Classloader.
+    // TODO: What about the boot classpath loader? We'll skip for now, but do we have to find the
+    //       fake BootClassLoader?
+    if (klass->GetClassLoader() != nullptr) {
+      stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_CLASS_LOADER,
+                                                   nullptr,
+                                                   klass,
+                                                   klass->GetClassLoader());
+      if (stop_reports_) {
+        return;
+      }
+    }
+    DCHECK_EQ(h_klass.Get(), klass);
+
+    // Declared static fields.
+    auto report_static_field = [&](art::ObjPtr<art::mirror::Object> obj ATTRIBUTE_UNUSED,
+                                   art::ObjPtr<art::mirror::Class> obj_klass,
+                                   art::ArtField& field,
+                                   size_t field_index,
+                                   void* user_data ATTRIBUTE_UNUSED)
+        REQUIRES_SHARED(art::Locks::mutator_lock_)
+        REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+      art::ObjPtr<art::mirror::Object> field_value = field.GetObject(obj_klass);
+      if (field_value != nullptr) {
+        jvmtiHeapReferenceInfo reference_info;
+        memset(&reference_info, 0, sizeof(reference_info));
+
+        reference_info.field.index = static_cast<jint>(field_index);
+
+        return !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_STATIC_FIELD,
+                                            &reference_info,
+                                            obj_klass.Ptr(),
+                                            field_value.Ptr());
+      }
+      return false;
+    };
+    stop_reports_ = FieldVisitor<void, false>::ReportFields(klass,
+                                                            nullptr,
+                                                            VisitorFalse<void>,
+                                                            report_static_field,
+                                                            VisitorFalse<void>,
+                                                            VisitorFalse<void>);
+    if (stop_reports_) {
+      return;
+    }
+
+    stop_reports_ = ReportPrimitiveField::Report(klass, tag_table_, callbacks_, user_data_);
+  }
+
+  void MaybeEnqueue(art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    if (visited_.find(obj) == visited_.end()) {
+      worklist_.push_back(obj);
+      visited_.insert(obj);
+    }
+  }
+
+  bool ReportReferenceMaybeEnqueue(jvmtiHeapReferenceKind kind,
+                                   const jvmtiHeapReferenceInfo* reference_info,
+                                   art::mirror::Object* referree,
+                                   art::mirror::Object* referrer)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+    jint result = ReportReference(kind, reference_info, referree, referrer);
+    if ((result & JVMTI_VISIT_ABORT) == 0) {
+      if ((result & JVMTI_VISIT_OBJECTS) != 0) {
+        MaybeEnqueue(referrer);
+      }
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  jint ReportReference(jvmtiHeapReferenceKind kind,
+                       const jvmtiHeapReferenceInfo* reference_info,
+                       art::mirror::Object* referrer,
+                       art::mirror::Object* referree)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+    if (referree == nullptr || stop_reports_) {
+      return 0;
+    }
+
+    if (UNLIKELY(class_filter_ != nullptr) && class_filter_ != referree->GetClass()) {
+      return JVMTI_VISIT_OBJECTS;
+    }
+
+    const jlong class_tag = tag_table_->GetTagOrZero(referree->GetClass());
+    jlong tag = tag_table_->GetTagOrZero(referree);
+
+    if (!heap_filter_.ShouldReportByHeapFilter(tag, class_tag)) {
+      return JVMTI_VISIT_OBJECTS;
+    }
+
+    const jlong referrer_class_tag =
+        referrer == nullptr ? 0 : tag_table_->GetTagOrZero(referrer->GetClass());
+    const jlong size = static_cast<jlong>(referree->SizeOf());
+    jlong saved_tag = tag;
+    jlong referrer_tag = 0;
+    jlong saved_referrer_tag = 0;
+    jlong* referrer_tag_ptr;
+    if (referrer == nullptr) {
+      referrer_tag_ptr = nullptr;
+    } else {
+      if (referrer == referree) {
+        referrer_tag_ptr = &tag;
+      } else {
+        referrer_tag = saved_referrer_tag = tag_table_->GetTagOrZero(referrer);
+        referrer_tag_ptr = &referrer_tag;
+      }
+    }
+
+    jint length = -1;
+    if (referree->IsArrayInstance()) {
+      length = referree->AsArray()->GetLength();
+    }
+
+    jint result = callbacks_->heap_reference_callback(kind,
+                                                      reference_info,
+                                                      class_tag,
+                                                      referrer_class_tag,
+                                                      size,
+                                                      &tag,
+                                                      referrer_tag_ptr,
+                                                      length,
+                                                      const_cast<void*>(user_data_));
+
+    if (tag != saved_tag) {
+      tag_table_->Set(referree, tag);
+    }
+    if (referrer_tag != saved_referrer_tag) {
+      tag_table_->Set(referrer, referrer_tag);
+    }
+
+    return result;
+  }
+
+  jvmtiEnv* env;
+  ObjectTagTable* tag_table_;
+  art::ObjPtr<art::mirror::Object> initial_object_;
+  const jvmtiHeapCallbacks* callbacks_;
+  art::ObjPtr<art::mirror::Class> class_filter_;
+  const HeapFilter heap_filter_;
+  const void* user_data_;
+
+  std::vector<art::mirror::Object*> worklist_;
+  size_t start_;
+  static constexpr size_t kMaxStart = 1000000U;
+
+  std::unordered_set<art::mirror::Object*> visited_;
+
+  bool stop_reports_;
+
+  friend class CollectAndReportRootsVisitor;
+};
+
+jvmtiError HeapUtil::FollowReferences(jvmtiEnv* env,
+                                      jint heap_filter,
+                                      jclass klass,
+                                      jobject initial_object,
+                                      const jvmtiHeapCallbacks* callbacks,
+                                      const void* user_data) {
+  if (callbacks == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::Thread* self = art::Thread::Current();
+
+  art::gc::Heap* heap = art::Runtime::Current()->GetHeap();
+  if (heap->IsGcConcurrentAndMoving()) {
+    // Need to take a heap dump while GC isn't running. See the
+    // comment in Heap::VisitObjects().
+    heap->IncrementDisableMovingGC(self);
+  }
+  {
+    art::ScopedObjectAccess soa(self);      // Now we know we have the shared lock.
+    art::ScopedThreadSuspension sts(self, art::kWaitingForVisitObjects);
+    art::ScopedSuspendAll ssa("FollowReferences");
+
+    art::ObjPtr<art::mirror::Class> class_filter = klass == nullptr
+        ? nullptr
+        : art::ObjPtr<art::mirror::Class>::DownCast(self->DecodeJObject(klass));
+    FollowReferencesHelper frh(this,
+                               env,
+                               self->DecodeJObject(initial_object),
+                               callbacks,
+                               class_filter,
+                               heap_filter,
+                               user_data);
+    frh.Init();
+    frh.Work();
+  }
+  if (heap->IsGcConcurrentAndMoving()) {
+    heap->DecrementDisableMovingGC(self);
+  }
+
+  return ERR(NONE);
+}
+
+jvmtiError HeapUtil::GetLoadedClasses(jvmtiEnv* env,
+                                      jint* class_count_ptr,
+                                      jclass** classes_ptr) {
+  if (class_count_ptr == nullptr || classes_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  class ReportClassVisitor : public art::ClassVisitor {
+   public:
+    explicit ReportClassVisitor(art::Thread* self) : self_(self) {}
+
+    bool operator()(art::ObjPtr<art::mirror::Class> klass)
+        OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+      if (klass->IsLoaded() || klass->IsErroneous()) {
+        classes_.push_back(self_->GetJniEnv()->AddLocalReference<jclass>(klass));
+      }
+      return true;
+    }
+
+    art::Thread* self_;
+    std::vector<jclass> classes_;
+  };
+
+  art::Thread* self = art::Thread::Current();
+  ReportClassVisitor rcv(self);
+  {
+    art::ScopedObjectAccess soa(self);
+    art::Runtime::Current()->GetClassLinker()->VisitClasses(&rcv);
+  }
+
+  size_t size = rcv.classes_.size();
+  jclass* classes = nullptr;
+  jvmtiError alloc_ret = env->Allocate(static_cast<jlong>(size * sizeof(jclass)),
+                                       reinterpret_cast<unsigned char**>(&classes));
+  if (alloc_ret != ERR(NONE)) {
+    return alloc_ret;
+  }
+
+  for (size_t i = 0; i < size; ++i) {
+    classes[i] = rcv.classes_[i];
+  }
+  *classes_ptr = classes;
+  *class_count_ptr = static_cast<jint>(size);
+
+  return ERR(NONE);
+}
+
+jvmtiError HeapUtil::ForceGarbageCollection(jvmtiEnv* env ATTRIBUTE_UNUSED) {
+  art::Runtime::Current()->GetHeap()->CollectGarbage(false);
+
+  return ERR(NONE);
+}
+
+static constexpr jint kHeapIdDefault = 0;
+static constexpr jint kHeapIdImage = 1;
+static constexpr jint kHeapIdZygote = 2;
+static constexpr jint kHeapIdApp = 3;
+
+static jint GetHeapId(art::ObjPtr<art::mirror::Object> obj)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  if (obj == nullptr) {
+    return -1;
+  }
+
+  art::gc::Heap* const heap = art::Runtime::Current()->GetHeap();
+  const art::gc::space::ContinuousSpace* const space =
+      heap->FindContinuousSpaceFromObject(obj, true);
+  jint heap_type = kHeapIdApp;
+  if (space != nullptr) {
+    if (space->IsZygoteSpace()) {
+      heap_type = kHeapIdZygote;
+    } else if (space->IsImageSpace() && heap->ObjectIsInBootImageSpace(obj)) {
+      // Only count objects in the boot image as HPROF_HEAP_IMAGE, this leaves app image objects
+      // as HPROF_HEAP_APP. b/35762934
+      heap_type = kHeapIdImage;
+    }
+  } else {
+    const auto* los = heap->GetLargeObjectsSpace();
+    if (los->Contains(obj.Ptr()) && los->IsZygoteLargeObject(art::Thread::Current(), obj.Ptr())) {
+      heap_type = kHeapIdZygote;
+    }
+  }
+  return heap_type;
+};
+
+jvmtiError HeapExtensions::GetObjectHeapId(jvmtiEnv* env, jlong tag, jint* heap_id, ...) {
+  if (heap_id == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::Thread* self = art::Thread::Current();
+
+  auto work = [&]() REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    ObjectTagTable* tag_table = ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get();
+    art::ObjPtr<art::mirror::Object> obj = tag_table->Find(tag);
+    jint heap_type = GetHeapId(obj);
+    if (heap_type == -1) {
+      return ERR(NOT_FOUND);
+    }
+    *heap_id = heap_type;
+    return ERR(NONE);
+  };
+
+  if (!art::Locks::mutator_lock_->IsSharedHeld(self)) {
+    if (!self->IsThreadSuspensionAllowable()) {
+      return ERR(INTERNAL);
+    }
+    art::ScopedObjectAccess soa(self);
+    return work();
+  } else {
+    // We cannot use SOA in this case. We might be holding the lock, but may not be in the
+    // runnable state (e.g., during GC).
+    art::Locks::mutator_lock_->AssertSharedHeld(self);
+    // TODO: Investigate why ASSERT_SHARED_CAPABILITY doesn't work.
+    auto annotalysis_workaround = [&]() NO_THREAD_SAFETY_ANALYSIS {
+      return work();
+    };
+    return annotalysis_workaround();
+  }
+}
+
+static jvmtiError CopyStringAndReturn(jvmtiEnv* env, const char* in, char** out) {
+  jvmtiError error;
+  JvmtiUniquePtr<char[]> param_name = CopyString(env, in, &error);
+  if (param_name == nullptr) {
+    return error;
+  }
+  *out = param_name.release();
+  return ERR(NONE);
+}
+
+static constexpr const char* kHeapIdDefaultName = "default";
+static constexpr const char* kHeapIdImageName = "image";
+static constexpr const char* kHeapIdZygoteName = "zygote";
+static constexpr const char* kHeapIdAppName = "app";
+
+jvmtiError HeapExtensions::GetHeapName(jvmtiEnv* env, jint heap_id, char** heap_name, ...) {
+  switch (heap_id) {
+    case kHeapIdDefault:
+      return CopyStringAndReturn(env, kHeapIdDefaultName, heap_name);
+    case kHeapIdImage:
+      return CopyStringAndReturn(env, kHeapIdImageName, heap_name);
+    case kHeapIdZygote:
+      return CopyStringAndReturn(env, kHeapIdZygoteName, heap_name);
+    case kHeapIdApp:
+      return CopyStringAndReturn(env, kHeapIdAppName, heap_name);
+
+    default:
+      return ERR(ILLEGAL_ARGUMENT);
+  }
+}
+
+jvmtiError HeapExtensions::IterateThroughHeapExt(jvmtiEnv* env,
+                                                 jint heap_filter,
+                                                 jclass klass,
+                                                 const jvmtiHeapCallbacks* callbacks,
+                                                 const void* user_data) {
+  if (ArtJvmTiEnv::AsArtJvmTiEnv(env)->capabilities.can_tag_objects != 1) { \
+    return ERR(MUST_POSSESS_CAPABILITY); \
+  }
+
+  // ART extension API: Also pass the heap id.
+  auto ArtIterateHeap = [](art::mirror::Object* obj,
+                           const jvmtiHeapCallbacks* cb_callbacks,
+                           jlong class_tag,
+                           jlong size,
+                           jlong* tag,
+                           jint length,
+                           void* cb_user_data)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    jint heap_id = GetHeapId(obj);
+    using ArtExtensionAPI = jint (*)(jlong, jlong, jlong*, jint length, void*, jint);
+    return reinterpret_cast<ArtExtensionAPI>(cb_callbacks->heap_iteration_callback)(
+        class_tag, size, tag, length, cb_user_data, heap_id);
+  };
+  return DoIterateThroughHeap(ArtIterateHeap,
+                              env,
+                              ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get(),
+                              heap_filter,
+                              klass,
+                              callbacks,
+                              user_data);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_heap.h b/openjdkjvmti/ti_heap.h
new file mode 100644
index 0000000..62761b5
--- /dev/null
+++ b/openjdkjvmti/ti_heap.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_HEAP_H_
+#define ART_OPENJDKJVMTI_TI_HEAP_H_
+
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class ObjectTagTable;
+
+class HeapUtil {
+ public:
+  explicit HeapUtil(ObjectTagTable* tags) : tags_(tags) {
+  }
+
+  jvmtiError GetLoadedClasses(jvmtiEnv* env, jint* class_count_ptr, jclass** classes_ptr);
+
+  jvmtiError IterateThroughHeap(jvmtiEnv* env,
+                                jint heap_filter,
+                                jclass klass,
+                                const jvmtiHeapCallbacks* callbacks,
+                                const void* user_data);
+
+  jvmtiError FollowReferences(jvmtiEnv* env,
+                              jint heap_filter,
+                              jclass klass,
+                              jobject initial_object,
+                              const jvmtiHeapCallbacks* callbacks,
+                              const void* user_data);
+
+  static jvmtiError ForceGarbageCollection(jvmtiEnv* env);
+
+  ObjectTagTable* GetTags() {
+    return tags_;
+  }
+
+  static void Register();
+  static void Unregister();
+
+ private:
+  ObjectTagTable* tags_;
+};
+
+class HeapExtensions {
+ public:
+  static jvmtiError JNICALL GetObjectHeapId(jvmtiEnv* env, jlong tag, jint* heap_id, ...);
+  static jvmtiError JNICALL GetHeapName(jvmtiEnv* env, jint heap_id, char** heap_name, ...);
+
+  static jvmtiError JNICALL IterateThroughHeapExt(jvmtiEnv* env,
+                                                  jint heap_filter,
+                                                  jclass klass,
+                                                  const jvmtiHeapCallbacks* callbacks,
+                                                  const void* user_data);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_HEAP_H_
diff --git a/openjdkjvmti/ti_jni.cc b/openjdkjvmti/ti_jni.cc
new file mode 100644
index 0000000..dd2dda1
--- /dev/null
+++ b/openjdkjvmti/ti_jni.cc
@@ -0,0 +1,91 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_jni.h"
+
+#include "jni.h"
+
+#include "art_jvmti.h"
+#include "base/mutex.h"
+#include "java_vm_ext.h"
+#include "jni_env_ext.h"
+#include "runtime.h"
+#include "thread-current-inl.h"
+
+namespace openjdkjvmti {
+
+jvmtiError JNIUtil::SetJNIFunctionTable(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                        const jniNativeInterface* function_table) {
+  // While we supporting setting null (which will reset the table), the spec says no.
+  if (function_table == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::JNIEnvExt::SetTableOverride(function_table);
+  return ERR(NONE);
+}
+
+jvmtiError JNIUtil::GetJNIFunctionTable(jvmtiEnv* env, jniNativeInterface** function_table) {
+  if (function_table == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  // We use the generic JNIEnvExt::GetFunctionTable instead of querying a specific JNIEnv, as
+  // this has to work in the start phase.
+
+  // Figure out which table is current. Conservatively assume check-jni is off.
+  bool check_jni = false;
+  art::Runtime* runtime = art::Runtime::Current();
+  if (runtime != nullptr && runtime->GetJavaVM() != nullptr) {
+    check_jni = runtime->GetJavaVM()->IsCheckJniEnabled();
+  }
+
+  // Get that table.
+  const JNINativeInterface* current_table;
+  {
+    art::MutexLock mu(art::Thread::Current(), *art::Locks::jni_function_table_lock_);
+    current_table = art::JNIEnvExt::GetFunctionTable(check_jni);
+  }
+
+  // Allocate memory and copy the table.
+  unsigned char* data;
+  jvmtiError data_result = env->Allocate(sizeof(JNINativeInterface), &data);
+  if (data_result != ERR(NONE)) {
+    return data_result;
+  }
+  memcpy(data, current_table, sizeof(JNINativeInterface));
+
+  *function_table = reinterpret_cast<JNINativeInterface*>(data);
+
+  return ERR(NONE);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_jni.h b/openjdkjvmti/ti_jni.h
new file mode 100644
index 0000000..590fd54
--- /dev/null
+++ b/openjdkjvmti/ti_jni.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_JNI_H_
+#define ART_OPENJDKJVMTI_TI_JNI_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+// Note: Currently, JNI function table changes are sensitive to the order of operations wrt/
+//       CheckJNI. If an agent sets the function table, and a program than late-enables CheckJNI,
+//       CheckJNI will not be working (as the agent will forward to the non-CheckJNI table).
+//
+//       This behavior results from our usage of the function table to avoid a check of the
+//       CheckJNI flag. A future implementation may install on loading of this plugin an
+//       intermediate function table that explicitly checks the flag, so that switching CheckJNI
+//       is transparently handled.
+
+class JNIUtil {
+ public:
+  static jvmtiError SetJNIFunctionTable(jvmtiEnv* env, const jniNativeInterface* function_table);
+
+  static jvmtiError GetJNIFunctionTable(jvmtiEnv* env, jniNativeInterface** function_table);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_JNI_H_
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
new file mode 100644
index 0000000..8f72714
--- /dev/null
+++ b/openjdkjvmti/ti_method.cc
@@ -0,0 +1,1071 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_method.h"
+
+#include "art_jvmti.h"
+#include "art_method-inl.h"
+#include "base/enums.h"
+#include "base/mutex-inl.h"
+#include "dex_file_annotations.h"
+#include "events-inl.h"
+#include "jni_internal.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_loader.h"
+#include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "modifiers.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "runtime_callbacks.h"
+#include "scoped_thread_state_change-inl.h"
+#include "stack.h"
+#include "thread-current-inl.h"
+#include "thread_list.h"
+#include "ti_thread.h"
+#include "ti_phase.h"
+
+namespace openjdkjvmti {
+
+struct TiMethodCallback : public art::MethodCallback {
+  void RegisterNativeMethod(art::ArtMethod* method,
+                            const void* cur_method,
+                            /*out*/void** new_method)
+      OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kNativeMethodBind)) {
+      art::Thread* thread = art::Thread::Current();
+      art::JNIEnvExt* jnienv = thread->GetJniEnv();
+      ScopedLocalRef<jthread> thread_jni(
+          jnienv, PhaseUtil::IsLivePhase() ? jnienv->AddLocalReference<jthread>(thread->GetPeer())
+                                           : nullptr);
+      art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative);
+      event_handler->DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>(
+          thread,
+          static_cast<JNIEnv*>(jnienv),
+          thread_jni.get(),
+          art::jni::EncodeArtMethod(method),
+          const_cast<void*>(cur_method),
+          new_method);
+    }
+  }
+
+  EventHandler* event_handler = nullptr;
+};
+
+TiMethodCallback gMethodCallback;
+
+void MethodUtil::Register(EventHandler* handler) {
+  gMethodCallback.event_handler = handler;
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Add method callback");
+  art::Runtime::Current()->GetRuntimeCallbacks()->AddMethodCallback(&gMethodCallback);
+}
+
+void MethodUtil::Unregister() {
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Remove method callback");
+  art::Runtime* runtime = art::Runtime::Current();
+  runtime->GetRuntimeCallbacks()->RemoveMethodCallback(&gMethodCallback);
+}
+
+jvmtiError MethodUtil::GetBytecodes(jvmtiEnv* env,
+                                    jmethodID method,
+                                    jint* size_ptr,
+                                    unsigned char** bytecode_ptr) {
+  if (method == nullptr) {
+    return ERR(INVALID_METHODID);
+  }
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+
+  if (art_method->IsNative()) {
+    return ERR(NATIVE_METHOD);
+  }
+
+  if (size_ptr == nullptr || bytecode_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  const art::DexFile::CodeItem* code_item = art_method->GetCodeItem();
+  if (code_item == nullptr) {
+    *size_ptr = 0;
+    *bytecode_ptr = nullptr;
+    return OK;
+  }
+  // 2 bytes per instruction for dex code.
+  *size_ptr = code_item->insns_size_in_code_units_ * 2;
+  jvmtiError err = env->Allocate(*size_ptr, bytecode_ptr);
+  if (err != OK) {
+    return err;
+  }
+  memcpy(*bytecode_ptr, code_item->insns_, *size_ptr);
+  return OK;
+}
+
+jvmtiError MethodUtil::GetArgumentsSize(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                        jmethodID method,
+                                        jint* size_ptr) {
+  if (method == nullptr) {
+    return ERR(INVALID_METHODID);
+  }
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+
+  if (art_method->IsNative()) {
+    return ERR(NATIVE_METHOD);
+  }
+
+  if (size_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
+    // Use the shorty.
+    art::ArtMethod* base_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
+    size_t arg_count = art::ArtMethod::NumArgRegisters(base_method->GetShorty());
+    if (!base_method->IsStatic()) {
+      arg_count++;
+    }
+    *size_ptr = static_cast<jint>(arg_count);
+    return ERR(NONE);
+  }
+
+  DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
+  *size_ptr = art_method->GetCodeItem()->ins_size_;
+
+  return ERR(NONE);
+}
+
+jvmtiError MethodUtil::GetLocalVariableTable(jvmtiEnv* env,
+                                             jmethodID method,
+                                             jint* entry_count_ptr,
+                                             jvmtiLocalVariableEntry** table_ptr) {
+  if (method == nullptr) {
+    return ERR(INVALID_METHODID);
+  }
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+
+  if (art_method->IsNative()) {
+    return ERR(NATIVE_METHOD);
+  }
+
+  if (entry_count_ptr == nullptr || table_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  const art::DexFile* dex_file = art_method->GetDexFile();
+  const art::DexFile::CodeItem* code_item = art_method->GetCodeItem();
+  // TODO code_item == nullptr means that the method is abstract (or native, but we check that
+  // earlier). We should check what is returned by the RI in this situation since it's not clear
+  // what the appropriate return value is from the spec.
+  if (dex_file == nullptr || code_item == nullptr) {
+    return ERR(ABSENT_INFORMATION);
+  }
+
+  struct LocalVariableContext {
+    explicit LocalVariableContext(jvmtiEnv* jenv) : env_(jenv), variables_(), err_(OK) {}
+
+    static void Callback(void* raw_ctx, const art::DexFile::LocalInfo& entry) {
+      reinterpret_cast<LocalVariableContext*>(raw_ctx)->Insert(entry);
+    }
+
+    void Insert(const art::DexFile::LocalInfo& entry) {
+      if (err_ != OK) {
+        return;
+      }
+      JvmtiUniquePtr<char[]> name_str = CopyString(env_, entry.name_, &err_);
+      if (err_ != OK) {
+        return;
+      }
+      JvmtiUniquePtr<char[]> sig_str = CopyString(env_, entry.descriptor_, &err_);
+      if (err_ != OK) {
+        return;
+      }
+      JvmtiUniquePtr<char[]> generic_sig_str = CopyString(env_, entry.signature_, &err_);
+      if (err_ != OK) {
+        return;
+      }
+      variables_.push_back({
+        .start_location = static_cast<jlocation>(entry.start_address_),
+        .length = static_cast<jint>(entry.end_address_ - entry.start_address_),
+        .name = name_str.release(),
+        .signature = sig_str.release(),
+        .generic_signature = generic_sig_str.release(),
+        .slot = entry.reg_,
+      });
+    }
+
+    jvmtiError Release(jint* out_entry_count_ptr, jvmtiLocalVariableEntry** out_table_ptr) {
+      jlong table_size = sizeof(jvmtiLocalVariableEntry) * variables_.size();
+      if (err_ != OK ||
+          (err_ = env_->Allocate(table_size,
+                                 reinterpret_cast<unsigned char**>(out_table_ptr))) != OK) {
+        Cleanup();
+        return err_;
+      } else {
+        *out_entry_count_ptr = variables_.size();
+        memcpy(*out_table_ptr, variables_.data(), table_size);
+        return OK;
+      }
+    }
+
+    void Cleanup() {
+      for (jvmtiLocalVariableEntry& e : variables_) {
+        env_->Deallocate(reinterpret_cast<unsigned char*>(e.name));
+        env_->Deallocate(reinterpret_cast<unsigned char*>(e.signature));
+        env_->Deallocate(reinterpret_cast<unsigned char*>(e.generic_signature));
+      }
+    }
+
+    jvmtiEnv* env_;
+    std::vector<jvmtiLocalVariableEntry> variables_;
+    jvmtiError err_;
+  };
+
+  LocalVariableContext context(env);
+  if (!dex_file->DecodeDebugLocalInfo(code_item,
+                                      art_method->IsStatic(),
+                                      art_method->GetDexMethodIndex(),
+                                      LocalVariableContext::Callback,
+                                      &context)) {
+    // Something went wrong with decoding the debug information. It might as well not be there.
+    return ERR(ABSENT_INFORMATION);
+  } else {
+    return context.Release(entry_count_ptr, table_ptr);
+  }
+}
+
+jvmtiError MethodUtil::GetMaxLocals(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                    jmethodID method,
+                                    jint* max_ptr) {
+  if (method == nullptr) {
+    return ERR(INVALID_METHODID);
+  }
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+
+  if (art_method->IsNative()) {
+    return ERR(NATIVE_METHOD);
+  }
+
+  if (max_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
+    // This isn't specified as an error case, so return 0.
+    *max_ptr = 0;
+    return ERR(NONE);
+  }
+
+  DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
+  *max_ptr = art_method->GetCodeItem()->registers_size_;
+
+  return ERR(NONE);
+}
+
+jvmtiError MethodUtil::GetMethodName(jvmtiEnv* env,
+                                     jmethodID method,
+                                     char** name_ptr,
+                                     char** signature_ptr,
+                                     char** generic_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+  art_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
+
+  JvmtiUniquePtr<char[]> name_copy;
+  if (name_ptr != nullptr) {
+    const char* method_name = art_method->GetName();
+    if (method_name == nullptr) {
+      method_name = "<error>";
+    }
+    jvmtiError ret;
+    name_copy = CopyString(env, method_name, &ret);
+    if (name_copy == nullptr) {
+      return ret;
+    }
+    *name_ptr = name_copy.get();
+  }
+
+  JvmtiUniquePtr<char[]> signature_copy;
+  if (signature_ptr != nullptr) {
+    const art::Signature sig = art_method->GetSignature();
+    std::string str = sig.ToString();
+    jvmtiError ret;
+    signature_copy = CopyString(env, str.c_str(), &ret);
+    if (signature_copy == nullptr) {
+      return ret;
+    }
+    *signature_ptr = signature_copy.get();
+  }
+
+  if (generic_ptr != nullptr) {
+    *generic_ptr = nullptr;
+    if (!art_method->GetDeclaringClass()->IsProxyClass()) {
+      art::mirror::ObjectArray<art::mirror::String>* str_array =
+          art::annotations::GetSignatureAnnotationForMethod(art_method);
+      if (str_array != nullptr) {
+        std::ostringstream oss;
+        for (int32_t i = 0; i != str_array->GetLength(); ++i) {
+          oss << str_array->Get(i)->ToModifiedUtf8();
+        }
+        std::string output_string = oss.str();
+        jvmtiError ret;
+        JvmtiUniquePtr<char[]> generic_copy = CopyString(env, output_string.c_str(), &ret);
+        if (generic_copy == nullptr) {
+          return ret;
+        }
+        *generic_ptr = generic_copy.release();
+      } else if (soa.Self()->IsExceptionPending()) {
+        // TODO: Should we report an error here?
+        soa.Self()->ClearException();
+      }
+    }
+  }
+
+  // Everything is fine, release the buffers.
+  name_copy.release();
+  signature_copy.release();
+
+  return ERR(NONE);
+}
+
+jvmtiError MethodUtil::GetMethodDeclaringClass(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                               jmethodID method,
+                                               jclass* declaring_class_ptr) {
+  if (declaring_class_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+  // Note: No GetInterfaceMethodIfProxy, we want to actual class.
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::mirror::Class* klass = art_method->GetDeclaringClass();
+  *declaring_class_ptr = soa.AddLocalReference<jclass>(klass);
+
+  return ERR(NONE);
+}
+
+jvmtiError MethodUtil::GetMethodLocation(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                         jmethodID method,
+                                         jlocation* start_location_ptr,
+                                         jlocation* end_location_ptr) {
+  if (method == nullptr) {
+    return ERR(INVALID_METHODID);
+  }
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+
+  if (art_method->IsNative()) {
+    return ERR(NATIVE_METHOD);
+  }
+
+  if (start_location_ptr == nullptr || end_location_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
+    // This isn't specified as an error case, so return -1/-1 as the RI does.
+    *start_location_ptr = -1;
+    *end_location_ptr = -1;
+    return ERR(NONE);
+  }
+
+  DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
+  *start_location_ptr = 0;
+  *end_location_ptr = art_method->GetCodeItem()->insns_size_in_code_units_ - 1;
+
+  return ERR(NONE);
+}
+
+jvmtiError MethodUtil::GetMethodModifiers(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                          jmethodID method,
+                                          jint* modifiers_ptr) {
+  if (modifiers_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+  uint32_t modifiers = art_method->GetAccessFlags();
+
+  // Note: Keep this code in sync with Executable.fixMethodFlags.
+  if ((modifiers & art::kAccAbstract) != 0) {
+    modifiers &= ~art::kAccNative;
+  }
+  modifiers &= ~art::kAccSynchronized;
+  if ((modifiers & art::kAccDeclaredSynchronized) != 0) {
+    modifiers |= art::kAccSynchronized;
+  }
+  modifiers &= art::kAccJavaFlagsMask;
+
+  *modifiers_ptr = modifiers;
+  return ERR(NONE);
+}
+
+using LineNumberContext = std::vector<jvmtiLineNumberEntry>;
+
+static bool CollectLineNumbers(void* void_context, const art::DexFile::PositionInfo& entry) {
+  LineNumberContext* context = reinterpret_cast<LineNumberContext*>(void_context);
+  jvmtiLineNumberEntry jvmti_entry = { static_cast<jlocation>(entry.address_),
+                                       static_cast<jint>(entry.line_) };
+  context->push_back(jvmti_entry);
+  return false;  // Collect all, no early exit.
+}
+
+jvmtiError MethodUtil::GetLineNumberTable(jvmtiEnv* env,
+                                          jmethodID method,
+                                          jint* entry_count_ptr,
+                                          jvmtiLineNumberEntry** table_ptr) {
+  if (method == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+  DCHECK(!art_method->IsRuntimeMethod());
+
+  const art::DexFile::CodeItem* code_item;
+  const art::DexFile* dex_file;
+  {
+    art::ScopedObjectAccess soa(art::Thread::Current());
+
+    if (art_method->IsProxyMethod()) {
+      return ERR(ABSENT_INFORMATION);
+    }
+    if (art_method->IsNative()) {
+      return ERR(NATIVE_METHOD);
+    }
+    if (entry_count_ptr == nullptr || table_ptr == nullptr) {
+      return ERR(NULL_POINTER);
+    }
+
+    code_item = art_method->GetCodeItem();
+    dex_file = art_method->GetDexFile();
+    DCHECK(code_item != nullptr) << art_method->PrettyMethod() << " " << dex_file->GetLocation();
+  }
+
+  LineNumberContext context;
+  bool success = dex_file->DecodeDebugPositionInfo(code_item, CollectLineNumbers, &context);
+  if (!success) {
+    return ERR(ABSENT_INFORMATION);
+  }
+
+  unsigned char* data;
+  jlong mem_size = context.size() * sizeof(jvmtiLineNumberEntry);
+  jvmtiError alloc_error = env->Allocate(mem_size, &data);
+  if (alloc_error != ERR(NONE)) {
+    return alloc_error;
+  }
+  *table_ptr = reinterpret_cast<jvmtiLineNumberEntry*>(data);
+  memcpy(*table_ptr, context.data(), mem_size);
+  *entry_count_ptr = static_cast<jint>(context.size());
+
+  return ERR(NONE);
+}
+
+template <typename T>
+static jvmtiError IsMethodT(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                            jmethodID method,
+                            T test,
+                            jboolean* is_t_ptr) {
+  if (method == nullptr) {
+    return ERR(INVALID_METHODID);
+  }
+  if (is_t_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
+  *is_t_ptr = test(art_method) ? JNI_TRUE : JNI_FALSE;
+
+  return ERR(NONE);
+}
+
+jvmtiError MethodUtil::IsMethodNative(jvmtiEnv* env, jmethodID m, jboolean* is_native_ptr) {
+  auto test = [](art::ArtMethod* method) {
+    return method->IsNative();
+  };
+  return IsMethodT(env, m, test, is_native_ptr);
+}
+
+jvmtiError MethodUtil::IsMethodObsolete(jvmtiEnv* env, jmethodID m, jboolean* is_obsolete_ptr) {
+  auto test = [](art::ArtMethod* method) {
+    return method->IsObsolete();
+  };
+  return IsMethodT(env, m, test, is_obsolete_ptr);
+}
+
+jvmtiError MethodUtil::IsMethodSynthetic(jvmtiEnv* env, jmethodID m, jboolean* is_synthetic_ptr) {
+  auto test = [](art::ArtMethod* method) {
+    return method->IsSynthetic();
+  };
+  return IsMethodT(env, m, test, is_synthetic_ptr);
+}
+
+struct FindFrameAtDepthVisitor : art::StackVisitor {
+ public:
+  FindFrameAtDepthVisitor(art::Thread* target, art::Context* ctx, jint depth)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      : art::StackVisitor(target, ctx, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        found_frame_(false),
+        cnt_(0),
+        depth_(static_cast<size_t>(depth)) { }
+
+  bool FoundFrame() {
+    return found_frame_;
+  }
+
+  bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
+    if (GetMethod()->IsRuntimeMethod()) {
+      return true;
+    }
+    if (cnt_ == depth_) {
+      // We found our frame, exit.
+      found_frame_ = true;
+      return false;
+    } else {
+      cnt_++;
+      return true;
+    }
+  }
+
+ private:
+  bool found_frame_;
+  size_t cnt_;
+  size_t depth_;
+};
+
+class CommonLocalVariableClosure : public art::Closure {
+ public:
+  CommonLocalVariableClosure(art::Thread* caller,
+                             jint depth,
+                             jint slot)
+      : result_(ERR(INTERNAL)), caller_(caller), depth_(depth), slot_(slot) {}
+
+  void Run(art::Thread* self) OVERRIDE REQUIRES(art::Locks::mutator_lock_) {
+    art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
+    std::unique_ptr<art::Context> context(art::Context::Create());
+    FindFrameAtDepthVisitor visitor(self, context.get(), depth_);
+    visitor.WalkStack();
+    if (!visitor.FoundFrame()) {
+      // Must have been a bad depth.
+      result_ = ERR(NO_MORE_FRAMES);
+      return;
+    }
+    art::ArtMethod* method = visitor.GetMethod();
+    if (method->IsNative() || !visitor.IsShadowFrame()) {
+      // TODO We really should support get/set for non-shadow frames.
+      result_ = ERR(OPAQUE_FRAME);
+      return;
+    } else if (method->GetCodeItem()->registers_size_ <= slot_) {
+      result_ = ERR(INVALID_SLOT);
+      return;
+    }
+    uint32_t pc = visitor.GetDexPc(/*abort_on_failure*/ false);
+    if (pc == art::DexFile::kDexNoIndex) {
+      // Cannot figure out current PC.
+      result_ = ERR(OPAQUE_FRAME);
+      return;
+    }
+    std::string descriptor;
+    art::Primitive::Type slot_type = art::Primitive::kPrimVoid;
+    jvmtiError err = GetSlotType(method, pc, &descriptor, &slot_type);
+    if (err != OK) {
+      result_ = err;
+      return;
+    }
+
+    err = GetTypeError(method, slot_type, descriptor);
+    if (err != OK) {
+      result_ = err;
+      return;
+    }
+    result_ = Execute(method, visitor);
+  }
+
+  jvmtiError GetResult() const {
+    return result_;
+  }
+
+ protected:
+  virtual jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
+      REQUIRES(art::Locks::mutator_lock_) = 0;
+  virtual jvmtiError GetTypeError(art::ArtMethod* method,
+                                  art::Primitive::Type type,
+                                  const std::string& descriptor)
+      REQUIRES(art::Locks::mutator_lock_)  = 0;
+
+  jvmtiError GetSlotType(art::ArtMethod* method,
+                         uint32_t dex_pc,
+                         /*out*/std::string* descriptor,
+                         /*out*/art::Primitive::Type* type)
+      REQUIRES(art::Locks::mutator_lock_) {
+    const art::DexFile* dex_file = method->GetDexFile();
+    const art::DexFile::CodeItem* code_item = method->GetCodeItem();
+    if (dex_file == nullptr || code_item == nullptr) {
+      return ERR(OPAQUE_FRAME);
+    }
+
+    struct GetLocalVariableInfoContext {
+      explicit GetLocalVariableInfoContext(jint slot,
+                                          uint32_t pc,
+                                          std::string* out_descriptor,
+                                          art::Primitive::Type* out_type)
+          : found_(false), jslot_(slot), pc_(pc), descriptor_(out_descriptor), type_(out_type) {
+        *descriptor_ = "";
+        *type_ = art::Primitive::kPrimVoid;
+      }
+
+      static void Callback(void* raw_ctx, const art::DexFile::LocalInfo& entry) {
+        reinterpret_cast<GetLocalVariableInfoContext*>(raw_ctx)->Handle(entry);
+      }
+
+      void Handle(const art::DexFile::LocalInfo& entry) {
+        if (found_) {
+          return;
+        } else if (entry.start_address_ <= pc_ &&
+                   entry.end_address_ > pc_ &&
+                   entry.reg_ == jslot_) {
+          found_ = true;
+          *type_ = art::Primitive::GetType(entry.descriptor_[0]);
+          *descriptor_ = entry.descriptor_;
+        }
+        return;
+      }
+
+      bool found_;
+      jint jslot_;
+      uint32_t pc_;
+      std::string* descriptor_;
+      art::Primitive::Type* type_;
+    };
+
+    GetLocalVariableInfoContext context(slot_, dex_pc, descriptor, type);
+    if (!dex_file->DecodeDebugLocalInfo(code_item,
+                                        method->IsStatic(),
+                                        method->GetDexMethodIndex(),
+                                        GetLocalVariableInfoContext::Callback,
+                                        &context) || !context.found_) {
+      // Something went wrong with decoding the debug information. It might as well not be there.
+      return ERR(INVALID_SLOT);
+    } else {
+      return OK;
+    }
+  }
+
+  jvmtiError result_;
+  art::Thread* caller_;
+  jint depth_;
+  jint slot_;
+};
+
+class GetLocalVariableClosure : public CommonLocalVariableClosure {
+ public:
+  GetLocalVariableClosure(art::Thread* caller,
+                          jint depth,
+                          jint slot,
+                          art::Primitive::Type type,
+                          jvalue* val)
+      : CommonLocalVariableClosure(caller, depth, slot), type_(type), val_(val) {}
+
+ protected:
+  jvmtiError GetTypeError(art::ArtMethod* method ATTRIBUTE_UNUSED,
+                          art::Primitive::Type slot_type,
+                          const std::string& descriptor ATTRIBUTE_UNUSED)
+      OVERRIDE REQUIRES(art::Locks::mutator_lock_) {
+    switch (slot_type) {
+      case art::Primitive::kPrimByte:
+      case art::Primitive::kPrimChar:
+      case art::Primitive::kPrimInt:
+      case art::Primitive::kPrimShort:
+      case art::Primitive::kPrimBoolean:
+        return type_ == art::Primitive::kPrimInt ? OK : ERR(TYPE_MISMATCH);
+      case art::Primitive::kPrimLong:
+      case art::Primitive::kPrimFloat:
+      case art::Primitive::kPrimDouble:
+      case art::Primitive::kPrimNot:
+        return type_ == slot_type ? OK : ERR(TYPE_MISMATCH);
+      case art::Primitive::kPrimVoid:
+        LOG(FATAL) << "Unexpected primitive type " << slot_type;
+        UNREACHABLE();
+    }
+  }
+
+  jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
+      OVERRIDE REQUIRES(art::Locks::mutator_lock_) {
+    switch (type_) {
+      case art::Primitive::kPrimNot: {
+        uint32_t ptr_val;
+        if (!visitor.GetVReg(method,
+                             static_cast<uint16_t>(slot_),
+                             art::kReferenceVReg,
+                             &ptr_val)) {
+          return ERR(OPAQUE_FRAME);
+        }
+        art::ObjPtr<art::mirror::Object> obj(reinterpret_cast<art::mirror::Object*>(ptr_val));
+        val_->l = obj.IsNull() ? nullptr : caller_->GetJniEnv()->AddLocalReference<jobject>(obj);
+        break;
+      }
+      case art::Primitive::kPrimInt:
+      case art::Primitive::kPrimFloat: {
+        if (!visitor.GetVReg(method,
+                             static_cast<uint16_t>(slot_),
+                             type_ == art::Primitive::kPrimFloat ? art::kFloatVReg : art::kIntVReg,
+                             reinterpret_cast<uint32_t*>(&val_->i))) {
+          return ERR(OPAQUE_FRAME);
+        }
+        break;
+      }
+      case art::Primitive::kPrimDouble:
+      case art::Primitive::kPrimLong: {
+        auto lo_type = type_ == art::Primitive::kPrimLong ? art::kLongLoVReg : art::kDoubleLoVReg;
+        auto high_type = type_ == art::Primitive::kPrimLong ? art::kLongHiVReg : art::kDoubleHiVReg;
+        if (!visitor.GetVRegPair(method,
+                                 static_cast<uint16_t>(slot_),
+                                 lo_type,
+                                 high_type,
+                                 reinterpret_cast<uint64_t*>(&val_->j))) {
+          return ERR(OPAQUE_FRAME);
+        }
+        break;
+      }
+      default: {
+        LOG(FATAL) << "unexpected register type " << type_;
+        UNREACHABLE();
+      }
+    }
+    return OK;
+  }
+
+ private:
+  art::Primitive::Type type_;
+  jvalue* val_;
+};
+
+jvmtiError MethodUtil::GetLocalVariableGeneric(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                               jthread thread,
+                                               jint depth,
+                                               jint slot,
+                                               art::Primitive::Type type,
+                                               jvalue* val) {
+  if (depth < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  art::Thread* self = art::Thread::Current();
+  art::ScopedObjectAccess soa(self);
+  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+  art::Thread* target = ThreadUtil::GetNativeThread(thread, soa);
+  if (target == nullptr && thread == nullptr) {
+    return ERR(INVALID_THREAD);
+  }
+  if (target == nullptr) {
+    return ERR(THREAD_NOT_ALIVE);
+  }
+  GetLocalVariableClosure c(self, depth, slot, type, val);
+  if (!target->RequestSynchronousCheckpoint(&c)) {
+    return ERR(THREAD_NOT_ALIVE);
+  } else {
+    return c.GetResult();
+  }
+}
+
+class SetLocalVariableClosure : public CommonLocalVariableClosure {
+ public:
+  SetLocalVariableClosure(art::Thread* caller,
+                          jint depth,
+                          jint slot,
+                          art::Primitive::Type type,
+                          jvalue val)
+      : CommonLocalVariableClosure(caller, depth, slot), type_(type), val_(val) {}
+
+ protected:
+  jvmtiError GetTypeError(art::ArtMethod* method,
+                          art::Primitive::Type slot_type,
+                          const std::string& descriptor)
+      OVERRIDE REQUIRES(art::Locks::mutator_lock_) {
+    switch (slot_type) {
+      case art::Primitive::kPrimNot: {
+        if (type_ != art::Primitive::kPrimNot) {
+          return ERR(TYPE_MISMATCH);
+        } else if (val_.l == nullptr) {
+          return OK;
+        } else {
+          art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
+          art::ObjPtr<art::mirror::Class> set_class =
+              caller_->DecodeJObject(val_.l)->GetClass();
+          art::ObjPtr<art::mirror::ClassLoader> loader =
+              method->GetDeclaringClass()->GetClassLoader();
+          art::ObjPtr<art::mirror::Class> slot_class =
+              cl->LookupClass(caller_, descriptor.c_str(), loader);
+          DCHECK(!slot_class.IsNull());
+          return slot_class->IsAssignableFrom(set_class) ? OK : ERR(TYPE_MISMATCH);
+        }
+      }
+      case art::Primitive::kPrimByte:
+      case art::Primitive::kPrimChar:
+      case art::Primitive::kPrimInt:
+      case art::Primitive::kPrimShort:
+      case art::Primitive::kPrimBoolean:
+        return type_ == art::Primitive::kPrimInt ? OK : ERR(TYPE_MISMATCH);
+      case art::Primitive::kPrimLong:
+      case art::Primitive::kPrimFloat:
+      case art::Primitive::kPrimDouble:
+        return type_ == slot_type ? OK : ERR(TYPE_MISMATCH);
+      case art::Primitive::kPrimVoid:
+        LOG(FATAL) << "Unexpected primitive type " << slot_type;
+        UNREACHABLE();
+    }
+  }
+
+  jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
+      OVERRIDE REQUIRES(art::Locks::mutator_lock_) {
+    switch (type_) {
+      case art::Primitive::kPrimNot: {
+        uint32_t ptr_val;
+        art::ObjPtr<art::mirror::Object> obj(caller_->DecodeJObject(val_.l));
+        ptr_val = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(obj.Ptr()));
+        if (!visitor.SetVReg(method,
+                             static_cast<uint16_t>(slot_),
+                             ptr_val,
+                             art::kReferenceVReg)) {
+          return ERR(OPAQUE_FRAME);
+        }
+        break;
+      }
+      case art::Primitive::kPrimInt:
+      case art::Primitive::kPrimFloat: {
+        if (!visitor.SetVReg(method,
+                             static_cast<uint16_t>(slot_),
+                             static_cast<uint32_t>(val_.i),
+                             type_ == art::Primitive::kPrimFloat ? art::kFloatVReg
+                                                                 : art::kIntVReg)) {
+          return ERR(OPAQUE_FRAME);
+        }
+        break;
+      }
+      case art::Primitive::kPrimDouble:
+      case art::Primitive::kPrimLong: {
+        auto lo_type = type_ == art::Primitive::kPrimLong ? art::kLongLoVReg : art::kDoubleLoVReg;
+        auto high_type = type_ == art::Primitive::kPrimLong ? art::kLongHiVReg : art::kDoubleHiVReg;
+        if (!visitor.SetVRegPair(method,
+                                 static_cast<uint16_t>(slot_),
+                                 static_cast<uint64_t>(val_.j),
+                                 lo_type,
+                                 high_type)) {
+          return ERR(OPAQUE_FRAME);
+        }
+        break;
+      }
+      default: {
+        LOG(FATAL) << "unexpected register type " << type_;
+        UNREACHABLE();
+      }
+    }
+    return OK;
+  }
+
+ private:
+  art::Primitive::Type type_;
+  jvalue val_;
+};
+
+jvmtiError MethodUtil::SetLocalVariableGeneric(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                               jthread thread,
+                                               jint depth,
+                                               jint slot,
+                                               art::Primitive::Type type,
+                                               jvalue val) {
+  if (depth < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  art::Thread* self = art::Thread::Current();
+  art::ScopedObjectAccess soa(self);
+  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+  art::Thread* target = ThreadUtil::GetNativeThread(thread, soa);
+  if (target == nullptr && thread == nullptr) {
+    return ERR(INVALID_THREAD);
+  }
+  if (target == nullptr) {
+    return ERR(THREAD_NOT_ALIVE);
+  }
+  SetLocalVariableClosure c(self, depth, slot, type, val);
+  if (!target->RequestSynchronousCheckpoint(&c)) {
+    return ERR(THREAD_NOT_ALIVE);
+  } else {
+    return c.GetResult();
+  }
+}
+
+class GetLocalInstanceClosure : public art::Closure {
+ public:
+  GetLocalInstanceClosure(art::Thread* caller, jint depth, jobject* val)
+      : result_(ERR(INTERNAL)),
+        caller_(caller),
+        depth_(depth),
+        val_(val) {}
+
+  void Run(art::Thread* self) OVERRIDE REQUIRES(art::Locks::mutator_lock_) {
+    art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
+    std::unique_ptr<art::Context> context(art::Context::Create());
+    FindFrameAtDepthVisitor visitor(self, context.get(), depth_);
+    visitor.WalkStack();
+    if (!visitor.FoundFrame()) {
+      // Must have been a bad depth.
+      result_ = ERR(NO_MORE_FRAMES);
+      return;
+    }
+    art::ArtMethod* method = visitor.GetMethod();
+    if (!visitor.IsShadowFrame() && !method->IsNative() && !method->IsProxyMethod()) {
+      // TODO We really should support get/set for non-shadow frames.
+      result_ = ERR(OPAQUE_FRAME);
+      return;
+    }
+    result_ = OK;
+    art::ObjPtr<art::mirror::Object> obj = visitor.GetThisObject();
+    *val_ = obj.IsNull() ? nullptr : caller_->GetJniEnv()->AddLocalReference<jobject>(obj);
+  }
+
+  jvmtiError GetResult() const {
+    return result_;
+  }
+
+ private:
+  jvmtiError result_;
+  art::Thread* caller_;
+  jint depth_;
+  jobject* val_;
+};
+
+jvmtiError MethodUtil::GetLocalInstance(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                        jthread thread,
+                                        jint depth,
+                                        jobject* data) {
+  if (depth < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  art::Thread* self = art::Thread::Current();
+  art::ScopedObjectAccess soa(self);
+  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+  art::Thread* target = ThreadUtil::GetNativeThread(thread, soa);
+  if (target == nullptr && thread == nullptr) {
+    return ERR(INVALID_THREAD);
+  }
+  if (target == nullptr) {
+    return ERR(THREAD_NOT_ALIVE);
+  }
+  GetLocalInstanceClosure c(self, depth, data);
+  if (!target->RequestSynchronousCheckpoint(&c)) {
+    return ERR(THREAD_NOT_ALIVE);
+  } else {
+    return c.GetResult();
+  }
+}
+
+#define FOR_JVMTI_JVALUE_TYPES(fn) \
+    fn(jint, art::Primitive::kPrimInt, i) \
+    fn(jlong, art::Primitive::kPrimLong, j) \
+    fn(jfloat, art::Primitive::kPrimFloat, f) \
+    fn(jdouble, art::Primitive::kPrimDouble, d) \
+    fn(jobject, art::Primitive::kPrimNot, l)
+
+namespace impl {
+
+template<typename T> void WriteJvalue(T, jvalue*);
+template<typename T> void ReadJvalue(jvalue, T*);
+template<typename T> art::Primitive::Type GetJNIType();
+
+#define JNI_TYPE_CHAR(type, prim, id) \
+template<> art::Primitive::Type GetJNIType<type>() { \
+  return prim; \
+}
+
+FOR_JVMTI_JVALUE_TYPES(JNI_TYPE_CHAR);
+
+#undef JNI_TYPE_CHAR
+
+#define RW_JVALUE(type, prim, id) \
+    template<> void ReadJvalue<type>(jvalue in, type* out) { \
+      *out = in.id; \
+    } \
+    template<> void WriteJvalue<type>(type in, jvalue* out) { \
+      out->id = in; \
+    }
+
+FOR_JVMTI_JVALUE_TYPES(RW_JVALUE);
+
+#undef RW_JVALUE
+
+}  // namespace impl
+
+template<typename T>
+jvmtiError MethodUtil::SetLocalVariable(jvmtiEnv* env,
+                                        jthread thread,
+                                        jint depth,
+                                        jint slot,
+                                        T data) {
+  jvalue v = {.j = 0};
+  art::Primitive::Type type = impl::GetJNIType<T>();
+  impl::WriteJvalue(data, &v);
+  return SetLocalVariableGeneric(env, thread, depth, slot, type, v);
+}
+
+template<typename T>
+jvmtiError MethodUtil::GetLocalVariable(jvmtiEnv* env,
+                                        jthread thread,
+                                        jint depth,
+                                        jint slot,
+                                        T* data) {
+  if (data == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  jvalue v = {.j = 0};
+  art::Primitive::Type type = impl::GetJNIType<T>();
+  jvmtiError err = GetLocalVariableGeneric(env, thread, depth, slot, type, &v);
+  if (err != OK) {
+    return err;
+  } else {
+    impl::ReadJvalue(v, data);
+    return OK;
+  }
+}
+
+#define GET_SET_LV(type, prim, id) \
+    template jvmtiError MethodUtil::GetLocalVariable<type>(jvmtiEnv*, jthread, jint, jint, type*); \
+    template jvmtiError MethodUtil::SetLocalVariable<type>(jvmtiEnv*, jthread, jint, jint, type);
+
+FOR_JVMTI_JVALUE_TYPES(GET_SET_LV);
+
+#undef GET_SET_LV
+
+#undef FOR_JVMTI_JVALUE_TYPES
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_method.h b/openjdkjvmti/ti_method.h
new file mode 100644
index 0000000..e3578a4
--- /dev/null
+++ b/openjdkjvmti/ti_method.h
@@ -0,0 +1,114 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_METHOD_H_
+#define ART_OPENJDKJVMTI_TI_METHOD_H_
+
+#include "jni.h"
+#include "jvmti.h"
+#include "primitive.h"
+
+namespace openjdkjvmti {
+
+class EventHandler;
+
+class MethodUtil {
+ public:
+  static void Register(EventHandler* event_handler);
+  static void Unregister();
+
+  static jvmtiError GetBytecodes(jvmtiEnv* env,
+                                 jmethodID method,
+                                 jint* count_ptr,
+                                 unsigned char** bytecodes);
+
+  static jvmtiError GetArgumentsSize(jvmtiEnv* env, jmethodID method, jint* size_ptr);
+
+  static jvmtiError GetMaxLocals(jvmtiEnv* env, jmethodID method, jint* max_ptr);
+
+  static jvmtiError GetMethodName(jvmtiEnv* env,
+                                  jmethodID method,
+                                  char** name_ptr,
+                                  char** signature_ptr,
+                                  char** generic_ptr);
+
+  static jvmtiError GetMethodDeclaringClass(jvmtiEnv* env,
+                                            jmethodID method,
+                                            jclass* declaring_class_ptr);
+
+  static jvmtiError GetMethodLocation(jvmtiEnv* env,
+                                      jmethodID method,
+                                      jlocation* start_location_ptr,
+                                      jlocation* end_location_ptr);
+
+  static jvmtiError GetMethodModifiers(jvmtiEnv* env,
+                                       jmethodID method,
+                                       jint* modifiers_ptr);
+
+  static jvmtiError GetLineNumberTable(jvmtiEnv* env,
+                                       jmethodID method,
+                                       jint* entry_count_ptr,
+                                       jvmtiLineNumberEntry** table_ptr);
+
+  static jvmtiError IsMethodNative(jvmtiEnv* env, jmethodID method, jboolean* is_native_ptr);
+  static jvmtiError IsMethodObsolete(jvmtiEnv* env, jmethodID method, jboolean* is_obsolete_ptr);
+  static jvmtiError IsMethodSynthetic(jvmtiEnv* env, jmethodID method, jboolean* is_synthetic_ptr);
+  static jvmtiError GetLocalVariableTable(jvmtiEnv* env,
+                                          jmethodID method,
+                                          jint* entry_count_ptr,
+                                          jvmtiLocalVariableEntry** table_ptr);
+
+  template<typename T>
+  static jvmtiError SetLocalVariable(jvmtiEnv* env, jthread thread, jint depth, jint slot, T data);
+
+  template<typename T>
+  static jvmtiError GetLocalVariable(jvmtiEnv* env, jthread thread, jint depth, jint slot, T* data);
+
+  static jvmtiError GetLocalInstance(jvmtiEnv* env, jthread thread, jint depth, jobject* data);
+
+ private:
+  static jvmtiError SetLocalVariableGeneric(jvmtiEnv* env,
+                                            jthread thread,
+                                            jint depth,
+                                            jint slot,
+                                            art::Primitive::Type type,
+                                            jvalue value);
+  static jvmtiError GetLocalVariableGeneric(jvmtiEnv* env,
+                                            jthread thread,
+                                            jint depth,
+                                            jint slot,
+                                            art::Primitive::Type type,
+                                            jvalue* value);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_METHOD_H_
diff --git a/openjdkjvmti/ti_monitor.cc b/openjdkjvmti/ti_monitor.cc
new file mode 100644
index 0000000..61bf533
--- /dev/null
+++ b/openjdkjvmti/ti_monitor.cc
@@ -0,0 +1,302 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_monitor.h"
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include "art_jvmti.h"
+#include "runtime.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+
+namespace openjdkjvmti {
+
+// We cannot use ART monitors, as they require the mutator lock for contention locking. We
+// also cannot use pthread mutexes and condition variables (or C++11 abstractions) directly,
+// as the do not have the right semantics for recursive mutexes and waiting (wait only unlocks
+// the mutex once).
+// So go ahead and use a wrapper that does the counting explicitly.
+
+class JvmtiMonitor {
+ public:
+  JvmtiMonitor() : owner_(nullptr), count_(0) {
+  }
+
+  static bool Destroy(art::Thread* self, JvmtiMonitor* monitor) NO_THREAD_SAFETY_ANALYSIS {
+    // Check whether this thread holds the monitor, or nobody does.
+    art::Thread* owner_thread = monitor->owner_.load(std::memory_order_relaxed);
+    if (owner_thread != nullptr && self != owner_thread) {
+      return false;
+    }
+
+    if (monitor->count_ > 0) {
+      monitor->count_ = 0;
+      monitor->owner_.store(nullptr, std::memory_order_relaxed);
+      monitor->mutex_.unlock();
+    }
+
+    delete monitor;
+    return true;
+  }
+
+  void MonitorEnter(art::Thread* self) NO_THREAD_SAFETY_ANALYSIS {
+    // Check for recursive enter.
+    if (IsOwner(self)) {
+      count_++;
+      return;
+    }
+
+    mutex_.lock();
+
+    DCHECK(owner_.load(std::memory_order_relaxed) == nullptr);
+    owner_.store(self, std::memory_order_relaxed);
+    DCHECK_EQ(0u, count_);
+    count_ = 1;
+  }
+
+  bool MonitorExit(art::Thread* self) NO_THREAD_SAFETY_ANALYSIS {
+    if (!IsOwner(self)) {
+      return false;
+    }
+
+    --count_;
+    if (count_ == 0u) {
+      owner_.store(nullptr, std::memory_order_relaxed);
+      mutex_.unlock();
+    }
+
+    return true;
+  }
+
+  bool Wait(art::Thread* self) {
+    auto wait_without_timeout = [&](std::unique_lock<std::mutex>& lk) {
+      cond_.wait(lk);
+    };
+    return Wait(self, wait_without_timeout);
+  }
+
+  bool Wait(art::Thread* self, uint64_t timeout_in_ms) {
+    auto wait_with_timeout = [&](std::unique_lock<std::mutex>& lk) {
+      cond_.wait_for(lk, std::chrono::milliseconds(timeout_in_ms));
+    };
+    return Wait(self, wait_with_timeout);
+  }
+
+  bool Notify(art::Thread* self) {
+    return Notify(self, [&]() { cond_.notify_one(); });
+  }
+
+  bool NotifyAll(art::Thread* self) {
+    return Notify(self, [&]() { cond_.notify_all(); });
+  }
+
+ private:
+  bool IsOwner(art::Thread* self) {
+    // There's a subtle correctness argument here for a relaxed load outside the critical section.
+    // A thread is guaranteed to see either its own latest store or another thread's store. If a
+    // thread sees another thread's store than it cannot be holding the lock.
+    art::Thread* owner_thread = owner_.load(std::memory_order_relaxed);
+    return self == owner_thread;
+  }
+
+  template <typename T>
+  bool Wait(art::Thread* self, T how_to_wait) {
+    if (!IsOwner(self)) {
+      return false;
+    }
+
+    size_t old_count = count_;
+
+    count_ = 0;
+    owner_.store(nullptr, std::memory_order_relaxed);
+
+    {
+      std::unique_lock<std::mutex> lk(mutex_, std::adopt_lock);
+      how_to_wait(lk);
+      lk.release();  // Do not unlock the mutex.
+    }
+
+    DCHECK(owner_.load(std::memory_order_relaxed) == nullptr);
+    owner_.store(self, std::memory_order_relaxed);
+    DCHECK_EQ(0u, count_);
+    count_ = old_count;
+
+    return true;
+  }
+
+  template <typename T>
+  bool Notify(art::Thread* self, T how_to_notify) {
+    if (!IsOwner(self)) {
+      return false;
+    }
+
+    how_to_notify();
+
+    return true;
+  }
+
+  std::mutex mutex_;
+  std::condition_variable cond_;
+  std::atomic<art::Thread*> owner_;
+  size_t count_;
+};
+
+static jrawMonitorID EncodeMonitor(JvmtiMonitor* monitor) {
+  return reinterpret_cast<jrawMonitorID>(monitor);
+}
+
+static JvmtiMonitor* DecodeMonitor(jrawMonitorID id) {
+  return reinterpret_cast<JvmtiMonitor*>(id);
+}
+
+jvmtiError MonitorUtil::CreateRawMonitor(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                         const char* name,
+                                         jrawMonitorID* monitor_ptr) {
+  if (name == nullptr || monitor_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  JvmtiMonitor* monitor = new JvmtiMonitor();
+  *monitor_ptr = EncodeMonitor(monitor);
+
+  return ERR(NONE);
+}
+
+jvmtiError MonitorUtil::DestroyRawMonitor(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
+  if (id == nullptr) {
+    return ERR(INVALID_MONITOR);
+  }
+
+  JvmtiMonitor* monitor = DecodeMonitor(id);
+  art::Thread* self = art::Thread::Current();
+
+  if (!JvmtiMonitor::Destroy(self, monitor)) {
+    return ERR(NOT_MONITOR_OWNER);
+  }
+
+  return ERR(NONE);
+}
+
+jvmtiError MonitorUtil::RawMonitorEnter(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
+  if (id == nullptr) {
+    return ERR(INVALID_MONITOR);
+  }
+
+  JvmtiMonitor* monitor = DecodeMonitor(id);
+  art::Thread* self = art::Thread::Current();
+
+  monitor->MonitorEnter(self);
+
+  return ERR(NONE);
+}
+
+jvmtiError MonitorUtil::RawMonitorExit(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
+  if (id == nullptr) {
+    return ERR(INVALID_MONITOR);
+  }
+
+  JvmtiMonitor* monitor = DecodeMonitor(id);
+  art::Thread* self = art::Thread::Current();
+
+  if (!monitor->MonitorExit(self)) {
+    return ERR(NOT_MONITOR_OWNER);
+  }
+
+  return ERR(NONE);
+}
+
+jvmtiError MonitorUtil::RawMonitorWait(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                       jrawMonitorID id,
+                                       jlong millis) {
+  if (id == nullptr) {
+    return ERR(INVALID_MONITOR);
+  }
+
+  JvmtiMonitor* monitor = DecodeMonitor(id);
+  art::Thread* self = art::Thread::Current();
+
+  // This is not in the spec, but it's the only thing that makes sense (and agrees with
+  // Object.wait).
+  if (millis < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+
+  bool result = (millis > 0)
+      ? monitor->Wait(self, static_cast<uint64_t>(millis))
+      : monitor->Wait(self);
+
+  if (!result) {
+    return ERR(NOT_MONITOR_OWNER);
+  }
+
+  // TODO: Make sure that is really what we should be checking here.
+  if (self->IsInterrupted()) {
+    return ERR(INTERRUPT);
+  }
+
+  return ERR(NONE);
+}
+
+jvmtiError MonitorUtil::RawMonitorNotify(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
+  if (id == nullptr) {
+    return ERR(INVALID_MONITOR);
+  }
+
+  JvmtiMonitor* monitor = DecodeMonitor(id);
+  art::Thread* self = art::Thread::Current();
+
+  if (!monitor->Notify(self)) {
+    return ERR(NOT_MONITOR_OWNER);
+  }
+
+  return ERR(NONE);
+}
+
+jvmtiError MonitorUtil::RawMonitorNotifyAll(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
+  if (id == nullptr) {
+    return ERR(INVALID_MONITOR);
+  }
+
+  JvmtiMonitor* monitor = DecodeMonitor(id);
+  art::Thread* self = art::Thread::Current();
+
+  if (!monitor->NotifyAll(self)) {
+    return ERR(NOT_MONITOR_OWNER);
+  }
+
+  return ERR(NONE);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_monitor.h b/openjdkjvmti/ti_monitor.h
new file mode 100644
index 0000000..add089c
--- /dev/null
+++ b/openjdkjvmti/ti_monitor.h
@@ -0,0 +1,59 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_MONITOR_H_
+#define ART_OPENJDKJVMTI_TI_MONITOR_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class MonitorUtil {
+ public:
+  static jvmtiError CreateRawMonitor(jvmtiEnv* env, const char* name, jrawMonitorID* monitor_ptr);
+
+  static jvmtiError DestroyRawMonitor(jvmtiEnv* env, jrawMonitorID monitor);
+
+  static jvmtiError RawMonitorEnter(jvmtiEnv* env, jrawMonitorID monitor);
+
+  static jvmtiError RawMonitorExit(jvmtiEnv* env, jrawMonitorID monitor);
+
+  static jvmtiError RawMonitorWait(jvmtiEnv* env, jrawMonitorID monitor, jlong millis);
+
+  static jvmtiError RawMonitorNotify(jvmtiEnv* env, jrawMonitorID monitor);
+
+  static jvmtiError RawMonitorNotifyAll(jvmtiEnv* env, jrawMonitorID monitor);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_MONITOR_H_
diff --git a/openjdkjvmti/ti_object.cc b/openjdkjvmti/ti_object.cc
new file mode 100644
index 0000000..2506aca
--- /dev/null
+++ b/openjdkjvmti/ti_object.cc
@@ -0,0 +1,76 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_object.h"
+
+#include "art_jvmti.h"
+#include "mirror/object-inl.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+
+namespace openjdkjvmti {
+
+jvmtiError ObjectUtil::GetObjectSize(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                     jobject jobject,
+                                     jlong* size_ptr) {
+  if (jobject == nullptr) {
+    return ERR(INVALID_OBJECT);
+  }
+  if (size_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Object> object = soa.Decode<art::mirror::Object>(jobject);
+
+  *size_ptr = object->SizeOf();
+  return ERR(NONE);
+}
+
+jvmtiError ObjectUtil::GetObjectHashCode(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                         jobject jobject,
+                                         jint* hash_code_ptr) {
+  if (jobject == nullptr) {
+    return ERR(INVALID_OBJECT);
+  }
+  if (hash_code_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Object> object = soa.Decode<art::mirror::Object>(jobject);
+
+  *hash_code_ptr = object->IdentityHashCode();
+
+  return ERR(NONE);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_object.h b/openjdkjvmti/ti_object.h
new file mode 100644
index 0000000..fa3bd0f
--- /dev/null
+++ b/openjdkjvmti/ti_object.h
@@ -0,0 +1,49 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_OBJECT_H_
+#define ART_OPENJDKJVMTI_TI_OBJECT_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class ObjectUtil {
+ public:
+  static jvmtiError GetObjectSize(jvmtiEnv* env, jobject object, jlong* size_ptr);
+
+  static jvmtiError GetObjectHashCode(jvmtiEnv* env, jobject object, jint* hash_code_ptr);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_OBJECT_H_
diff --git a/openjdkjvmti/ti_phase.cc b/openjdkjvmti/ti_phase.cc
new file mode 100644
index 0000000..8893c9b
--- /dev/null
+++ b/openjdkjvmti/ti_phase.cc
@@ -0,0 +1,155 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_phase.h"
+
+#include "art_jvmti.h"
+#include "base/macros.h"
+#include "events-inl.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "runtime.h"
+#include "runtime_callbacks.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+#include "thread_list.h"
+#include "ti_thread.h"
+
+namespace openjdkjvmti {
+
+jvmtiPhase PhaseUtil::current_phase_ = static_cast<jvmtiPhase>(0);
+
+struct PhaseUtil::PhaseCallback : public art::RuntimePhaseCallback {
+  inline static JNIEnv* GetJniEnv() {
+    return reinterpret_cast<JNIEnv*>(art::Thread::Current()->GetJniEnv());
+  }
+
+  inline static jthread GetCurrentJThread() {
+    art::ScopedObjectAccess soa(art::Thread::Current());
+    return soa.AddLocalReference<jthread>(soa.Self()->GetPeer());
+  }
+
+  void NextRuntimePhase(RuntimePhase phase) REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
+    switch (phase) {
+      case RuntimePhase::kInitialAgents:
+        PhaseUtil::current_phase_ = JVMTI_PHASE_PRIMORDIAL;
+        break;
+      case RuntimePhase::kStart:
+        {
+          art::ScopedThreadSuspension sts(art::Thread::Current(), art::ThreadState::kNative);
+          event_handler->DispatchEvent<ArtJvmtiEvent::kVmStart>(nullptr, GetJniEnv());
+          PhaseUtil::current_phase_ = JVMTI_PHASE_START;
+        }
+        break;
+      case RuntimePhase::kInit:
+        {
+          ThreadUtil::CacheData();
+          ScopedLocalRef<jthread> thread(GetJniEnv(), GetCurrentJThread());
+          art::ScopedThreadSuspension sts(art::Thread::Current(), art::ThreadState::kNative);
+          event_handler->DispatchEvent<ArtJvmtiEvent::kVmInit>(nullptr, GetJniEnv(), thread.get());
+          PhaseUtil::current_phase_ = JVMTI_PHASE_LIVE;
+        }
+        break;
+      case RuntimePhase::kDeath:
+        {
+          art::ScopedThreadSuspension sts(art::Thread::Current(), art::ThreadState::kNative);
+          event_handler->DispatchEvent<ArtJvmtiEvent::kVmDeath>(nullptr, GetJniEnv());
+          PhaseUtil::current_phase_ = JVMTI_PHASE_DEAD;
+        }
+        // TODO: Block events now.
+        break;
+    }
+  }
+
+  EventHandler* event_handler = nullptr;
+};
+
+PhaseUtil::PhaseCallback gPhaseCallback;
+
+jvmtiError PhaseUtil::GetPhase(jvmtiEnv* env ATTRIBUTE_UNUSED, jvmtiPhase* phase_ptr) {
+  if (phase_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  jvmtiPhase now = PhaseUtil::current_phase_;
+  DCHECK(now == JVMTI_PHASE_ONLOAD ||
+         now == JVMTI_PHASE_PRIMORDIAL ||
+         now == JVMTI_PHASE_START ||
+         now == JVMTI_PHASE_LIVE ||
+         now == JVMTI_PHASE_DEAD);
+  *phase_ptr = now;
+  return ERR(NONE);
+}
+
+bool PhaseUtil::IsLivePhase() {
+  jvmtiPhase now = PhaseUtil::current_phase_;
+  DCHECK(now == JVMTI_PHASE_ONLOAD ||
+         now == JVMTI_PHASE_PRIMORDIAL ||
+         now == JVMTI_PHASE_START ||
+         now == JVMTI_PHASE_LIVE ||
+         now == JVMTI_PHASE_DEAD);
+  return now == JVMTI_PHASE_LIVE;
+}
+
+void PhaseUtil::SetToOnLoad() {
+  DCHECK_EQ(0u, static_cast<size_t>(PhaseUtil::current_phase_));
+  PhaseUtil::current_phase_ = JVMTI_PHASE_ONLOAD;
+}
+
+void PhaseUtil::SetToPrimordial() {
+  DCHECK_EQ(static_cast<size_t>(JVMTI_PHASE_ONLOAD), static_cast<size_t>(PhaseUtil::current_phase_));
+  PhaseUtil::current_phase_ = JVMTI_PHASE_ONLOAD;
+}
+
+void PhaseUtil::SetToLive() {
+  DCHECK_EQ(static_cast<size_t>(0), static_cast<size_t>(PhaseUtil::current_phase_));
+  ThreadUtil::CacheData();
+  PhaseUtil::current_phase_ = JVMTI_PHASE_LIVE;
+}
+
+void PhaseUtil::Register(EventHandler* handler) {
+  gPhaseCallback.event_handler = handler;
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Add phase callback");
+  art::Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&gPhaseCallback);
+}
+
+void PhaseUtil::Unregister() {
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Remove phase callback");
+  art::Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&gPhaseCallback);
+}
+
+jvmtiPhase PhaseUtil::GetPhaseUnchecked() {
+  return PhaseUtil::current_phase_;
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_phase.h b/openjdkjvmti/ti_phase.h
new file mode 100644
index 0000000..d4ed86b
--- /dev/null
+++ b/openjdkjvmti/ti_phase.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_PHASE_H_
+#define ART_OPENJDKJVMTI_TI_PHASE_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class EventHandler;
+
+class PhaseUtil {
+ public:
+  static jvmtiError GetPhase(jvmtiEnv* env, jvmtiPhase* phase_ptr);
+  static bool IsLivePhase();
+
+  static void Register(EventHandler* event_handler);
+  static void Unregister();
+
+  // Move the phase from unitialized to LOAD.
+  static void SetToOnLoad();
+
+  // Move the phase from LOAD to PRIMORDIAL.
+  static void SetToPrimordial();
+
+  // Move the phase from unitialized to LIVE.
+  static void SetToLive();
+
+  struct PhaseCallback;
+
+  static jvmtiPhase GetPhaseUnchecked();
+
+ private:
+  static jvmtiPhase current_phase_;
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_PHASE_H_
diff --git a/openjdkjvmti/ti_properties.cc b/openjdkjvmti/ti_properties.cc
new file mode 100644
index 0000000..c412814
--- /dev/null
+++ b/openjdkjvmti/ti_properties.cc
@@ -0,0 +1,236 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_properties.h"
+
+#include <string.h>
+#include <vector>
+
+#include "jni.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "nativehelper/ScopedUtfChars.h"
+
+#include "art_jvmti.h"
+#include "runtime.h"
+#include "thread-current-inl.h"
+#include "ti_phase.h"
+#include "well_known_classes.h"
+
+namespace openjdkjvmti {
+
+// Hardcoded properties. Tests ensure that these are consistent with libcore's view, as seen
+// in System.java and AndroidHardcodedSystemProperties.java.
+static constexpr const char* kProperties[][2] = {
+    // Recommended by the spec.
+    { "java.vm.vendor", "The Android Project" },
+    { "java.vm.version", "2.1.0" },  // This is Runtime::GetVersion().
+    { "java.vm.name", "Dalvik" },
+    // Android does not provide java.vm.info.
+    //
+    // These are other values provided by AndroidHardcodedSystemProperties.
+    { "java.class.version", "50.0" },
+    { "java.version", "0" },
+    { "java.compiler", "" },
+    { "java.ext.dirs", "" },
+
+    { "java.specification.name", "Dalvik Core Library" },
+    { "java.specification.vendor", "The Android Project" },
+    { "java.specification.version", "0.9" },
+
+    { "java.vendor", "The Android Project" },
+    { "java.vendor.url", "http://www.android.com/" },
+    { "java.vm.name", "Dalvik" },
+    { "java.vm.specification.name", "Dalvik Virtual Machine Specification" },
+    { "java.vm.specification.vendor", "The Android Project" },
+    { "java.vm.specification.version", "0.9" },
+    { "java.vm.vendor", "The Android Project" },
+
+    { "java.vm.vendor.url", "http://www.android.com/" },
+
+    { "java.net.preferIPv6Addresses", "false" },
+
+    { "file.encoding", "UTF-8" },
+
+    { "file.separator", "/" },
+    { "line.separator", "\n" },
+    { "path.separator", ":" },
+
+    { "os.name", "Linux" },
+};
+static constexpr size_t kPropertiesSize = arraysize(kProperties);
+static constexpr const char* kPropertyLibraryPath = "java.library.path";
+static constexpr const char* kPropertyClassPath = "java.class.path";
+
+jvmtiError PropertiesUtil::GetSystemProperties(jvmtiEnv* env,
+                                               jint* count_ptr,
+                                               char*** property_ptr) {
+  if (count_ptr == nullptr || property_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  jvmtiError array_alloc_result;
+  JvmtiUniquePtr<char*[]> array_data_ptr = AllocJvmtiUniquePtr<char*[]>(env,
+                                                                        kPropertiesSize + 2,
+                                                                        &array_alloc_result);
+  if (array_data_ptr == nullptr) {
+    return array_alloc_result;
+  }
+
+  std::vector<JvmtiUniquePtr<char[]>> property_copies;
+
+  {
+    jvmtiError libpath_result;
+    JvmtiUniquePtr<char[]> libpath_data = CopyString(env, kPropertyLibraryPath, &libpath_result);
+    if (libpath_data == nullptr) {
+      return libpath_result;
+    }
+    array_data_ptr.get()[0] = libpath_data.get();
+    property_copies.push_back(std::move(libpath_data));
+  }
+
+  {
+    jvmtiError classpath_result;
+    JvmtiUniquePtr<char[]> classpath_data = CopyString(env, kPropertyClassPath, &classpath_result);
+    if (classpath_data == nullptr) {
+      return classpath_result;
+    }
+    array_data_ptr.get()[1] = classpath_data.get();
+    property_copies.push_back(std::move(classpath_data));
+  }
+
+  for (size_t i = 0; i != kPropertiesSize; ++i) {
+    jvmtiError data_result;
+    JvmtiUniquePtr<char[]> data = CopyString(env, kProperties[i][0], &data_result);
+    if (data == nullptr) {
+      return data_result;
+    }
+    array_data_ptr.get()[i + 2] = data.get();
+    property_copies.push_back(std::move(data));
+  }
+
+  // Everything is OK, release the data.
+  *count_ptr = kPropertiesSize + 2;
+  *property_ptr = array_data_ptr.release();
+  for (auto& uptr : property_copies) {
+    uptr.release();
+  }
+
+  return ERR(NONE);
+}
+
+static jvmtiError Copy(jvmtiEnv* env, const char* in, char** out) {
+  jvmtiError result;
+  JvmtiUniquePtr<char[]> data = CopyString(env, in, &result);
+  *out = data.release();
+  return result;
+}
+
+// See dalvik_system_VMRuntime.cpp.
+static const char* DefaultToDot(const std::string& class_path) {
+  return class_path.empty() ? "." : class_path.c_str();
+}
+
+// Handle kPropertyLibraryPath.
+static jvmtiError GetLibraryPath(jvmtiEnv* env, char** value_ptr) {
+  const std::vector<std::string>& runtime_props = art::Runtime::Current()->GetProperties();
+  for (const std::string& prop_assignment : runtime_props) {
+    size_t assign_pos = prop_assignment.find('=');
+    if (assign_pos != std::string::npos && assign_pos > 0) {
+      if (prop_assignment.substr(0, assign_pos) == kPropertyLibraryPath) {
+        return Copy(env, prop_assignment.substr(assign_pos + 1).c_str(), value_ptr);
+      }
+    }
+  }
+  if (!PhaseUtil::IsLivePhase()) {
+    return ERR(NOT_AVAILABLE);
+  }
+  // We expect this call to be rare. So don't optimize.
+  DCHECK(art::Thread::Current() != nullptr);
+  JNIEnv* jni_env = art::Thread::Current()->GetJniEnv();
+  jmethodID get_prop = jni_env->GetStaticMethodID(art::WellKnownClasses::java_lang_System,
+                                                  "getProperty",
+                                                  "(Ljava/lang/String;)Ljava/lang/String;");
+  CHECK(get_prop != nullptr);
+
+  ScopedLocalRef<jobject> input_str(jni_env, jni_env->NewStringUTF(kPropertyLibraryPath));
+  if (input_str.get() == nullptr) {
+    jni_env->ExceptionClear();
+    return ERR(OUT_OF_MEMORY);
+  }
+
+  ScopedLocalRef<jobject> prop_res(
+      jni_env, jni_env->CallStaticObjectMethod(art::WellKnownClasses::java_lang_System,
+                                               get_prop,
+                                               input_str.get()));
+  if (jni_env->ExceptionCheck() == JNI_TRUE) {
+    jni_env->ExceptionClear();
+    return ERR(INTERNAL);
+  }
+  if (prop_res.get() == nullptr) {
+    *value_ptr = nullptr;
+    return ERR(NONE);
+  }
+
+  ScopedUtfChars chars(jni_env, reinterpret_cast<jstring>(prop_res.get()));
+  return Copy(env, chars.c_str(), value_ptr);
+}
+
+jvmtiError PropertiesUtil::GetSystemProperty(jvmtiEnv* env,
+                                             const char* property,
+                                             char** value_ptr) {
+  if (property == nullptr || value_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  if (strcmp(property, kPropertyLibraryPath) == 0) {
+    return GetLibraryPath(env, value_ptr);
+  }
+
+  if (strcmp(property, kPropertyClassPath) == 0) {
+    return Copy(env, DefaultToDot(art::Runtime::Current()->GetClassPathString()), value_ptr);
+  }
+
+  for (size_t i = 0; i != kPropertiesSize; ++i) {
+    if (strcmp(property, kProperties[i][0]) == 0) {
+      return Copy(env, kProperties[i][1], value_ptr);
+    }
+  }
+
+  return ERR(NOT_AVAILABLE);
+}
+
+jvmtiError PropertiesUtil::SetSystemProperty(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                             const char* property ATTRIBUTE_UNUSED,
+                                             const char* value ATTRIBUTE_UNUSED) {
+  // We do not allow manipulation of any property here.
+  return ERR(NOT_AVAILABLE);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_properties.h b/openjdkjvmti/ti_properties.h
new file mode 100644
index 0000000..187b85d
--- /dev/null
+++ b/openjdkjvmti/ti_properties.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_PROPERTIES_H_
+#define ART_OPENJDKJVMTI_TI_PROPERTIES_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class PropertiesUtil {
+ public:
+  static jvmtiError GetSystemProperties(jvmtiEnv* env, jint* count_ptr, char*** property_ptr);
+
+  static jvmtiError GetSystemProperty(jvmtiEnv* env, const char* property, char** value_ptr);
+
+  static jvmtiError SetSystemProperty(jvmtiEnv* env, const char* property, const char* value);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_PROPERTIES_H_
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
new file mode 100644
index 0000000..c679d73
--- /dev/null
+++ b/openjdkjvmti/ti_redefine.cc
@@ -0,0 +1,1517 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_redefine.h"
+
+#include <limits>
+
+#include "android-base/stringprintf.h"
+
+#include "art_field-inl.h"
+#include "art_jvmti.h"
+#include "art_method-inl.h"
+#include "base/array_ref.h"
+#include "base/logging.h"
+#include "base/stringpiece.h"
+#include "class_linker-inl.h"
+#include "debugger.h"
+#include "dex_file.h"
+#include "dex_file_types.h"
+#include "events-inl.h"
+#include "gc/allocation_listener.h"
+#include "gc/heap.h"
+#include "instrumentation.h"
+#include "intern_table.h"
+#include "jdwp/jdwp.h"
+#include "jdwp/jdwp_constants.h"
+#include "jdwp/jdwp_event.h"
+#include "jdwp/object_registry.h"
+#include "jit/jit.h"
+#include "jit/jit_code_cache.h"
+#include "jni_env_ext-inl.h"
+#include "jvmti_allocator.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_ext.h"
+#include "mirror/object.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "non_debuggable_classes.h"
+#include "object_lock.h"
+#include "runtime.h"
+#include "ti_breakpoint.h"
+#include "ti_class_loader.h"
+#include "transform.h"
+#include "verifier/method_verifier.h"
+#include "verifier/verifier_enums.h"
+
+namespace openjdkjvmti {
+
+using android::base::StringPrintf;
+
+// A helper that fills in a classes obsolete_methods_ and obsolete_dex_caches_ classExt fields as
+// they are created. This ensures that we can always call any method of an obsolete ArtMethod object
+// almost as soon as they are created since the GetObsoleteDexCache method will succeed.
+class ObsoleteMap {
+ public:
+  art::ArtMethod* FindObsoleteVersion(art::ArtMethod* original)
+      REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
+    auto method_pair = id_map_.find(original);
+    if (method_pair != id_map_.end()) {
+      art::ArtMethod* res = obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
+          method_pair->second, art::kRuntimePointerSize);
+      DCHECK(res != nullptr);
+      DCHECK_EQ(original, res->GetNonObsoleteMethod());
+      return res;
+    } else {
+      return nullptr;
+    }
+  }
+
+  void RecordObsolete(art::ArtMethod* original, art::ArtMethod* obsolete)
+      REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
+    DCHECK(original != nullptr);
+    DCHECK(obsolete != nullptr);
+    int32_t slot = next_free_slot_++;
+    DCHECK_LT(slot, obsolete_methods_->GetLength());
+    DCHECK(nullptr ==
+           obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(slot, art::kRuntimePointerSize));
+    DCHECK(nullptr == obsolete_dex_caches_->Get(slot));
+    obsolete_methods_->SetElementPtrSize(slot, obsolete, art::kRuntimePointerSize);
+    obsolete_dex_caches_->Set(slot, original_dex_cache_);
+    id_map_.insert({original, slot});
+  }
+
+  ObsoleteMap(art::ObjPtr<art::mirror::PointerArray> obsolete_methods,
+              art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches,
+              art::ObjPtr<art::mirror::DexCache> original_dex_cache)
+      : next_free_slot_(0),
+        obsolete_methods_(obsolete_methods),
+        obsolete_dex_caches_(obsolete_dex_caches),
+        original_dex_cache_(original_dex_cache) {
+    // Figure out where the first unused slot in the obsolete_methods_ array is.
+    while (obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
+        next_free_slot_, art::kRuntimePointerSize) != nullptr) {
+      DCHECK(obsolete_dex_caches_->Get(next_free_slot_) != nullptr);
+      next_free_slot_++;
+    }
+    // Sanity check that the same slot in obsolete_dex_caches_ is free.
+    DCHECK(obsolete_dex_caches_->Get(next_free_slot_) == nullptr);
+  }
+
+ private:
+  int32_t next_free_slot_;
+  std::unordered_map<art::ArtMethod*, int32_t> id_map_;
+  // Pointers to the fields in mirror::ClassExt. These can be held as ObjPtr since this is only used
+  // when we have an exclusive mutator_lock_ (i.e. all threads are suspended).
+  art::ObjPtr<art::mirror::PointerArray> obsolete_methods_;
+  art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches_;
+  art::ObjPtr<art::mirror::DexCache> original_dex_cache_;
+};
+
+// This visitor walks thread stacks and allocates and sets up the obsolete methods. It also does
+// some basic sanity checks that the obsolete method is sane.
+class ObsoleteMethodStackVisitor : public art::StackVisitor {
+ protected:
+  ObsoleteMethodStackVisitor(
+      art::Thread* thread,
+      art::LinearAlloc* allocator,
+      const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
+      ObsoleteMap* obsolete_maps)
+        : StackVisitor(thread,
+                       /*context*/nullptr,
+                       StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+          allocator_(allocator),
+          obsoleted_methods_(obsoleted_methods),
+          obsolete_maps_(obsolete_maps) { }
+
+  ~ObsoleteMethodStackVisitor() OVERRIDE {}
+
+ public:
+  // Returns true if we successfully installed obsolete methods on this thread, filling
+  // obsolete_maps_ with the translations if needed. Returns false and fills error_msg if we fail.
+  // The stack is cleaned up when we fail.
+  static void UpdateObsoleteFrames(
+      art::Thread* thread,
+      art::LinearAlloc* allocator,
+      const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
+      ObsoleteMap* obsolete_maps)
+        REQUIRES(art::Locks::mutator_lock_) {
+    ObsoleteMethodStackVisitor visitor(thread,
+                                       allocator,
+                                       obsoleted_methods,
+                                       obsolete_maps);
+    visitor.WalkStack();
+  }
+
+  bool VisitFrame() OVERRIDE REQUIRES(art::Locks::mutator_lock_) {
+    art::ScopedAssertNoThreadSuspension snts("Fixing up the stack for obsolete methods.");
+    art::ArtMethod* old_method = GetMethod();
+    if (obsoleted_methods_.find(old_method) != obsoleted_methods_.end()) {
+      // We cannot ensure that the right dex file is used in inlined frames so we don't support
+      // redefining them.
+      DCHECK(!IsInInlinedFrame()) << "Inlined frames are not supported when using redefinition";
+      art::ArtMethod* new_obsolete_method = obsolete_maps_->FindObsoleteVersion(old_method);
+      if (new_obsolete_method == nullptr) {
+        // Create a new Obsolete Method and put it in the list.
+        art::Runtime* runtime = art::Runtime::Current();
+        art::ClassLinker* cl = runtime->GetClassLinker();
+        auto ptr_size = cl->GetImagePointerSize();
+        const size_t method_size = art::ArtMethod::Size(ptr_size);
+        auto* method_storage = allocator_->Alloc(art::Thread::Current(), method_size);
+        CHECK(method_storage != nullptr) << "Unable to allocate storage for obsolete version of '"
+                                         << old_method->PrettyMethod() << "'";
+        new_obsolete_method = new (method_storage) art::ArtMethod();
+        new_obsolete_method->CopyFrom(old_method, ptr_size);
+        DCHECK_EQ(new_obsolete_method->GetDeclaringClass(), old_method->GetDeclaringClass());
+        new_obsolete_method->SetIsObsolete();
+        new_obsolete_method->SetDontCompile();
+        cl->SetEntryPointsForObsoleteMethod(new_obsolete_method);
+        obsolete_maps_->RecordObsolete(old_method, new_obsolete_method);
+        // Update JIT Data structures to point to the new method.
+        art::jit::Jit* jit = art::Runtime::Current()->GetJit();
+        if (jit != nullptr) {
+          // Notify the JIT we are making this obsolete method. It will update the jit's internal
+          // structures to keep track of the new obsolete method.
+          jit->GetCodeCache()->MoveObsoleteMethod(old_method, new_obsolete_method);
+        }
+      }
+      DCHECK(new_obsolete_method != nullptr);
+      SetMethod(new_obsolete_method);
+    }
+    return true;
+  }
+
+ private:
+  // The linear allocator we should use to make new methods.
+  art::LinearAlloc* allocator_;
+  // The set of all methods which could be obsoleted.
+  const std::unordered_set<art::ArtMethod*>& obsoleted_methods_;
+  // A map from the original to the newly allocated obsolete method for frames on this thread. The
+  // values in this map are added to the obsolete_methods_ (and obsolete_dex_caches_) fields of
+  // the redefined classes ClassExt as it is filled.
+  ObsoleteMap* obsolete_maps_;
+};
+
+jvmtiError Redefiner::IsModifiableClass(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                        jclass klass,
+                                        jboolean* is_redefinable) {
+  art::Thread* self = art::Thread::Current();
+  art::ScopedObjectAccess soa(self);
+  art::StackHandleScope<1> hs(self);
+  art::ObjPtr<art::mirror::Object> obj(self->DecodeJObject(klass));
+  if (obj.IsNull()) {
+    return ERR(INVALID_CLASS);
+  }
+  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(obj->AsClass()));
+  std::string err_unused;
+  *is_redefinable =
+      Redefiner::GetClassRedefinitionError(h_klass, &err_unused) == OK ? JNI_TRUE : JNI_FALSE;
+  return OK;
+}
+
+jvmtiError Redefiner::GetClassRedefinitionError(art::Handle<art::mirror::Class> klass,
+                                                /*out*/std::string* error_msg) {
+  if (klass->IsPrimitive()) {
+    *error_msg = "Modification of primitive classes is not supported";
+    return ERR(UNMODIFIABLE_CLASS);
+  } else if (klass->IsInterface()) {
+    *error_msg = "Modification of Interface classes is currently not supported";
+    return ERR(UNMODIFIABLE_CLASS);
+  } else if (klass->IsStringClass()) {
+    *error_msg = "Modification of String class is not supported";
+    return ERR(UNMODIFIABLE_CLASS);
+  } else if (klass->IsArrayClass()) {
+    *error_msg = "Modification of Array classes is not supported";
+    return ERR(UNMODIFIABLE_CLASS);
+  } else if (klass->IsProxyClass()) {
+    *error_msg = "Modification of proxy classes is not supported";
+    return ERR(UNMODIFIABLE_CLASS);
+  }
+
+  for (jclass c : art::NonDebuggableClasses::GetNonDebuggableClasses()) {
+    if (klass.Get() == art::Thread::Current()->DecodeJObject(c)->AsClass()) {
+      *error_msg = "Class might have stack frames that cannot be made obsolete";
+      return ERR(UNMODIFIABLE_CLASS);
+    }
+  }
+
+  return OK;
+}
+
+// Moves dex data to an anonymous, read-only mmap'd region.
+std::unique_ptr<art::MemMap> Redefiner::MoveDataToMemMap(const std::string& original_location,
+                                                         art::ArrayRef<const unsigned char> data,
+                                                         std::string* error_msg) {
+  std::unique_ptr<art::MemMap> map(art::MemMap::MapAnonymous(
+      StringPrintf("%s-transformed", original_location.c_str()).c_str(),
+      nullptr,
+      data.size(),
+      PROT_READ|PROT_WRITE,
+      /*low_4gb*/false,
+      /*reuse*/false,
+      error_msg));
+  if (map == nullptr) {
+    return map;
+  }
+  memcpy(map->Begin(), data.data(), data.size());
+  // Make the dex files mmap read only. This matches how other DexFiles are mmaped and prevents
+  // programs from corrupting it.
+  map->Protect(PROT_READ);
+  return map;
+}
+
+Redefiner::ClassRedefinition::ClassRedefinition(
+    Redefiner* driver,
+    jclass klass,
+    const art::DexFile* redefined_dex_file,
+    const char* class_sig,
+    art::ArrayRef<const unsigned char> orig_dex_file) :
+      driver_(driver),
+      klass_(klass),
+      dex_file_(redefined_dex_file),
+      class_sig_(class_sig),
+      original_dex_file_(orig_dex_file) {
+  GetMirrorClass()->MonitorEnter(driver_->self_);
+}
+
+Redefiner::ClassRedefinition::~ClassRedefinition() {
+  if (driver_ != nullptr) {
+    GetMirrorClass()->MonitorExit(driver_->self_);
+  }
+}
+
+jvmtiError Redefiner::RedefineClasses(ArtJvmTiEnv* env,
+                                      EventHandler* event_handler,
+                                      art::Runtime* runtime,
+                                      art::Thread* self,
+                                      jint class_count,
+                                      const jvmtiClassDefinition* definitions,
+                                      /*out*/std::string* error_msg) {
+  if (env == nullptr) {
+    *error_msg = "env was null!";
+    return ERR(INVALID_ENVIRONMENT);
+  } else if (class_count < 0) {
+    *error_msg = "class_count was less then 0";
+    return ERR(ILLEGAL_ARGUMENT);
+  } else if (class_count == 0) {
+    // We don't actually need to do anything. Just return OK.
+    return OK;
+  } else if (definitions == nullptr) {
+    *error_msg = "null definitions!";
+    return ERR(NULL_POINTER);
+  }
+  std::vector<ArtClassDefinition> def_vector;
+  def_vector.reserve(class_count);
+  for (jint i = 0; i < class_count; i++) {
+    jboolean is_modifiable = JNI_FALSE;
+    jvmtiError res = env->IsModifiableClass(definitions[i].klass, &is_modifiable);
+    if (res != OK) {
+      return res;
+    } else if (!is_modifiable) {
+      return ERR(UNMODIFIABLE_CLASS);
+    }
+    // We make a copy of the class_bytes to pass into the retransformation.
+    // This makes cleanup easier (since we unambiguously own the bytes) and also is useful since we
+    // will need to keep the original bytes around unaltered for subsequent RetransformClasses calls
+    // to get the passed in bytes.
+    unsigned char* class_bytes_copy = nullptr;
+    res = env->Allocate(definitions[i].class_byte_count, &class_bytes_copy);
+    if (res != OK) {
+      return res;
+    }
+    memcpy(class_bytes_copy, definitions[i].class_bytes, definitions[i].class_byte_count);
+
+    ArtClassDefinition def;
+    res = def.Init(env, definitions[i]);
+    if (res != OK) {
+      return res;
+    }
+    def_vector.push_back(std::move(def));
+  }
+  // Call all the transformation events.
+  jvmtiError res = Transformer::RetransformClassesDirect(env,
+                                                         event_handler,
+                                                         self,
+                                                         &def_vector);
+  if (res != OK) {
+    // Something went wrong with transformation!
+    return res;
+  }
+  return RedefineClassesDirect(env, runtime, self, def_vector, error_msg);
+}
+
+jvmtiError Redefiner::RedefineClassesDirect(ArtJvmTiEnv* env,
+                                            art::Runtime* runtime,
+                                            art::Thread* self,
+                                            const std::vector<ArtClassDefinition>& definitions,
+                                            std::string* error_msg) {
+  DCHECK(env != nullptr);
+  if (definitions.size() == 0) {
+    // We don't actually need to do anything. Just return OK.
+    return OK;
+  }
+  // Stop JIT for the duration of this redefine since the JIT might concurrently compile a method we
+  // are going to redefine.
+  art::jit::ScopedJitSuspend suspend_jit;
+  // Get shared mutator lock so we can lock all the classes.
+  art::ScopedObjectAccess soa(self);
+  Redefiner r(env, runtime, self, error_msg);
+  for (const ArtClassDefinition& def : definitions) {
+    // Only try to transform classes that have been modified.
+    if (def.IsModified()) {
+      jvmtiError res = r.AddRedefinition(env, def);
+      if (res != OK) {
+        return res;
+      }
+    }
+  }
+  return r.Run();
+}
+
+jvmtiError Redefiner::AddRedefinition(ArtJvmTiEnv* env, const ArtClassDefinition& def) {
+  std::string original_dex_location;
+  jvmtiError ret = OK;
+  if ((ret = GetClassLocation(env, def.GetClass(), &original_dex_location))) {
+    *error_msg_ = "Unable to get original dex file location!";
+    return ret;
+  }
+  char* generic_ptr_unused = nullptr;
+  char* signature_ptr = nullptr;
+  if ((ret = env->GetClassSignature(def.GetClass(), &signature_ptr, &generic_ptr_unused)) != OK) {
+    *error_msg_ = "Unable to get class signature!";
+    return ret;
+  }
+  JvmtiUniquePtr<char> generic_unique_ptr(MakeJvmtiUniquePtr(env, generic_ptr_unused));
+  JvmtiUniquePtr<char> signature_unique_ptr(MakeJvmtiUniquePtr(env, signature_ptr));
+  std::unique_ptr<art::MemMap> map(MoveDataToMemMap(original_dex_location,
+                                                    def.GetDexData(),
+                                                    error_msg_));
+  std::ostringstream os;
+  if (map.get() == nullptr) {
+    os << "Failed to create anonymous mmap for modified dex file of class " << def.GetName()
+       << "in dex file " << original_dex_location << " because: " << *error_msg_;
+    *error_msg_ = os.str();
+    return ERR(OUT_OF_MEMORY);
+  }
+  if (map->Size() < sizeof(art::DexFile::Header)) {
+    *error_msg_ = "Could not read dex file header because dex_data was too short";
+    return ERR(INVALID_CLASS_FORMAT);
+  }
+  uint32_t checksum = reinterpret_cast<const art::DexFile::Header*>(map->Begin())->checksum_;
+  std::unique_ptr<const art::DexFile> dex_file(art::DexFile::Open(map->GetName(),
+                                                                  checksum,
+                                                                  std::move(map),
+                                                                  /*verify*/true,
+                                                                  /*verify_checksum*/true,
+                                                                  error_msg_));
+  if (dex_file.get() == nullptr) {
+    os << "Unable to load modified dex file for " << def.GetName() << ": " << *error_msg_;
+    *error_msg_ = os.str();
+    return ERR(INVALID_CLASS_FORMAT);
+  }
+  redefinitions_.push_back(
+      Redefiner::ClassRedefinition(this,
+                                   def.GetClass(),
+                                   dex_file.release(),
+                                   signature_ptr,
+                                   def.GetNewOriginalDexFile()));
+  return OK;
+}
+
+art::mirror::Class* Redefiner::ClassRedefinition::GetMirrorClass() {
+  return driver_->self_->DecodeJObject(klass_)->AsClass();
+}
+
+art::mirror::ClassLoader* Redefiner::ClassRedefinition::GetClassLoader() {
+  return GetMirrorClass()->GetClassLoader();
+}
+
+art::mirror::DexCache* Redefiner::ClassRedefinition::CreateNewDexCache(
+    art::Handle<art::mirror::ClassLoader> loader) {
+  art::StackHandleScope<2> hs(driver_->self_);
+  art::ClassLinker* cl = driver_->runtime_->GetClassLinker();
+  art::Handle<art::mirror::DexCache> cache(hs.NewHandle(
+      art::ObjPtr<art::mirror::DexCache>::DownCast(
+          cl->GetClassRoot(art::ClassLinker::kJavaLangDexCache)->AllocObject(driver_->self_))));
+  if (cache.IsNull()) {
+    driver_->self_->AssertPendingOOMException();
+    return nullptr;
+  }
+  art::Handle<art::mirror::String> location(hs.NewHandle(
+      cl->GetInternTable()->InternStrong(dex_file_->GetLocation().c_str())));
+  if (location.IsNull()) {
+    driver_->self_->AssertPendingOOMException();
+    return nullptr;
+  }
+  art::WriterMutexLock mu(driver_->self_, *art::Locks::dex_lock_);
+  art::mirror::DexCache::InitializeDexCache(driver_->self_,
+                                            cache.Get(),
+                                            location.Get(),
+                                            dex_file_.get(),
+                                            loader.IsNull() ? driver_->runtime_->GetLinearAlloc()
+                                                            : loader->GetAllocator(),
+                                            art::kRuntimePointerSize);
+  return cache.Get();
+}
+
+void Redefiner::RecordFailure(jvmtiError result,
+                              const std::string& class_sig,
+                              const std::string& error_msg) {
+  *error_msg_ = StringPrintf("Unable to perform redefinition of '%s': %s",
+                             class_sig.c_str(),
+                             error_msg.c_str());
+  result_ = result;
+}
+
+art::mirror::Object* Redefiner::ClassRedefinition::AllocateOrGetOriginalDexFile() {
+  // If we have been specifically given a new set of bytes use that
+  if (original_dex_file_.size() != 0) {
+    return art::mirror::ByteArray::AllocateAndFill(
+        driver_->self_,
+        reinterpret_cast<const signed char*>(original_dex_file_.data()),
+        original_dex_file_.size());
+  }
+
+  // See if we already have one set.
+  art::ObjPtr<art::mirror::ClassExt> ext(GetMirrorClass()->GetExtData());
+  if (!ext.IsNull()) {
+    art::ObjPtr<art::mirror::Object> old_original_dex_file(ext->GetOriginalDexFile());
+    if (!old_original_dex_file.IsNull()) {
+      // We do. Use it.
+      return old_original_dex_file.Ptr();
+    }
+  }
+
+  // return the current dex_cache which has the dex file in it.
+  art::ObjPtr<art::mirror::DexCache> current_dex_cache(GetMirrorClass()->GetDexCache());
+  // TODO Handle this or make it so it cannot happen.
+  if (current_dex_cache->GetDexFile()->NumClassDefs() != 1) {
+    LOG(WARNING) << "Current dex file has more than one class in it. Calling RetransformClasses "
+                 << "on this class might fail if no transformations are applied to it!";
+  }
+  return current_dex_cache.Ptr();
+}
+
+struct CallbackCtx {
+  ObsoleteMap* obsolete_map;
+  art::LinearAlloc* allocator;
+  std::unordered_set<art::ArtMethod*> obsolete_methods;
+
+  explicit CallbackCtx(ObsoleteMap* map, art::LinearAlloc* alloc)
+      : obsolete_map(map), allocator(alloc) {}
+};
+
+void DoAllocateObsoleteMethodsCallback(art::Thread* t, void* vdata) NO_THREAD_SAFETY_ANALYSIS {
+  CallbackCtx* data = reinterpret_cast<CallbackCtx*>(vdata);
+  ObsoleteMethodStackVisitor::UpdateObsoleteFrames(t,
+                                                   data->allocator,
+                                                   data->obsolete_methods,
+                                                   data->obsolete_map);
+}
+
+// This creates any ArtMethod* structures needed for obsolete methods and ensures that the stack is
+// updated so they will be run.
+// TODO Rewrite so we can do this only once regardless of how many redefinitions there are.
+void Redefiner::ClassRedefinition::FindAndAllocateObsoleteMethods(art::mirror::Class* art_klass) {
+  art::ScopedAssertNoThreadSuspension ns("No thread suspension during thread stack walking");
+  art::mirror::ClassExt* ext = art_klass->GetExtData();
+  CHECK(ext->GetObsoleteMethods() != nullptr);
+  art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
+  // This holds pointers to the obsolete methods map fields which are updated as needed.
+  ObsoleteMap map(ext->GetObsoleteMethods(), ext->GetObsoleteDexCaches(), art_klass->GetDexCache());
+  CallbackCtx ctx(&map, linker->GetAllocatorForClassLoader(art_klass->GetClassLoader()));
+  // Add all the declared methods to the map
+  for (auto& m : art_klass->GetDeclaredMethods(art::kRuntimePointerSize)) {
+    if (m.IsIntrinsic()) {
+      LOG(WARNING) << "Redefining intrinsic method " << m.PrettyMethod() << ". This may cause the "
+                   << "unexpected use of the original definition of " << m.PrettyMethod() << "in "
+                   << "methods that have already been compiled.";
+    }
+    // It is possible to simply filter out some methods where they cannot really become obsolete,
+    // such as native methods and keep their original (possibly optimized) implementations. We don't
+    // do this, however, since we would need to mark these functions (still in the classes
+    // declared_methods array) as obsolete so we will find the correct dex file to get meta-data
+    // from (for example about stack-frame size). Furthermore we would be unable to get some useful
+    // error checking from the interpreter which ensure we don't try to start executing obsolete
+    // methods.
+    ctx.obsolete_methods.insert(&m);
+  }
+  {
+    art::MutexLock mu(driver_->self_, *art::Locks::thread_list_lock_);
+    art::ThreadList* list = art::Runtime::Current()->GetThreadList();
+    list->ForEach(DoAllocateObsoleteMethodsCallback, static_cast<void*>(&ctx));
+  }
+}
+
+// Try and get the declared method. First try to get a virtual method then a direct method if that's
+// not found.
+static art::ArtMethod* FindMethod(art::Handle<art::mirror::Class> klass,
+                                  art::StringPiece name,
+                                  art::Signature sig) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  DCHECK(!klass->IsProxyClass());
+  for (art::ArtMethod& m : klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize)) {
+    if (m.GetName() == name && m.GetSignature() == sig) {
+      return &m;
+    }
+  }
+  return nullptr;
+}
+
+bool Redefiner::ClassRedefinition::CheckSameMethods() {
+  art::StackHandleScope<1> hs(driver_->self_);
+  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
+  DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
+
+  art::ClassDataItemIterator new_iter(*dex_file_,
+                                      dex_file_->GetClassData(dex_file_->GetClassDef(0)));
+
+  // Make sure we have the same number of methods.
+  uint32_t num_new_method = new_iter.NumVirtualMethods() + new_iter.NumDirectMethods();
+  uint32_t num_old_method = h_klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size();
+  if (num_new_method != num_old_method) {
+    bool bigger = num_new_method > num_old_method;
+    RecordFailure(bigger ? ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED)
+                         : ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED),
+                  StringPrintf("Total number of declared methods changed from %d to %d",
+                               num_old_method, num_new_method));
+    return false;
+  }
+
+  // Skip all of the fields. We should have already checked this.
+  new_iter.SkipAllFields();
+  // Check each of the methods. NB we don't need to specifically check for removals since the 2 dex
+  // files have the same number of methods, which means there must be an equal amount of additions
+  // and removals.
+  for (; new_iter.HasNextVirtualMethod() || new_iter.HasNextDirectMethod(); new_iter.Next()) {
+    // Get the data on the method we are searching for
+    const art::DexFile::MethodId& new_method_id = dex_file_->GetMethodId(new_iter.GetMemberIndex());
+    const char* new_method_name = dex_file_->GetMethodName(new_method_id);
+    art::Signature new_method_signature = dex_file_->GetMethodSignature(new_method_id);
+    art::ArtMethod* old_method = FindMethod(h_klass, new_method_name, new_method_signature);
+    // If we got past the check for the same number of methods above that means there must be at
+    // least one added and one removed method. We will return the ADDED failure message since it is
+    // easier to get a useful error report for it.
+    if (old_method == nullptr) {
+      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED),
+                    StringPrintf("Unknown method '%s' (sig: %s) was added!",
+                                  new_method_name,
+                                  new_method_signature.ToString().c_str()));
+      return false;
+    }
+    // Since direct methods have different flags than virtual ones (specifically direct methods must
+    // have kAccPrivate or kAccStatic or kAccConstructor flags) we can tell if a method changes from
+    // virtual to direct.
+    uint32_t new_flags = new_iter.GetMethodAccessFlags() & ~art::kAccPreviouslyWarm;
+    if (new_flags != (old_method->GetAccessFlags() & (art::kAccValidMethodFlags ^ art::kAccPreviouslyWarm))) {
+      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED),
+                    StringPrintf("method '%s' (sig: %s) had different access flags",
+                                 new_method_name,
+                                 new_method_signature.ToString().c_str()));
+      return false;
+    }
+  }
+  return true;
+}
+
+bool Redefiner::ClassRedefinition::CheckSameFields() {
+  art::StackHandleScope<1> hs(driver_->self_);
+  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
+  DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
+  art::ClassDataItemIterator new_iter(*dex_file_,
+                                      dex_file_->GetClassData(dex_file_->GetClassDef(0)));
+  const art::DexFile& old_dex_file = h_klass->GetDexFile();
+  art::ClassDataItemIterator old_iter(old_dex_file,
+                                      old_dex_file.GetClassData(*h_klass->GetClassDef()));
+  // Instance and static fields can be differentiated by their flags so no need to check them
+  // separately.
+  while (new_iter.HasNextInstanceField() || new_iter.HasNextStaticField()) {
+    // Get the data on the method we are searching for
+    const art::DexFile::FieldId& new_field_id = dex_file_->GetFieldId(new_iter.GetMemberIndex());
+    const char* new_field_name = dex_file_->GetFieldName(new_field_id);
+    const char* new_field_type = dex_file_->GetFieldTypeDescriptor(new_field_id);
+
+    if (!(old_iter.HasNextInstanceField() || old_iter.HasNextStaticField())) {
+      // We are missing the old version of this method!
+      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
+                    StringPrintf("Unknown field '%s' (type: %s) added!",
+                                  new_field_name,
+                                  new_field_type));
+      return false;
+    }
+
+    const art::DexFile::FieldId& old_field_id = old_dex_file.GetFieldId(old_iter.GetMemberIndex());
+    const char* old_field_name = old_dex_file.GetFieldName(old_field_id);
+    const char* old_field_type = old_dex_file.GetFieldTypeDescriptor(old_field_id);
+
+    // Check name and type.
+    if (strcmp(old_field_name, new_field_name) != 0 ||
+        strcmp(old_field_type, new_field_type) != 0) {
+      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
+                    StringPrintf("Field changed from '%s' (sig: %s) to '%s' (sig: %s)!",
+                                  old_field_name,
+                                  old_field_type,
+                                  new_field_name,
+                                  new_field_type));
+      return false;
+    }
+
+    // Since static fields have different flags than instance ones (specifically static fields must
+    // have the kAccStatic flag) we can tell if a field changes from static to instance.
+    if (new_iter.GetFieldAccessFlags() != old_iter.GetFieldAccessFlags()) {
+      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
+                    StringPrintf("Field '%s' (sig: %s) had different access flags",
+                                  new_field_name,
+                                  new_field_type));
+      return false;
+    }
+
+    new_iter.Next();
+    old_iter.Next();
+  }
+  if (old_iter.HasNextInstanceField() || old_iter.HasNextStaticField()) {
+    RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
+                  StringPrintf("field '%s' (sig: %s) is missing!",
+                                old_dex_file.GetFieldName(old_dex_file.GetFieldId(
+                                    old_iter.GetMemberIndex())),
+                                old_dex_file.GetFieldTypeDescriptor(old_dex_file.GetFieldId(
+                                    old_iter.GetMemberIndex()))));
+    return false;
+  }
+  return true;
+}
+
+bool Redefiner::ClassRedefinition::CheckClass() {
+  art::StackHandleScope<1> hs(driver_->self_);
+  // Easy check that only 1 class def is present.
+  if (dex_file_->NumClassDefs() != 1) {
+    RecordFailure(ERR(ILLEGAL_ARGUMENT),
+                  StringPrintf("Expected 1 class def in dex file but found %d",
+                               dex_file_->NumClassDefs()));
+    return false;
+  }
+  // Get the ClassDef from the new DexFile.
+  // Since the dex file has only a single class def the index is always 0.
+  const art::DexFile::ClassDef& def = dex_file_->GetClassDef(0);
+  // Get the class as it is now.
+  art::Handle<art::mirror::Class> current_class(hs.NewHandle(GetMirrorClass()));
+
+  // Check the access flags didn't change.
+  if (def.GetJavaAccessFlags() != (current_class->GetAccessFlags() & art::kAccValidClassFlags)) {
+    RecordFailure(ERR(UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED),
+                  "Cannot change modifiers of class by redefinition");
+    return false;
+  }
+
+  // Check class name.
+  // These should have been checked by the dexfile verifier on load.
+  DCHECK_NE(def.class_idx_, art::dex::TypeIndex::Invalid()) << "Invalid type index";
+  const char* descriptor = dex_file_->StringByTypeIdx(def.class_idx_);
+  DCHECK(descriptor != nullptr) << "Invalid dex file structure!";
+  if (!current_class->DescriptorEquals(descriptor)) {
+    std::string storage;
+    RecordFailure(ERR(NAMES_DONT_MATCH),
+                  StringPrintf("expected file to contain class called '%s' but found '%s'!",
+                               current_class->GetDescriptor(&storage),
+                               descriptor));
+    return false;
+  }
+  if (current_class->IsObjectClass()) {
+    if (def.superclass_idx_ != art::dex::TypeIndex::Invalid()) {
+      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass added!");
+      return false;
+    }
+  } else {
+    const char* super_descriptor = dex_file_->StringByTypeIdx(def.superclass_idx_);
+    DCHECK(descriptor != nullptr) << "Invalid dex file structure!";
+    if (!current_class->GetSuperClass()->DescriptorEquals(super_descriptor)) {
+      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass changed");
+      return false;
+    }
+  }
+  const art::DexFile::TypeList* interfaces = dex_file_->GetInterfacesList(def);
+  if (interfaces == nullptr) {
+    if (current_class->NumDirectInterfaces() != 0) {
+      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added");
+      return false;
+    }
+  } else {
+    DCHECK(!current_class->IsProxyClass());
+    const art::DexFile::TypeList* current_interfaces = current_class->GetInterfaceTypeList();
+    if (current_interfaces == nullptr || current_interfaces->Size() != interfaces->Size()) {
+      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added or removed");
+      return false;
+    }
+    // The order of interfaces is (barely) meaningful so we error if it changes.
+    const art::DexFile& orig_dex_file = current_class->GetDexFile();
+    for (uint32_t i = 0; i < interfaces->Size(); i++) {
+      if (strcmp(
+            dex_file_->StringByTypeIdx(interfaces->GetTypeItem(i).type_idx_),
+            orig_dex_file.StringByTypeIdx(current_interfaces->GetTypeItem(i).type_idx_)) != 0) {
+        RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED),
+                      "Interfaces changed or re-ordered");
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool Redefiner::ClassRedefinition::CheckRedefinable() {
+  std::string err;
+  art::StackHandleScope<1> hs(driver_->self_);
+
+  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
+  jvmtiError res = Redefiner::GetClassRedefinitionError(h_klass, &err);
+  if (res != OK) {
+    RecordFailure(res, err);
+    return false;
+  } else {
+    return true;
+  }
+}
+
+bool Redefiner::ClassRedefinition::CheckRedefinitionIsValid() {
+  return CheckRedefinable() &&
+      CheckClass() &&
+      CheckSameFields() &&
+      CheckSameMethods();
+}
+
+class RedefinitionDataIter;
+
+// A wrapper that lets us hold onto the arbitrary sized data needed for redefinitions in a
+// reasonably sane way. This adds no fields to the normal ObjectArray. By doing this we can avoid
+// having to deal with the fact that we need to hold an arbitrary number of references live.
+class RedefinitionDataHolder {
+ public:
+  enum DataSlot : int32_t {
+    kSlotSourceClassLoader = 0,
+    kSlotJavaDexFile = 1,
+    kSlotNewDexFileCookie = 2,
+    kSlotNewDexCache = 3,
+    kSlotMirrorClass = 4,
+    kSlotOrigDexFile = 5,
+    kSlotOldObsoleteMethods = 6,
+    kSlotOldDexCaches = 7,
+
+    // Must be last one.
+    kNumSlots = 8,
+  };
+
+  // This needs to have a HandleScope passed in that is capable of creating a new Handle without
+  // overflowing. Only one handle will be created. This object has a lifetime identical to that of
+  // the passed in handle-scope.
+  RedefinitionDataHolder(art::StackHandleScope<1>* hs,
+                         art::Runtime* runtime,
+                         art::Thread* self,
+                         std::vector<Redefiner::ClassRedefinition>* redefinitions)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) :
+    arr_(
+      hs->NewHandle(
+        art::mirror::ObjectArray<art::mirror::Object>::Alloc(
+            self,
+            runtime->GetClassLinker()->GetClassRoot(art::ClassLinker::kObjectArrayClass),
+            redefinitions->size() * kNumSlots))),
+    redefinitions_(redefinitions) {}
+
+  bool IsNull() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return arr_.IsNull();
+  }
+
+  art::mirror::ClassLoader* GetSourceClassLoader(jint klass_index) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return art::down_cast<art::mirror::ClassLoader*>(GetSlot(klass_index, kSlotSourceClassLoader));
+  }
+  art::mirror::Object* GetJavaDexFile(jint klass_index) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return GetSlot(klass_index, kSlotJavaDexFile);
+  }
+  art::mirror::LongArray* GetNewDexFileCookie(jint klass_index) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return art::down_cast<art::mirror::LongArray*>(GetSlot(klass_index, kSlotNewDexFileCookie));
+  }
+  art::mirror::DexCache* GetNewDexCache(jint klass_index) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return art::down_cast<art::mirror::DexCache*>(GetSlot(klass_index, kSlotNewDexCache));
+  }
+  art::mirror::Class* GetMirrorClass(jint klass_index) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return art::down_cast<art::mirror::Class*>(GetSlot(klass_index, kSlotMirrorClass));
+  }
+
+  art::mirror::Object* GetOriginalDexFile(jint klass_index) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return art::down_cast<art::mirror::Object*>(GetSlot(klass_index, kSlotOrigDexFile));
+  }
+
+  art::mirror::PointerArray* GetOldObsoleteMethods(jint klass_index) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return art::down_cast<art::mirror::PointerArray*>(
+        GetSlot(klass_index, kSlotOldObsoleteMethods));
+  }
+
+  art::mirror::ObjectArray<art::mirror::DexCache>* GetOldDexCaches(jint klass_index) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return art::down_cast<art::mirror::ObjectArray<art::mirror::DexCache>*>(
+        GetSlot(klass_index, kSlotOldDexCaches));
+  }
+
+  void SetSourceClassLoader(jint klass_index, art::mirror::ClassLoader* loader)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    SetSlot(klass_index, kSlotSourceClassLoader, loader);
+  }
+  void SetJavaDexFile(jint klass_index, art::mirror::Object* dexfile)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    SetSlot(klass_index, kSlotJavaDexFile, dexfile);
+  }
+  void SetNewDexFileCookie(jint klass_index, art::mirror::LongArray* cookie)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    SetSlot(klass_index, kSlotNewDexFileCookie, cookie);
+  }
+  void SetNewDexCache(jint klass_index, art::mirror::DexCache* cache)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    SetSlot(klass_index, kSlotNewDexCache, cache);
+  }
+  void SetMirrorClass(jint klass_index, art::mirror::Class* klass)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    SetSlot(klass_index, kSlotMirrorClass, klass);
+  }
+  void SetOriginalDexFile(jint klass_index, art::mirror::Object* bytes)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    SetSlot(klass_index, kSlotOrigDexFile, bytes);
+  }
+  void SetOldObsoleteMethods(jint klass_index, art::mirror::PointerArray* methods)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    SetSlot(klass_index, kSlotOldObsoleteMethods, methods);
+  }
+  void SetOldDexCaches(jint klass_index, art::mirror::ObjectArray<art::mirror::DexCache>* caches)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    SetSlot(klass_index, kSlotOldDexCaches, caches);
+  }
+
+  int32_t Length() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return arr_->GetLength() / kNumSlots;
+  }
+
+  std::vector<Redefiner::ClassRedefinition>* GetRedefinitions()
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return redefinitions_;
+  }
+
+  bool operator==(const RedefinitionDataHolder& other) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return arr_.Get() == other.arr_.Get();
+  }
+
+  bool operator!=(const RedefinitionDataHolder& other) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return !(*this == other);
+  }
+
+  RedefinitionDataIter begin() REQUIRES_SHARED(art::Locks::mutator_lock_);
+  RedefinitionDataIter end() REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+ private:
+  mutable art::Handle<art::mirror::ObjectArray<art::mirror::Object>> arr_;
+  std::vector<Redefiner::ClassRedefinition>* redefinitions_;
+
+  art::mirror::Object* GetSlot(jint klass_index,
+                               DataSlot slot) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    DCHECK_LT(klass_index, Length());
+    return arr_->Get((kNumSlots * klass_index) + slot);
+  }
+
+  void SetSlot(jint klass_index,
+               DataSlot slot,
+               art::ObjPtr<art::mirror::Object> obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    DCHECK(!art::Runtime::Current()->IsActiveTransaction());
+    DCHECK_LT(klass_index, Length());
+    arr_->Set<false>((kNumSlots * klass_index) + slot, obj);
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(RedefinitionDataHolder);
+};
+
+class RedefinitionDataIter {
+ public:
+  RedefinitionDataIter(int32_t idx, RedefinitionDataHolder& holder) : idx_(idx), holder_(holder) {}
+
+  RedefinitionDataIter(const RedefinitionDataIter&) = default;
+  RedefinitionDataIter(RedefinitionDataIter&&) = default;
+  RedefinitionDataIter& operator=(const RedefinitionDataIter&) = default;
+  RedefinitionDataIter& operator=(RedefinitionDataIter&&) = default;
+
+  bool operator==(const RedefinitionDataIter& other) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return idx_ == other.idx_ && holder_ == other.holder_;
+  }
+
+  bool operator!=(const RedefinitionDataIter& other) const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return !(*this == other);
+  }
+
+  RedefinitionDataIter operator++() {  // Value after modification.
+    idx_++;
+    return *this;
+  }
+
+  RedefinitionDataIter operator++(int) {
+    RedefinitionDataIter temp = *this;
+    idx_++;
+    return temp;
+  }
+
+  RedefinitionDataIter operator+(ssize_t delta) const {
+    RedefinitionDataIter temp = *this;
+    temp += delta;
+    return temp;
+  }
+
+  RedefinitionDataIter& operator+=(ssize_t delta) {
+    idx_ += delta;
+    return *this;
+  }
+
+  Redefiner::ClassRedefinition& GetRedefinition() REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return (*holder_.GetRedefinitions())[idx_];
+  }
+
+  RedefinitionDataHolder& GetHolder() {
+    return holder_;
+  }
+
+  art::mirror::ClassLoader* GetSourceClassLoader() const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return holder_.GetSourceClassLoader(idx_);
+  }
+  art::mirror::Object* GetJavaDexFile() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return holder_.GetJavaDexFile(idx_);
+  }
+  art::mirror::LongArray* GetNewDexFileCookie() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return holder_.GetNewDexFileCookie(idx_);
+  }
+  art::mirror::DexCache* GetNewDexCache() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return holder_.GetNewDexCache(idx_);
+  }
+  art::mirror::Class* GetMirrorClass() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return holder_.GetMirrorClass(idx_);
+  }
+  art::mirror::Object* GetOriginalDexFile() const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return holder_.GetOriginalDexFile(idx_);
+  }
+  art::mirror::PointerArray* GetOldObsoleteMethods() const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return holder_.GetOldObsoleteMethods(idx_);
+  }
+  art::mirror::ObjectArray<art::mirror::DexCache>* GetOldDexCaches() const
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    return holder_.GetOldDexCaches(idx_);
+  }
+
+  int32_t GetIndex() const {
+    return idx_;
+  }
+
+  void SetSourceClassLoader(art::mirror::ClassLoader* loader)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    holder_.SetSourceClassLoader(idx_, loader);
+  }
+  void SetJavaDexFile(art::mirror::Object* dexfile) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    holder_.SetJavaDexFile(idx_, dexfile);
+  }
+  void SetNewDexFileCookie(art::mirror::LongArray* cookie)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    holder_.SetNewDexFileCookie(idx_, cookie);
+  }
+  void SetNewDexCache(art::mirror::DexCache* cache) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    holder_.SetNewDexCache(idx_, cache);
+  }
+  void SetMirrorClass(art::mirror::Class* klass) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    holder_.SetMirrorClass(idx_, klass);
+  }
+  void SetOriginalDexFile(art::mirror::Object* bytes)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    holder_.SetOriginalDexFile(idx_, bytes);
+  }
+  void SetOldObsoleteMethods(art::mirror::PointerArray* methods)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    holder_.SetOldObsoleteMethods(idx_, methods);
+  }
+  void SetOldDexCaches(art::mirror::ObjectArray<art::mirror::DexCache>* caches)
+      REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    holder_.SetOldDexCaches(idx_, caches);
+  }
+
+ private:
+  int32_t idx_;
+  RedefinitionDataHolder& holder_;
+};
+
+RedefinitionDataIter RedefinitionDataHolder::begin() {
+  return RedefinitionDataIter(0, *this);
+}
+
+RedefinitionDataIter RedefinitionDataHolder::end() {
+  return RedefinitionDataIter(Length(), *this);
+}
+
+bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& iter) {
+  DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
+  art::StackHandleScope<2> hs(driver_->self_);
+  std::string error;
+  // TODO Make verification log level lower
+  art::verifier::FailureKind failure =
+      art::verifier::MethodVerifier::VerifyClass(driver_->self_,
+                                                 dex_file_.get(),
+                                                 hs.NewHandle(iter.GetNewDexCache()),
+                                                 hs.NewHandle(GetClassLoader()),
+                                                 dex_file_->GetClassDef(0), /*class_def*/
+                                                 nullptr, /*compiler_callbacks*/
+                                                 false, /*allow_soft_failures*/
+                                                 /*log_level*/
+                                                 art::verifier::HardFailLogMode::kLogWarning,
+                                                 &error);
+  bool passes = failure == art::verifier::FailureKind::kNoFailure;
+  if (!passes) {
+    RecordFailure(ERR(FAILS_VERIFICATION), "Failed to verify class. Error was: " + error);
+  }
+  return passes;
+}
+
+// Looks through the previously allocated cookies to see if we need to update them with another new
+// dexfile. This is so that even if multiple classes with the same classloader are redefined at
+// once they are all added to the classloader.
+bool Redefiner::ClassRedefinition::AllocateAndRememberNewDexFileCookie(
+    art::Handle<art::mirror::ClassLoader> source_class_loader,
+    art::Handle<art::mirror::Object> dex_file_obj,
+    /*out*/RedefinitionDataIter* cur_data) {
+  art::StackHandleScope<2> hs(driver_->self_);
+  art::MutableHandle<art::mirror::LongArray> old_cookie(
+      hs.NewHandle<art::mirror::LongArray>(nullptr));
+  bool has_older_cookie = false;
+  // See if we already have a cookie that a previous redefinition got from the same classloader.
+  for (auto old_data = cur_data->GetHolder().begin(); old_data != *cur_data; ++old_data) {
+    if (old_data.GetSourceClassLoader() == source_class_loader.Get()) {
+      // Since every instance of this classloader should have the same cookie associated with it we
+      // can stop looking here.
+      has_older_cookie = true;
+      old_cookie.Assign(old_data.GetNewDexFileCookie());
+      break;
+    }
+  }
+  if (old_cookie.IsNull()) {
+    // No older cookie. Get it directly from the dex_file_obj
+    // We should not have seen this classloader elsewhere.
+    CHECK(!has_older_cookie);
+    old_cookie.Assign(ClassLoaderHelper::GetDexFileCookie(dex_file_obj));
+  }
+  // Use the old cookie to generate the new one with the new DexFile* added in.
+  art::Handle<art::mirror::LongArray>
+      new_cookie(hs.NewHandle(ClassLoaderHelper::AllocateNewDexFileCookie(driver_->self_,
+                                                                          old_cookie,
+                                                                          dex_file_.get())));
+  // Make sure the allocation worked.
+  if (new_cookie.IsNull()) {
+    return false;
+  }
+
+  // Save the cookie.
+  cur_data->SetNewDexFileCookie(new_cookie.Get());
+  // If there are other copies of this same classloader we need to make sure that we all have the
+  // same cookie.
+  if (has_older_cookie) {
+    for (auto old_data = cur_data->GetHolder().begin(); old_data != *cur_data; ++old_data) {
+      // We will let the GC take care of the cookie we allocated for this one.
+      if (old_data.GetSourceClassLoader() == source_class_loader.Get()) {
+        old_data.SetNewDexFileCookie(new_cookie.Get());
+      }
+    }
+  }
+
+  return true;
+}
+
+bool Redefiner::ClassRedefinition::FinishRemainingAllocations(
+    /*out*/RedefinitionDataIter* cur_data) {
+  art::ScopedObjectAccessUnchecked soa(driver_->self_);
+  art::StackHandleScope<2> hs(driver_->self_);
+  cur_data->SetMirrorClass(GetMirrorClass());
+  // This shouldn't allocate
+  art::Handle<art::mirror::ClassLoader> loader(hs.NewHandle(GetClassLoader()));
+  // The bootclasspath is handled specially so it doesn't have a j.l.DexFile.
+  if (!art::ClassLinker::IsBootClassLoader(soa, loader.Get())) {
+    cur_data->SetSourceClassLoader(loader.Get());
+    art::Handle<art::mirror::Object> dex_file_obj(hs.NewHandle(
+        ClassLoaderHelper::FindSourceDexFileObject(driver_->self_, loader)));
+    cur_data->SetJavaDexFile(dex_file_obj.Get());
+    if (dex_file_obj == nullptr) {
+      RecordFailure(ERR(INTERNAL), "Unable to find dex file!");
+      return false;
+    }
+    // Allocate the new dex file cookie.
+    if (!AllocateAndRememberNewDexFileCookie(loader, dex_file_obj, cur_data)) {
+      driver_->self_->AssertPendingOOMException();
+      driver_->self_->ClearException();
+      RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate dex file array for class loader");
+      return false;
+    }
+  }
+  cur_data->SetNewDexCache(CreateNewDexCache(loader));
+  if (cur_data->GetNewDexCache() == nullptr) {
+    driver_->self_->AssertPendingException();
+    driver_->self_->ClearException();
+    RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate DexCache");
+    return false;
+  }
+
+  // We won't always need to set this field.
+  cur_data->SetOriginalDexFile(AllocateOrGetOriginalDexFile());
+  if (cur_data->GetOriginalDexFile() == nullptr) {
+    driver_->self_->AssertPendingOOMException();
+    driver_->self_->ClearException();
+    RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate array for original dex file");
+    return false;
+  }
+  return true;
+}
+
+void Redefiner::ClassRedefinition::UnregisterJvmtiBreakpoints() {
+  BreakpointUtil::RemoveBreakpointsInClass(driver_->env_, GetMirrorClass());
+}
+
+void Redefiner::ClassRedefinition::UnregisterBreakpoints() {
+  DCHECK(art::Dbg::IsDebuggerActive());
+  art::JDWP::JdwpState* state = art::Dbg::GetJdwpState();
+  if (state != nullptr) {
+    state->UnregisterLocationEventsOnClass(GetMirrorClass());
+  }
+}
+
+void Redefiner::UnregisterAllBreakpoints() {
+  if (LIKELY(!art::Dbg::IsDebuggerActive())) {
+    return;
+  }
+  for (Redefiner::ClassRedefinition& redef : redefinitions_) {
+    redef.UnregisterBreakpoints();
+  }
+}
+
+bool Redefiner::CheckAllRedefinitionAreValid() {
+  for (Redefiner::ClassRedefinition& redef : redefinitions_) {
+    if (!redef.CheckRedefinitionIsValid()) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void Redefiner::RestoreObsoleteMethodMapsIfUnneeded(RedefinitionDataHolder& holder) {
+  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
+    data.GetRedefinition().RestoreObsoleteMethodMapsIfUnneeded(&data);
+  }
+}
+
+bool Redefiner::EnsureAllClassAllocationsFinished(RedefinitionDataHolder& holder) {
+  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
+    if (!data.GetRedefinition().EnsureClassAllocationsFinished(&data)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool Redefiner::FinishAllRemainingAllocations(RedefinitionDataHolder& holder) {
+  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
+    // Allocate the data this redefinition requires.
+    if (!data.GetRedefinition().FinishRemainingAllocations(&data)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void Redefiner::ClassRedefinition::ReleaseDexFile() {
+  dex_file_.release();
+}
+
+void Redefiner::ReleaseAllDexFiles() {
+  for (Redefiner::ClassRedefinition& redef : redefinitions_) {
+    redef.ReleaseDexFile();
+  }
+}
+
+bool Redefiner::CheckAllClassesAreVerified(RedefinitionDataHolder& holder) {
+  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
+    if (!data.GetRedefinition().CheckVerification(data)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+class ScopedDisableConcurrentAndMovingGc {
+ public:
+  ScopedDisableConcurrentAndMovingGc(art::gc::Heap* heap, art::Thread* self)
+      : heap_(heap), self_(self) {
+    if (heap_->IsGcConcurrentAndMoving()) {
+      heap_->IncrementDisableMovingGC(self_);
+    }
+  }
+
+  ~ScopedDisableConcurrentAndMovingGc() {
+    if (heap_->IsGcConcurrentAndMoving()) {
+      heap_->DecrementDisableMovingGC(self_);
+    }
+  }
+ private:
+  art::gc::Heap* heap_;
+  art::Thread* self_;
+};
+
+jvmtiError Redefiner::Run() {
+  art::StackHandleScope<1> hs(self_);
+  // Allocate an array to hold onto all java temporary objects associated with this redefinition.
+  // We will let this be collected after the end of this function.
+  RedefinitionDataHolder holder(&hs, runtime_, self_, &redefinitions_);
+  if (holder.IsNull()) {
+    self_->AssertPendingOOMException();
+    self_->ClearException();
+    RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate storage for temporaries");
+    return result_;
+  }
+
+  // First we just allocate the ClassExt and its fields that we need. These can be updated
+  // atomically without any issues (since we allocate the map arrays as empty) so we don't bother
+  // doing a try loop. The other allocations we need to ensure that nothing has changed in the time
+  // between allocating them and pausing all threads before we can update them so we need to do a
+  // try loop.
+  if (!CheckAllRedefinitionAreValid() ||
+      !EnsureAllClassAllocationsFinished(holder) ||
+      !FinishAllRemainingAllocations(holder) ||
+      !CheckAllClassesAreVerified(holder)) {
+    return result_;
+  }
+
+  // At this point we can no longer fail without corrupting the runtime state.
+  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
+    art::ClassLinker* cl = runtime_->GetClassLinker();
+    cl->RegisterExistingDexCache(data.GetNewDexCache(), data.GetSourceClassLoader());
+    if (data.GetSourceClassLoader() == nullptr) {
+      cl->AppendToBootClassPath(self_, data.GetRedefinition().GetDexFile());
+    }
+  }
+  UnregisterAllBreakpoints();
+
+  // Disable GC and wait for it to be done if we are a moving GC.  This is fine since we are done
+  // allocating so no deadlocks.
+  ScopedDisableConcurrentAndMovingGc sdcamgc(runtime_->GetHeap(), self_);
+
+  // Do transition to final suspension
+  // TODO We might want to give this its own suspended state!
+  // TODO This isn't right. We need to change state without any chance of suspend ideally!
+  art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
+  art::ScopedSuspendAll ssa("Final installation of redefined Classes!", /*long_suspend*/true);
+  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
+    art::ScopedAssertNoThreadSuspension nts("Updating runtime objects for redefinition");
+    ClassRedefinition& redef = data.GetRedefinition();
+    if (data.GetSourceClassLoader() != nullptr) {
+      ClassLoaderHelper::UpdateJavaDexFile(data.GetJavaDexFile(), data.GetNewDexFileCookie());
+    }
+    art::mirror::Class* klass = data.GetMirrorClass();
+    // TODO Rewrite so we don't do a stack walk for each and every class.
+    redef.FindAndAllocateObsoleteMethods(klass);
+    redef.UpdateClass(klass, data.GetNewDexCache(), data.GetOriginalDexFile());
+    redef.UnregisterJvmtiBreakpoints();
+  }
+  RestoreObsoleteMethodMapsIfUnneeded(holder);
+  // TODO We should check for if any of the redefined methods are intrinsic methods here and, if any
+  // are, force a full-world deoptimization before finishing redefinition. If we don't do this then
+  // methods that have been jitted prior to the current redefinition being applied might continue
+  // to use the old versions of the intrinsics!
+  // TODO Do the dex_file release at a more reasonable place. This works but it muddles who really
+  // owns the DexFile and when ownership is transferred.
+  ReleaseAllDexFiles();
+  return OK;
+}
+
+void Redefiner::ClassRedefinition::UpdateMethods(art::ObjPtr<art::mirror::Class> mclass,
+                                                 art::ObjPtr<art::mirror::DexCache> new_dex_cache,
+                                                 const art::DexFile::ClassDef& class_def) {
+  art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
+  art::PointerSize image_pointer_size = linker->GetImagePointerSize();
+  const art::DexFile::TypeId& declaring_class_id = dex_file_->GetTypeId(class_def.class_idx_);
+  const art::DexFile& old_dex_file = mclass->GetDexFile();
+  // Update methods.
+  for (art::ArtMethod& method : mclass->GetDeclaredMethods(image_pointer_size)) {
+    const art::DexFile::StringId* new_name_id = dex_file_->FindStringId(method.GetName());
+    art::dex::TypeIndex method_return_idx =
+        dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(method.GetReturnTypeDescriptor()));
+    const auto* old_type_list = method.GetParameterTypeList();
+    std::vector<art::dex::TypeIndex> new_type_list;
+    for (uint32_t i = 0; old_type_list != nullptr && i < old_type_list->Size(); i++) {
+      new_type_list.push_back(
+          dex_file_->GetIndexForTypeId(
+              *dex_file_->FindTypeId(
+                  old_dex_file.GetTypeDescriptor(
+                      old_dex_file.GetTypeId(
+                          old_type_list->GetTypeItem(i).type_idx_)))));
+    }
+    const art::DexFile::ProtoId* proto_id = dex_file_->FindProtoId(method_return_idx,
+                                                                   new_type_list);
+    CHECK(proto_id != nullptr || old_type_list == nullptr);
+    const art::DexFile::MethodId* method_id = dex_file_->FindMethodId(declaring_class_id,
+                                                                      *new_name_id,
+                                                                      *proto_id);
+    CHECK(method_id != nullptr);
+    uint32_t dex_method_idx = dex_file_->GetIndexForMethodId(*method_id);
+    method.SetDexMethodIndex(dex_method_idx);
+    linker->SetEntryPointsToInterpreter(&method);
+    method.SetCodeItemOffset(dex_file_->FindCodeItemOffset(class_def, dex_method_idx));
+    method.SetDexCacheResolvedMethods(new_dex_cache->GetResolvedMethods(), image_pointer_size);
+    // Clear all the intrinsics related flags.
+    method.ClearAccessFlags(art::kAccIntrinsic | (~art::kAccFlagsNotUsedByIntrinsic));
+    // Notify the jit that this method is redefined.
+    art::jit::Jit* jit = driver_->runtime_->GetJit();
+    if (jit != nullptr) {
+      jit->GetCodeCache()->NotifyMethodRedefined(&method);
+    }
+  }
+}
+
+void Redefiner::ClassRedefinition::UpdateFields(art::ObjPtr<art::mirror::Class> mclass) {
+  // TODO The IFields & SFields pointers should be combined like the methods_ arrays were.
+  for (auto fields_iter : {mclass->GetIFields(), mclass->GetSFields()}) {
+    for (art::ArtField& field : fields_iter) {
+      std::string declaring_class_name;
+      const art::DexFile::TypeId* new_declaring_id =
+          dex_file_->FindTypeId(field.GetDeclaringClass()->GetDescriptor(&declaring_class_name));
+      const art::DexFile::StringId* new_name_id = dex_file_->FindStringId(field.GetName());
+      const art::DexFile::TypeId* new_type_id = dex_file_->FindTypeId(field.GetTypeDescriptor());
+      CHECK(new_name_id != nullptr && new_type_id != nullptr && new_declaring_id != nullptr);
+      const art::DexFile::FieldId* new_field_id =
+          dex_file_->FindFieldId(*new_declaring_id, *new_name_id, *new_type_id);
+      CHECK(new_field_id != nullptr);
+      // We only need to update the index since the other data in the ArtField cannot be updated.
+      field.SetDexFieldIndex(dex_file_->GetIndexForFieldId(*new_field_id));
+    }
+  }
+}
+
+// Performs updates to class that will allow us to verify it.
+void Redefiner::ClassRedefinition::UpdateClass(
+    art::ObjPtr<art::mirror::Class> mclass,
+    art::ObjPtr<art::mirror::DexCache> new_dex_cache,
+    art::ObjPtr<art::mirror::Object> original_dex_file) {
+  DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
+  const art::DexFile::ClassDef& class_def = dex_file_->GetClassDef(0);
+  UpdateMethods(mclass, new_dex_cache, class_def);
+  UpdateFields(mclass);
+
+  // Update the class fields.
+  // Need to update class last since the ArtMethod gets its DexFile from the class (which is needed
+  // to call GetReturnTypeDescriptor and GetParameterTypeList above).
+  mclass->SetDexCache(new_dex_cache.Ptr());
+  mclass->SetDexClassDefIndex(dex_file_->GetIndexForClassDef(class_def));
+  mclass->SetDexTypeIndex(dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(class_sig_.c_str())));
+  art::ObjPtr<art::mirror::ClassExt> ext(mclass->GetExtData());
+  CHECK(!ext.IsNull());
+  ext->SetOriginalDexFile(original_dex_file);
+}
+
+// Restores the old obsolete methods maps if it turns out they weren't needed (ie there were no new
+// obsolete methods).
+void Redefiner::ClassRedefinition::RestoreObsoleteMethodMapsIfUnneeded(
+    const RedefinitionDataIter* cur_data) {
+  art::mirror::Class* klass = GetMirrorClass();
+  art::mirror::ClassExt* ext = klass->GetExtData();
+  art::mirror::PointerArray* methods = ext->GetObsoleteMethods();
+  art::mirror::PointerArray* old_methods = cur_data->GetOldObsoleteMethods();
+  int32_t old_length = old_methods == nullptr ? 0 : old_methods->GetLength();
+  int32_t expected_length =
+      old_length + klass->NumDirectMethods() + klass->NumDeclaredVirtualMethods();
+  // Check to make sure we are only undoing this one.
+  if (expected_length == methods->GetLength()) {
+    for (int32_t i = 0; i < expected_length; i++) {
+      art::ArtMethod* expected = nullptr;
+      if (i < old_length) {
+        expected = old_methods->GetElementPtrSize<art::ArtMethod*>(i, art::kRuntimePointerSize);
+      }
+      if (methods->GetElementPtrSize<art::ArtMethod*>(i, art::kRuntimePointerSize) != expected) {
+        // We actually have some new obsolete methods. Just abort since we cannot safely shrink the
+        // obsolete methods array.
+        return;
+      }
+    }
+    // No new obsolete methods! We can get rid of the maps.
+    ext->SetObsoleteArrays(cur_data->GetOldObsoleteMethods(), cur_data->GetOldDexCaches());
+  }
+}
+
+// This function does all (java) allocations we need to do for the Class being redefined.
+// TODO Change this name maybe?
+bool Redefiner::ClassRedefinition::EnsureClassAllocationsFinished(
+    /*out*/RedefinitionDataIter* cur_data) {
+  art::StackHandleScope<2> hs(driver_->self_);
+  art::Handle<art::mirror::Class> klass(hs.NewHandle(
+      driver_->self_->DecodeJObject(klass_)->AsClass()));
+  if (klass == nullptr) {
+    RecordFailure(ERR(INVALID_CLASS), "Unable to decode class argument!");
+    return false;
+  }
+  // Allocate the classExt
+  art::Handle<art::mirror::ClassExt> ext(hs.NewHandle(klass->EnsureExtDataPresent(driver_->self_)));
+  if (ext == nullptr) {
+    // No memory. Clear exception (it's not useful) and return error.
+    driver_->self_->AssertPendingOOMException();
+    driver_->self_->ClearException();
+    RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate ClassExt");
+    return false;
+  }
+  // First save the old values of the 2 arrays that make up the obsolete methods maps.  Then
+  // allocate the 2 arrays that make up the obsolete methods map.  Since the contents of the arrays
+  // are only modified when all threads (other than the modifying one) are suspended we don't need
+  // to worry about missing the unsyncronized writes to the array. We do synchronize when setting it
+  // however, since that can happen at any time.
+  cur_data->SetOldObsoleteMethods(ext->GetObsoleteMethods());
+  cur_data->SetOldDexCaches(ext->GetObsoleteDexCaches());
+  if (!ext->ExtendObsoleteArrays(
+        driver_->self_, klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size())) {
+    // OOM. Clear exception and return error.
+    driver_->self_->AssertPendingOOMException();
+    driver_->self_->ClearException();
+    RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate/extend obsolete methods map");
+    return false;
+  }
+  return true;
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_redefine.h b/openjdkjvmti/ti_redefine.h
new file mode 100644
index 0000000..984f922
--- /dev/null
+++ b/openjdkjvmti/ti_redefine.h
@@ -0,0 +1,268 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_REDEFINE_H_
+#define ART_OPENJDKJVMTI_TI_REDEFINE_H_
+
+#include <string>
+
+#include <jni.h>
+
+#include "art_jvmti.h"
+#include "art_method.h"
+#include "base/array_ref.h"
+#include "class_linker.h"
+#include "dex_file.h"
+#include "gc_root-inl.h"
+#include "globals.h"
+#include "jni_env_ext-inl.h"
+#include "jvmti.h"
+#include "linear_alloc.h"
+#include "mem_map.h"
+#include "mirror/array-inl.h"
+#include "mirror/array.h"
+#include "mirror/class-inl.h"
+#include "mirror/class.h"
+#include "mirror/class_loader-inl.h"
+#include "mirror/string-inl.h"
+#include "oat_file.h"
+#include "obj_ptr.h"
+#include "scoped_thread_state_change-inl.h"
+#include "stack.h"
+#include "thread_list.h"
+#include "ti_class_definition.h"
+#include "transform.h"
+#include "utf.h"
+#include "utils/dex_cache_arrays_layout-inl.h"
+
+namespace openjdkjvmti {
+
+class RedefinitionDataHolder;
+class RedefinitionDataIter;
+
+// Class that can redefine a single class's methods.
+class Redefiner {
+ public:
+  // Redefine the given classes with the given dex data. Note this function does not take ownership
+  // of the dex_data pointers. It is not used after this call however and may be freed if desired.
+  // The caller is responsible for freeing it. The runtime makes its own copy of the data. This
+  // function does not call the transformation events.
+  static jvmtiError RedefineClassesDirect(ArtJvmTiEnv* env,
+                                          art::Runtime* runtime,
+                                          art::Thread* self,
+                                          const std::vector<ArtClassDefinition>& definitions,
+                                          /*out*/std::string* error_msg);
+
+  // Redefine the given classes with the given dex data. Note this function does not take ownership
+  // of the dex_data pointers. It is not used after this call however and may be freed if desired.
+  // The caller is responsible for freeing it. The runtime makes its own copy of the data.
+  static jvmtiError RedefineClasses(ArtJvmTiEnv* env,
+                                    EventHandler* event_handler,
+                                    art::Runtime* runtime,
+                                    art::Thread* self,
+                                    jint class_count,
+                                    const jvmtiClassDefinition* definitions,
+                                    /*out*/std::string* error_msg);
+
+  static jvmtiError IsModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_redefinable);
+
+  static std::unique_ptr<art::MemMap> MoveDataToMemMap(const std::string& original_location,
+                                                       art::ArrayRef<const unsigned char> data,
+                                                       std::string* error_msg);
+
+ private:
+  class ClassRedefinition {
+   public:
+    ClassRedefinition(Redefiner* driver,
+                      jclass klass,
+                      const art::DexFile* redefined_dex_file,
+                      const char* class_sig,
+                      art::ArrayRef<const unsigned char> orig_dex_file)
+      REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    // NO_THREAD_SAFETY_ANALYSIS so we can unlock the class in the destructor.
+    ~ClassRedefinition() NO_THREAD_SAFETY_ANALYSIS;
+
+    // Move constructor so we can put these into a vector.
+    ClassRedefinition(ClassRedefinition&& other)
+        : driver_(other.driver_),
+          klass_(other.klass_),
+          dex_file_(std::move(other.dex_file_)),
+          class_sig_(std::move(other.class_sig_)),
+          original_dex_file_(other.original_dex_file_) {
+      other.driver_ = nullptr;
+    }
+
+    art::mirror::Class* GetMirrorClass() REQUIRES_SHARED(art::Locks::mutator_lock_);
+    art::mirror::ClassLoader* GetClassLoader() REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    const art::DexFile& GetDexFile() {
+      return *dex_file_;
+    }
+
+    art::mirror::DexCache* CreateNewDexCache(art::Handle<art::mirror::ClassLoader> loader)
+        REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    // This may return nullptr with a OOME pending if allocation fails.
+    art::mirror::Object* AllocateOrGetOriginalDexFile()
+        REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    void RecordFailure(jvmtiError e, const std::string& err) {
+      driver_->RecordFailure(e, class_sig_, err);
+    }
+
+    bool FinishRemainingAllocations(/*out*/RedefinitionDataIter* cur_data)
+        REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    bool AllocateAndRememberNewDexFileCookie(
+        art::Handle<art::mirror::ClassLoader> source_class_loader,
+        art::Handle<art::mirror::Object> dex_file_obj,
+        /*out*/RedefinitionDataIter* cur_data)
+          REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    void FindAndAllocateObsoleteMethods(art::mirror::Class* art_klass)
+        REQUIRES(art::Locks::mutator_lock_);
+
+    // Checks that the dex file contains only the single expected class and that the top-level class
+    // data has not been modified in an incompatible manner.
+    bool CheckClass() REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    // Checks that the contained class can be successfully verified.
+    bool CheckVerification(const RedefinitionDataIter& holder)
+        REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    // Preallocates all needed allocations in klass so that we can pause execution safely.
+    bool EnsureClassAllocationsFinished(/*out*/RedefinitionDataIter* data)
+        REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    // This will check that no constraints are violated (more than 1 class in dex file, any changes
+    // in number/declaration of methods & fields, changes in access flags, etc.)
+    bool CheckRedefinitionIsValid() REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    // Checks that the class can even be redefined.
+    bool CheckRedefinable() REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    // Checks that the dex file does not add/remove methods, or change their modifiers or types.
+    bool CheckSameMethods() REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    // Checks that the dex file does not modify fields types or modifiers.
+    bool CheckSameFields() REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    void UpdateJavaDexFile(art::ObjPtr<art::mirror::Object> java_dex_file,
+                           art::ObjPtr<art::mirror::LongArray> new_cookie)
+        REQUIRES(art::Locks::mutator_lock_);
+
+    void UpdateFields(art::ObjPtr<art::mirror::Class> mclass)
+        REQUIRES(art::Locks::mutator_lock_);
+
+    void UpdateMethods(art::ObjPtr<art::mirror::Class> mclass,
+                       art::ObjPtr<art::mirror::DexCache> new_dex_cache,
+                       const art::DexFile::ClassDef& class_def)
+        REQUIRES(art::Locks::mutator_lock_);
+
+    void UpdateClass(art::ObjPtr<art::mirror::Class> mclass,
+                     art::ObjPtr<art::mirror::DexCache> new_dex_cache,
+                     art::ObjPtr<art::mirror::Object> original_dex_file)
+        REQUIRES(art::Locks::mutator_lock_);
+
+    void RestoreObsoleteMethodMapsIfUnneeded(const RedefinitionDataIter* cur_data)
+        REQUIRES(art::Locks::mutator_lock_);
+
+    void ReleaseDexFile() REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+    void UnregisterBreakpoints() REQUIRES_SHARED(art::Locks::mutator_lock_);
+    // This should be done with all threads suspended.
+    void UnregisterJvmtiBreakpoints() REQUIRES(art::Locks::mutator_lock_);
+
+   private:
+    Redefiner* driver_;
+    jclass klass_;
+    std::unique_ptr<const art::DexFile> dex_file_;
+    std::string class_sig_;
+    art::ArrayRef<const unsigned char> original_dex_file_;
+  };
+
+  ArtJvmTiEnv* env_;
+  jvmtiError result_;
+  art::Runtime* runtime_;
+  art::Thread* self_;
+  std::vector<ClassRedefinition> redefinitions_;
+  // Kept as a jclass since we have weird run-state changes that make keeping it around as a
+  // mirror::Class difficult and confusing.
+  std::string* error_msg_;
+
+  Redefiner(ArtJvmTiEnv* env,
+            art::Runtime* runtime,
+            art::Thread* self,
+            std::string* error_msg)
+      : env_(env),
+        result_(ERR(INTERNAL)),
+        runtime_(runtime),
+        self_(self),
+        redefinitions_(),
+        error_msg_(error_msg) { }
+
+  jvmtiError AddRedefinition(ArtJvmTiEnv* env, const ArtClassDefinition& def)
+      REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+  static jvmtiError GetClassRedefinitionError(art::Handle<art::mirror::Class> klass,
+                                              /*out*/std::string* error_msg)
+      REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+  jvmtiError Run() REQUIRES_SHARED(art::Locks::mutator_lock_);
+
+  bool CheckAllRedefinitionAreValid() REQUIRES_SHARED(art::Locks::mutator_lock_);
+  bool CheckAllClassesAreVerified(RedefinitionDataHolder& holder)
+      REQUIRES_SHARED(art::Locks::mutator_lock_);
+  bool EnsureAllClassAllocationsFinished(RedefinitionDataHolder& holder)
+      REQUIRES_SHARED(art::Locks::mutator_lock_);
+  bool FinishAllRemainingAllocations(RedefinitionDataHolder& holder)
+      REQUIRES_SHARED(art::Locks::mutator_lock_);
+  void ReleaseAllDexFiles() REQUIRES_SHARED(art::Locks::mutator_lock_);
+  void UnregisterAllBreakpoints() REQUIRES_SHARED(art::Locks::mutator_lock_);
+  // Restores the old obsolete methods maps if it turns out they weren't needed (ie there were no
+  // new obsolete methods).
+  void RestoreObsoleteMethodMapsIfUnneeded(RedefinitionDataHolder& holder)
+      REQUIRES(art::Locks::mutator_lock_);
+
+  void RecordFailure(jvmtiError result, const std::string& class_sig, const std::string& error_msg);
+  void RecordFailure(jvmtiError result, const std::string& error_msg) {
+    RecordFailure(result, "NO CLASS", error_msg);
+  }
+
+  friend struct CallbackCtx;
+  friend class RedefinitionDataHolder;
+  friend class RedefinitionDataIter;
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_REDEFINE_H_
diff --git a/openjdkjvmti/ti_search.cc b/openjdkjvmti/ti_search.cc
new file mode 100644
index 0000000..25bc5d6
--- /dev/null
+++ b/openjdkjvmti/ti_search.cc
@@ -0,0 +1,296 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_search.h"
+
+#include "jni.h"
+
+#include "art_field-inl.h"
+#include "art_jvmti.h"
+#include "base/enums.h"
+#include "base/macros.h"
+#include "class_linker.h"
+#include "dex_file.h"
+#include "jni_internal.h"
+#include "mirror/class-inl.h"
+#include "mirror/object.h"
+#include "mirror/string.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "obj_ptr-inl.h"
+#include "runtime.h"
+#include "runtime_callbacks.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+#include "thread_list.h"
+#include "ti_phase.h"
+#include "well_known_classes.h"
+
+namespace openjdkjvmti {
+
+static std::vector<std::string> gSystemOnloadSegments;
+
+static art::ObjPtr<art::mirror::Object> GetSystemProperties(art::Thread* self,
+                                                            art::ClassLinker* class_linker)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  art::ObjPtr<art::mirror::Class> system_class =
+      class_linker->LookupClass(self, "Ljava/lang/System;", nullptr);
+  DCHECK(system_class != nullptr);
+  DCHECK(system_class->IsInitialized());
+
+  art::ArtField* props_field =
+      system_class->FindDeclaredStaticField("props", "Ljava/util/Properties;");
+  DCHECK(props_field != nullptr);
+
+  art::ObjPtr<art::mirror::Object> props_obj = props_field->GetObject(system_class);
+  DCHECK(props_obj != nullptr);
+
+  return props_obj;
+}
+
+static void Update() REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  if (gSystemOnloadSegments.empty()) {
+    return;
+  }
+
+  // In the on-load phase we have to modify java.class.path to influence the system classloader.
+  // As this is an unmodifiable system property, we have to access the "defaults" field.
+  art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
+  DCHECK(class_linker != nullptr);
+  art::Thread* self = art::Thread::Current();
+
+  // Prepare: collect classes, fields and methods.
+  art::ObjPtr<art::mirror::Class> properties_class =
+      class_linker->LookupClass(self, "Ljava/util/Properties;", nullptr);
+  DCHECK(properties_class != nullptr);
+
+  ScopedLocalRef<jobject> defaults_jobj(self->GetJniEnv(), nullptr);
+  {
+    art::ObjPtr<art::mirror::Object> props_obj = GetSystemProperties(self, class_linker);
+
+    art::ArtField* defaults_field =
+        properties_class->FindDeclaredInstanceField("defaults", "Ljava/util/Properties;");
+    DCHECK(defaults_field != nullptr);
+
+    art::ObjPtr<art::mirror::Object> defaults_obj = defaults_field->GetObject(props_obj);
+    DCHECK(defaults_obj != nullptr);
+    defaults_jobj.reset(self->GetJniEnv()->AddLocalReference<jobject>(defaults_obj));
+  }
+
+  art::ArtMethod* get_property =
+      properties_class->FindClassMethod(
+          "getProperty",
+          "(Ljava/lang/String;)Ljava/lang/String;",
+          art::kRuntimePointerSize);
+  DCHECK(get_property != nullptr);
+  DCHECK(!get_property->IsDirect());
+  DCHECK(get_property->GetDeclaringClass() == properties_class);
+  art::ArtMethod* set_property =
+      properties_class->FindClassMethod(
+          "setProperty",
+          "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;",
+          art::kRuntimePointerSize);
+  DCHECK(set_property != nullptr);
+  DCHECK(!set_property->IsDirect());
+  DCHECK(set_property->GetDeclaringClass() == properties_class);
+
+  // This is an allocation. Do this late to avoid the need for handles.
+  ScopedLocalRef<jobject> cp_jobj(self->GetJniEnv(), nullptr);
+  {
+    art::ObjPtr<art::mirror::Object> cp_key =
+        art::mirror::String::AllocFromModifiedUtf8(self, "java.class.path");
+    if (cp_key == nullptr) {
+      self->AssertPendingOOMException();
+      self->ClearException();
+      return;
+    }
+    cp_jobj.reset(self->GetJniEnv()->AddLocalReference<jobject>(cp_key));
+  }
+
+  // OK, now get the current value.
+  std::string str_value;
+  {
+    ScopedLocalRef<jobject> old_value(self->GetJniEnv(),
+                                      self->GetJniEnv()->CallObjectMethod(
+                                          defaults_jobj.get(),
+                                          art::jni::EncodeArtMethod(get_property),
+                                          cp_jobj.get()));
+    DCHECK(old_value.get() != nullptr);
+
+    str_value = self->DecodeJObject(old_value.get())->AsString()->ToModifiedUtf8();
+    self->GetJniEnv()->DeleteLocalRef(old_value.release());
+  }
+
+  // Update the value by appending the new segments.
+  for (const std::string& segment : gSystemOnloadSegments) {
+    if (!str_value.empty()) {
+      str_value += ":";
+    }
+    str_value += segment;
+  }
+  gSystemOnloadSegments.clear();
+
+  // Create the new value object.
+  ScopedLocalRef<jobject> new_val_jobj(self->GetJniEnv(), nullptr);
+  {
+    art::ObjPtr<art::mirror::Object> new_value =
+        art::mirror::String::AllocFromModifiedUtf8(self, str_value.c_str());
+    if (new_value == nullptr) {
+      self->AssertPendingOOMException();
+      self->ClearException();
+      return;
+    }
+
+    new_val_jobj.reset(self->GetJniEnv()->AddLocalReference<jobject>(new_value));
+  }
+
+  // Write to the defaults.
+  ScopedLocalRef<jobject> res_obj(self->GetJniEnv(),
+                                  self->GetJniEnv()->CallObjectMethod(defaults_jobj.get(),
+                                      art::jni::EncodeArtMethod(set_property),
+                                      cp_jobj.get(),
+                                      new_val_jobj.get()));
+  if (self->IsExceptionPending()) {
+    self->ClearException();
+    return;
+  }
+}
+
+struct SearchCallback : public art::RuntimePhaseCallback {
+  void NextRuntimePhase(RuntimePhase phase) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    if (phase == RuntimePhase::kStart) {
+      // It's time to update the system properties.
+      Update();
+    }
+  }
+};
+
+static SearchCallback gSearchCallback;
+
+void SearchUtil::Register() {
+  art::Runtime* runtime = art::Runtime::Current();
+
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Add search callback");
+  runtime->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&gSearchCallback);
+}
+
+void SearchUtil::Unregister() {
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Remove search callback");
+  art::Runtime* runtime = art::Runtime::Current();
+  runtime->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&gSearchCallback);
+}
+
+jvmtiError SearchUtil::AddToBootstrapClassLoaderSearch(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                                       const char* segment) {
+  art::Runtime* current = art::Runtime::Current();
+  if (current == nullptr) {
+    return ERR(WRONG_PHASE);
+  }
+  if (current->GetClassLinker() == nullptr) {
+    return ERR(WRONG_PHASE);
+  }
+  if (segment == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  std::string error_msg;
+  std::vector<std::unique_ptr<const art::DexFile>> dex_files;
+  if (!art::DexFile::Open(segment, segment, true, &error_msg, &dex_files)) {
+    LOG(WARNING) << "Could not open " << segment << " for boot classpath extension: " << error_msg;
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  for (std::unique_ptr<const art::DexFile>& dex_file : dex_files) {
+    current->GetClassLinker()->AppendToBootClassPath(art::Thread::Current(), *dex_file.release());
+  }
+
+  return ERR(NONE);
+}
+
+jvmtiError SearchUtil::AddToSystemClassLoaderSearch(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
+                                                    const char* segment) {
+  if (segment == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  jvmtiPhase phase = PhaseUtil::GetPhaseUnchecked();
+
+  if (phase == jvmtiPhase::JVMTI_PHASE_ONLOAD) {
+    // We could try and see whether it is a valid path. We could also try to allocate Java
+    // objects to avoid later OOME.
+    gSystemOnloadSegments.push_back(segment);
+    return ERR(NONE);
+  } else if (phase != jvmtiPhase::JVMTI_PHASE_LIVE) {
+    return ERR(WRONG_PHASE);
+  }
+
+  jobject sys_class_loader = art::Runtime::Current()->GetSystemClassLoader();
+  if (sys_class_loader == nullptr) {
+    // This is unexpected.
+    return ERR(INTERNAL);
+  }
+
+  // We'll use BaseDexClassLoader.addDexPath, as it takes care of array resizing etc. As a downside,
+  // exceptions are swallowed.
+
+  art::Thread* self = art::Thread::Current();
+  JNIEnv* env = self->GetJniEnv();
+  if (!env->IsInstanceOf(sys_class_loader,
+                         art::WellKnownClasses::dalvik_system_BaseDexClassLoader)) {
+    return ERR(INTERNAL);
+  }
+
+  jmethodID add_dex_path_id = env->GetMethodID(
+      art::WellKnownClasses::dalvik_system_BaseDexClassLoader,
+      "addDexPath",
+      "(Ljava/lang/String;)V");
+  if (add_dex_path_id == nullptr) {
+    return ERR(INTERNAL);
+  }
+
+  ScopedLocalRef<jstring> dex_path(env, env->NewStringUTF(segment));
+  if (dex_path.get() == nullptr) {
+    return ERR(INTERNAL);
+  }
+  env->CallVoidMethod(sys_class_loader, add_dex_path_id, dex_path.get());
+
+  if (env->ExceptionCheck()) {
+    env->ExceptionClear();
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  return ERR(NONE);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_search.h b/openjdkjvmti/ti_search.h
new file mode 100644
index 0000000..81a28cc
--- /dev/null
+++ b/openjdkjvmti/ti_search.h
@@ -0,0 +1,53 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_SEARCH_H_
+#define ART_OPENJDKJVMTI_TI_SEARCH_H_
+
+#include <vector>
+
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class SearchUtil {
+ public:
+  static void Register();
+  static void Unregister();
+
+  static jvmtiError AddToBootstrapClassLoaderSearch(jvmtiEnv* env, const char* segment);
+
+  static jvmtiError AddToSystemClassLoaderSearch(jvmtiEnv* env, const char* segment);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_SEARCH_H_
diff --git a/openjdkjvmti/ti_stack.cc b/openjdkjvmti/ti_stack.cc
new file mode 100644
index 0000000..ff2de8d
--- /dev/null
+++ b/openjdkjvmti/ti_stack.cc
@@ -0,0 +1,827 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_stack.h"
+
+#include <algorithm>
+#include <list>
+#include <unordered_map>
+#include <vector>
+
+#include "art_field-inl.h"
+#include "art_jvmti.h"
+#include "art_method-inl.h"
+#include "barrier.h"
+#include "base/bit_utils.h"
+#include "base/enums.h"
+#include "base/mutex.h"
+#include "dex_file.h"
+#include "dex_file_annotations.h"
+#include "handle_scope-inl.h"
+#include "jni_env_ext.h"
+#include "jni_internal.h"
+#include "mirror/class.h"
+#include "mirror/dex_cache.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "scoped_thread_state_change-inl.h"
+#include "stack.h"
+#include "thread-current-inl.h"
+#include "thread_list.h"
+#include "thread_pool.h"
+#include "well_known_classes.h"
+
+namespace openjdkjvmti {
+
+template <typename FrameFn>
+struct GetStackTraceVisitor : public art::StackVisitor {
+  GetStackTraceVisitor(art::Thread* thread_in,
+                       size_t start_,
+                       size_t stop_,
+                       FrameFn fn_)
+      : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        fn(fn_),
+        start(start_),
+        stop(stop_) {}
+  GetStackTraceVisitor(const GetStackTraceVisitor&) = default;
+  GetStackTraceVisitor(GetStackTraceVisitor&&) = default;
+
+  bool VisitFrame() REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    art::ArtMethod* m = GetMethod();
+    if (m->IsRuntimeMethod()) {
+      return true;
+    }
+
+    if (start == 0) {
+      m = m->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
+      jmethodID id = art::jni::EncodeArtMethod(m);
+
+      uint32_t dex_pc = GetDexPc(false);
+      jlong dex_location = (dex_pc == art::DexFile::kDexNoIndex) ? -1 : static_cast<jlong>(dex_pc);
+
+      jvmtiFrameInfo info = { id, dex_location };
+      fn(info);
+
+      if (stop == 1) {
+        return false;  // We're done.
+      } else if (stop > 0) {
+        stop--;
+      }
+    } else {
+      start--;
+    }
+
+    return true;
+  }
+
+  FrameFn fn;
+  size_t start;
+  size_t stop;
+};
+
+template <typename FrameFn>
+GetStackTraceVisitor<FrameFn> MakeStackTraceVisitor(art::Thread* thread_in,
+                                                    size_t start,
+                                                    size_t stop,
+                                                    FrameFn fn) {
+  return GetStackTraceVisitor<FrameFn>(thread_in, start, stop, fn);
+}
+
+struct GetStackTraceVectorClosure : public art::Closure {
+ public:
+  GetStackTraceVectorClosure(size_t start, size_t stop)
+      : start_input(start),
+        stop_input(stop),
+        start_result(0),
+        stop_result(0) {}
+
+  void Run(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    auto frames_fn = [&](jvmtiFrameInfo info) {
+      frames.push_back(info);
+    };
+    auto visitor = MakeStackTraceVisitor(self, start_input, stop_input, frames_fn);
+    visitor.WalkStack(/* include_transitions */ false);
+
+    start_result = visitor.start;
+    stop_result = visitor.stop;
+  }
+
+  const size_t start_input;
+  const size_t stop_input;
+
+  std::vector<jvmtiFrameInfo> frames;
+  size_t start_result;
+  size_t stop_result;
+};
+
+static jvmtiError TranslateFrameVector(const std::vector<jvmtiFrameInfo>& frames,
+                                       jint start_depth,
+                                       size_t start_result,
+                                       jint max_frame_count,
+                                       jvmtiFrameInfo* frame_buffer,
+                                       jint* count_ptr) {
+  size_t collected_frames = frames.size();
+
+  // Assume we're here having collected something.
+  DCHECK_GT(max_frame_count, 0);
+
+  // Frames from the top.
+  if (start_depth >= 0) {
+    if (start_result != 0) {
+      // Not enough frames.
+      return ERR(ILLEGAL_ARGUMENT);
+    }
+    DCHECK_LE(collected_frames, static_cast<size_t>(max_frame_count));
+    if (frames.size() > 0) {
+      memcpy(frame_buffer, frames.data(), collected_frames * sizeof(jvmtiFrameInfo));
+    }
+    *count_ptr = static_cast<jint>(frames.size());
+    return ERR(NONE);
+  }
+
+  // Frames from the bottom.
+  if (collected_frames < static_cast<size_t>(-start_depth)) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+
+  size_t count = std::min(static_cast<size_t>(-start_depth), static_cast<size_t>(max_frame_count));
+  memcpy(frame_buffer,
+         &frames.data()[collected_frames + start_depth],
+         count * sizeof(jvmtiFrameInfo));
+  *count_ptr = static_cast<jint>(count);
+  return ERR(NONE);
+}
+
+struct GetStackTraceDirectClosure : public art::Closure {
+ public:
+  GetStackTraceDirectClosure(jvmtiFrameInfo* frame_buffer_, size_t start, size_t stop)
+      : frame_buffer(frame_buffer_),
+        start_input(start),
+        stop_input(stop),
+        index(0) {
+    DCHECK_GE(start_input, 0u);
+  }
+
+  void Run(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    auto frames_fn = [&](jvmtiFrameInfo info) {
+      frame_buffer[index] = info;
+      ++index;
+    };
+    auto visitor = MakeStackTraceVisitor(self, start_input, stop_input, frames_fn);
+    visitor.WalkStack(/* include_transitions */ false);
+  }
+
+  jvmtiFrameInfo* frame_buffer;
+
+  const size_t start_input;
+  const size_t stop_input;
+
+  size_t index = 0;
+};
+
+static jvmtiError GetThread(JNIEnv* env,
+                            art::ScopedObjectAccessAlreadyRunnable& soa,
+                            jthread java_thread,
+                            art::Thread** thread)
+    REQUIRES_SHARED(art::Locks::mutator_lock_)  // Needed for FromManagedThread.
+    REQUIRES(art::Locks::thread_list_lock_) {   // Needed for FromManagedThread.
+  if (java_thread == nullptr) {
+    *thread = art::Thread::Current();
+    if (*thread == nullptr) {
+      // GetStackTrace can only be run during the live phase, so the current thread should be
+      // attached and thus available. Getting a null for current means we're starting up or
+      // dying.
+      return ERR(WRONG_PHASE);
+    }
+  } else {
+    if (!env->IsInstanceOf(java_thread, art::WellKnownClasses::java_lang_Thread)) {
+      return ERR(INVALID_THREAD);
+    }
+
+    // TODO: Need non-aborting call here, to return JVMTI_ERROR_INVALID_THREAD.
+    *thread = art::Thread::FromManagedThread(soa, java_thread);
+    if (*thread == nullptr) {
+      return ERR(THREAD_NOT_ALIVE);
+    }
+  }
+  return ERR(NONE);
+}
+
+jvmtiError StackUtil::GetStackTrace(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
+                                    jthread java_thread,
+                                    jint start_depth,
+                                    jint max_frame_count,
+                                    jvmtiFrameInfo* frame_buffer,
+                                    jint* count_ptr) {
+  // It is not great that we have to hold these locks for so long, but it is necessary to ensure
+  // that the thread isn't dying on us.
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
+
+  art::Thread* thread;
+  jvmtiError thread_error = GetThread(art::Thread::Current()->GetJniEnv(),
+                                      soa,
+                                      java_thread,
+                                      &thread);
+  if (thread_error != ERR(NONE)) {
+    return thread_error;
+  }
+  DCHECK(thread != nullptr);
+
+  art::ThreadState state = thread->GetState();
+  if (state == art::ThreadState::kStarting ||
+      state == art::ThreadState::kTerminated ||
+      thread->IsStillStarting()) {
+    return ERR(THREAD_NOT_ALIVE);
+  }
+
+  if (max_frame_count < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  if (frame_buffer == nullptr || count_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  if (max_frame_count == 0) {
+    *count_ptr = 0;
+    return ERR(NONE);
+  }
+
+  if (start_depth >= 0) {
+    // Fast path: Regular order of stack trace. Fill into the frame_buffer directly.
+    GetStackTraceDirectClosure closure(frame_buffer,
+                                       static_cast<size_t>(start_depth),
+                                       static_cast<size_t>(max_frame_count));
+    thread->RequestSynchronousCheckpoint(&closure);
+    *count_ptr = static_cast<jint>(closure.index);
+    if (closure.index < static_cast<size_t>(start_depth)) {
+      return ERR(ILLEGAL_ARGUMENT);
+    }
+    return ERR(NONE);
+  }
+
+  GetStackTraceVectorClosure closure(0, 0);
+  thread->RequestSynchronousCheckpoint(&closure);
+
+  return TranslateFrameVector(closure.frames,
+                              start_depth,
+                              closure.start_result,
+                              max_frame_count,
+                              frame_buffer,
+                              count_ptr);
+}
+
+template <typename Data>
+struct GetAllStackTracesVectorClosure : public art::Closure {
+  GetAllStackTracesVectorClosure(size_t stop, Data* data_)
+      : barrier(0), stop_input(stop), data(data_) {}
+
+  void Run(art::Thread* thread) OVERRIDE
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!data->mutex) {
+    art::Thread* self = art::Thread::Current();
+    Work(thread, self);
+    barrier.Pass(self);
+  }
+
+  void Work(art::Thread* thread, art::Thread* self)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(!data->mutex) {
+    // Skip threads that are still starting.
+    if (thread->IsStillStarting()) {
+      return;
+    }
+
+    std::vector<jvmtiFrameInfo>* thread_frames = data->GetFrameStorageFor(self, thread);
+    if (thread_frames == nullptr) {
+      return;
+    }
+
+    // Now collect the data.
+    auto frames_fn = [&](jvmtiFrameInfo info) {
+      thread_frames->push_back(info);
+    };
+    auto visitor = MakeStackTraceVisitor(thread, 0u, stop_input, frames_fn);
+    visitor.WalkStack(/* include_transitions */ false);
+  }
+
+  art::Barrier barrier;
+  const size_t stop_input;
+  Data* data;
+};
+
+template <typename Data>
+static void RunCheckpointAndWait(Data* data, size_t max_frame_count) {
+  GetAllStackTracesVectorClosure<Data> closure(max_frame_count, data);
+  size_t barrier_count = art::Runtime::Current()->GetThreadList()->RunCheckpoint(&closure, nullptr);
+  if (barrier_count == 0) {
+    return;
+  }
+  art::Thread* self = art::Thread::Current();
+  art::ScopedThreadStateChange tsc(self, art::ThreadState::kWaitingForCheckPointsToRun);
+  closure.barrier.Increment(self, barrier_count);
+}
+
+jvmtiError StackUtil::GetAllStackTraces(jvmtiEnv* env,
+                                        jint max_frame_count,
+                                        jvmtiStackInfo** stack_info_ptr,
+                                        jint* thread_count_ptr) {
+  if (max_frame_count < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  if (stack_info_ptr == nullptr || thread_count_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  struct AllStackTracesData {
+    AllStackTracesData() : mutex("GetAllStackTraces", art::LockLevel::kAbortLock) {}
+    ~AllStackTracesData() {
+      JNIEnv* jni_env = art::Thread::Current()->GetJniEnv();
+      for (jthread global_thread_ref : thread_peers) {
+        jni_env->DeleteGlobalRef(global_thread_ref);
+      }
+    }
+
+    std::vector<jvmtiFrameInfo>* GetFrameStorageFor(art::Thread* self, art::Thread* thread)
+        REQUIRES_SHARED(art::Locks::mutator_lock_)
+        REQUIRES(!mutex) {
+      art::MutexLock mu(self, mutex);
+
+      threads.push_back(thread);
+
+      jthread peer = art::Runtime::Current()->GetJavaVM()->AddGlobalRef(
+          self, thread->GetPeerFromOtherThread());
+      thread_peers.push_back(peer);
+
+      frames.emplace_back(new std::vector<jvmtiFrameInfo>());
+      return frames.back().get();
+    }
+
+    art::Mutex mutex;
+
+    // Storage. Only access directly after completion.
+
+    std::vector<art::Thread*> threads;
+    // "thread_peers" contains global references to their peers.
+    std::vector<jthread> thread_peers;
+
+    std::vector<std::unique_ptr<std::vector<jvmtiFrameInfo>>> frames;
+  };
+
+  AllStackTracesData data;
+  RunCheckpointAndWait(&data, static_cast<size_t>(max_frame_count));
+
+  art::Thread* current = art::Thread::Current();
+
+  // Convert the data into our output format.
+
+  // Note: we use an array of jvmtiStackInfo for convenience. The spec says we need to
+  //       allocate one big chunk for this and the actual frames, which means we need
+  //       to either be conservative or rearrange things later (the latter is implemented).
+  std::unique_ptr<jvmtiStackInfo[]> stack_info_array(new jvmtiStackInfo[data.frames.size()]);
+  std::vector<std::unique_ptr<jvmtiFrameInfo[]>> frame_infos;
+  frame_infos.reserve(data.frames.size());
+
+  // Now run through and add data for each thread.
+  size_t sum_frames = 0;
+  for (size_t index = 0; index < data.frames.size(); ++index) {
+    jvmtiStackInfo& stack_info = stack_info_array.get()[index];
+    memset(&stack_info, 0, sizeof(jvmtiStackInfo));
+
+    const std::vector<jvmtiFrameInfo>& thread_frames = *data.frames[index].get();
+
+    // For the time being, set the thread to null. We'll fix it up in the second stage.
+    stack_info.thread = nullptr;
+    stack_info.state = JVMTI_THREAD_STATE_SUSPENDED;
+
+    size_t collected_frames = thread_frames.size();
+    if (max_frame_count == 0 || collected_frames == 0) {
+      stack_info.frame_count = 0;
+      stack_info.frame_buffer = nullptr;
+      continue;
+    }
+    DCHECK_LE(collected_frames, static_cast<size_t>(max_frame_count));
+
+    jvmtiFrameInfo* frame_info = new jvmtiFrameInfo[collected_frames];
+    frame_infos.emplace_back(frame_info);
+
+    jint count;
+    jvmtiError translate_result = TranslateFrameVector(thread_frames,
+                                                       0,
+                                                       0,
+                                                       static_cast<jint>(collected_frames),
+                                                       frame_info,
+                                                       &count);
+    DCHECK(translate_result == JVMTI_ERROR_NONE);
+    stack_info.frame_count = static_cast<jint>(collected_frames);
+    stack_info.frame_buffer = frame_info;
+    sum_frames += static_cast<size_t>(count);
+  }
+
+  // No errors, yet. Now put it all into an output buffer.
+  size_t rounded_stack_info_size = art::RoundUp(sizeof(jvmtiStackInfo) * data.frames.size(),
+                                                alignof(jvmtiFrameInfo));
+  size_t chunk_size = rounded_stack_info_size + sum_frames * sizeof(jvmtiFrameInfo);
+  unsigned char* chunk_data;
+  jvmtiError alloc_result = env->Allocate(chunk_size, &chunk_data);
+  if (alloc_result != ERR(NONE)) {
+    return alloc_result;
+  }
+
+  jvmtiStackInfo* stack_info = reinterpret_cast<jvmtiStackInfo*>(chunk_data);
+  // First copy in all the basic data.
+  memcpy(stack_info, stack_info_array.get(), sizeof(jvmtiStackInfo) * data.frames.size());
+
+  // Now copy the frames and fix up the pointers.
+  jvmtiFrameInfo* frame_info = reinterpret_cast<jvmtiFrameInfo*>(
+      chunk_data + rounded_stack_info_size);
+  for (size_t i = 0; i < data.frames.size(); ++i) {
+    jvmtiStackInfo& old_stack_info = stack_info_array.get()[i];
+    jvmtiStackInfo& new_stack_info = stack_info[i];
+
+    // Translate the global ref into a local ref.
+    new_stack_info.thread =
+        static_cast<JNIEnv*>(current->GetJniEnv())->NewLocalRef(data.thread_peers[i]);
+
+    if (old_stack_info.frame_count > 0) {
+      // Only copy when there's data - leave the nullptr alone.
+      size_t frames_size = static_cast<size_t>(old_stack_info.frame_count) * sizeof(jvmtiFrameInfo);
+      memcpy(frame_info, old_stack_info.frame_buffer, frames_size);
+      new_stack_info.frame_buffer = frame_info;
+      frame_info += old_stack_info.frame_count;
+    }
+  }
+
+  *stack_info_ptr = stack_info;
+  *thread_count_ptr = static_cast<jint>(data.frames.size());
+
+  return ERR(NONE);
+}
+
+jvmtiError StackUtil::GetThreadListStackTraces(jvmtiEnv* env,
+                                               jint thread_count,
+                                               const jthread* thread_list,
+                                               jint max_frame_count,
+                                               jvmtiStackInfo** stack_info_ptr) {
+  if (max_frame_count < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  if (thread_count < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  if (thread_count == 0) {
+    *stack_info_ptr = nullptr;
+    return ERR(NONE);
+  }
+  if (stack_info_ptr == nullptr || stack_info_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::Thread* current = art::Thread::Current();
+  art::ScopedObjectAccess soa(current);      // Now we know we have the shared lock.
+
+  struct SelectStackTracesData {
+    SelectStackTracesData() : mutex("GetSelectStackTraces", art::LockLevel::kAbortLock) {}
+
+    std::vector<jvmtiFrameInfo>* GetFrameStorageFor(art::Thread* self, art::Thread* thread)
+              REQUIRES_SHARED(art::Locks::mutator_lock_)
+              REQUIRES(!mutex) {
+      art::ObjPtr<art::mirror::Object> peer = thread->GetPeerFromOtherThread();
+      for (size_t index = 0; index != handles.size(); ++index) {
+        if (peer == handles[index].Get()) {
+          // Found the thread.
+          art::MutexLock mu(self, mutex);
+
+          threads.push_back(thread);
+          thread_list_indices.push_back(index);
+
+          frames.emplace_back(new std::vector<jvmtiFrameInfo>());
+          return frames.back().get();
+        }
+      }
+      return nullptr;
+    }
+
+    art::Mutex mutex;
+
+    // Selection data.
+
+    std::vector<art::Handle<art::mirror::Object>> handles;
+
+    // Storage. Only access directly after completion.
+
+    std::vector<art::Thread*> threads;
+    std::vector<size_t> thread_list_indices;
+
+    std::vector<std::unique_ptr<std::vector<jvmtiFrameInfo>>> frames;
+  };
+
+  SelectStackTracesData data;
+
+  // Decode all threads to raw pointers. Put them into a handle scope to avoid any moving GC bugs.
+  art::VariableSizedHandleScope hs(current);
+  for (jint i = 0; i != thread_count; ++i) {
+    if (thread_list[i] == nullptr) {
+      return ERR(INVALID_THREAD);
+    }
+    if (!soa.Env()->IsInstanceOf(thread_list[i], art::WellKnownClasses::java_lang_Thread)) {
+      return ERR(INVALID_THREAD);
+    }
+    data.handles.push_back(hs.NewHandle(soa.Decode<art::mirror::Object>(thread_list[i])));
+  }
+
+  RunCheckpointAndWait(&data, static_cast<size_t>(max_frame_count));
+
+  // Convert the data into our output format.
+
+  // Note: we use an array of jvmtiStackInfo for convenience. The spec says we need to
+  //       allocate one big chunk for this and the actual frames, which means we need
+  //       to either be conservative or rearrange things later (the latter is implemented).
+  std::unique_ptr<jvmtiStackInfo[]> stack_info_array(new jvmtiStackInfo[data.frames.size()]);
+  std::vector<std::unique_ptr<jvmtiFrameInfo[]>> frame_infos;
+  frame_infos.reserve(data.frames.size());
+
+  // Now run through and add data for each thread.
+  size_t sum_frames = 0;
+  for (size_t index = 0; index < data.frames.size(); ++index) {
+    jvmtiStackInfo& stack_info = stack_info_array.get()[index];
+    memset(&stack_info, 0, sizeof(jvmtiStackInfo));
+
+    art::Thread* self = data.threads[index];
+    const std::vector<jvmtiFrameInfo>& thread_frames = *data.frames[index].get();
+
+    // For the time being, set the thread to null. We don't have good ScopedLocalRef
+    // infrastructure.
+    DCHECK(self->GetPeerFromOtherThread() != nullptr);
+    stack_info.thread = nullptr;
+    stack_info.state = JVMTI_THREAD_STATE_SUSPENDED;
+
+    size_t collected_frames = thread_frames.size();
+    if (max_frame_count == 0 || collected_frames == 0) {
+      stack_info.frame_count = 0;
+      stack_info.frame_buffer = nullptr;
+      continue;
+    }
+    DCHECK_LE(collected_frames, static_cast<size_t>(max_frame_count));
+
+    jvmtiFrameInfo* frame_info = new jvmtiFrameInfo[collected_frames];
+    frame_infos.emplace_back(frame_info);
+
+    jint count;
+    jvmtiError translate_result = TranslateFrameVector(thread_frames,
+                                                       0,
+                                                       0,
+                                                       static_cast<jint>(collected_frames),
+                                                       frame_info,
+                                                       &count);
+    DCHECK(translate_result == JVMTI_ERROR_NONE);
+    stack_info.frame_count = static_cast<jint>(collected_frames);
+    stack_info.frame_buffer = frame_info;
+    sum_frames += static_cast<size_t>(count);
+  }
+
+  // No errors, yet. Now put it all into an output buffer. Note that this is not frames.size(),
+  // potentially.
+  size_t rounded_stack_info_size = art::RoundUp(sizeof(jvmtiStackInfo) * thread_count,
+                                                alignof(jvmtiFrameInfo));
+  size_t chunk_size = rounded_stack_info_size + sum_frames * sizeof(jvmtiFrameInfo);
+  unsigned char* chunk_data;
+  jvmtiError alloc_result = env->Allocate(chunk_size, &chunk_data);
+  if (alloc_result != ERR(NONE)) {
+    return alloc_result;
+  }
+
+  jvmtiStackInfo* stack_info = reinterpret_cast<jvmtiStackInfo*>(chunk_data);
+  jvmtiFrameInfo* frame_info = reinterpret_cast<jvmtiFrameInfo*>(
+      chunk_data + rounded_stack_info_size);
+
+  for (size_t i = 0; i < static_cast<size_t>(thread_count); ++i) {
+    // Check whether we found a running thread for this.
+    // Note: For simplicity, and with the expectation that the list is usually small, use a simple
+    //       search. (The list is *not* sorted!)
+    auto it = std::find(data.thread_list_indices.begin(), data.thread_list_indices.end(), i);
+    if (it == data.thread_list_indices.end()) {
+      // No native thread. Must be new or dead. We need to fill out the stack info now.
+      // (Need to read the Java "started" field to know whether this is starting or terminated.)
+      art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread_list[i]);
+      art::ObjPtr<art::mirror::Class> klass = peer->GetClass();
+      art::ArtField* started_field = klass->FindDeclaredInstanceField("started", "Z");
+      CHECK(started_field != nullptr);
+      bool started = started_field->GetBoolean(peer) != 0;
+      constexpr jint kStartedState = JVMTI_JAVA_LANG_THREAD_STATE_NEW;
+      constexpr jint kTerminatedState = JVMTI_THREAD_STATE_TERMINATED |
+          JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
+      stack_info[i].thread = reinterpret_cast<JNIEnv*>(soa.Env())->NewLocalRef(thread_list[i]);
+      stack_info[i].state = started ? kTerminatedState : kStartedState;
+      stack_info[i].frame_count = 0;
+      stack_info[i].frame_buffer = nullptr;
+    } else {
+      // Had a native thread and frames.
+      size_t f_index = it - data.thread_list_indices.begin();
+
+      jvmtiStackInfo& old_stack_info = stack_info_array.get()[f_index];
+      jvmtiStackInfo& new_stack_info = stack_info[i];
+
+      memcpy(&new_stack_info, &old_stack_info, sizeof(jvmtiStackInfo));
+      new_stack_info.thread = reinterpret_cast<JNIEnv*>(soa.Env())->NewLocalRef(thread_list[i]);
+      if (old_stack_info.frame_count > 0) {
+        // Only copy when there's data - leave the nullptr alone.
+        size_t frames_size =
+            static_cast<size_t>(old_stack_info.frame_count) * sizeof(jvmtiFrameInfo);
+        memcpy(frame_info, old_stack_info.frame_buffer, frames_size);
+        new_stack_info.frame_buffer = frame_info;
+        frame_info += old_stack_info.frame_count;
+      }
+    }
+  }
+
+  *stack_info_ptr = stack_info;
+
+  return ERR(NONE);
+}
+
+// Walks up the stack counting Java frames. This is not StackVisitor::ComputeNumFrames, as
+// runtime methods and transitions must not be counted.
+struct GetFrameCountVisitor : public art::StackVisitor {
+  explicit GetFrameCountVisitor(art::Thread* thread)
+      : art::StackVisitor(thread, nullptr, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        count(0) {}
+
+  bool VisitFrame() REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    art::ArtMethod* m = GetMethod();
+    const bool do_count = !(m == nullptr || m->IsRuntimeMethod());
+    if (do_count) {
+      count++;
+    }
+    return true;
+  }
+
+  size_t count;
+};
+
+struct GetFrameCountClosure : public art::Closure {
+ public:
+  GetFrameCountClosure() : count(0) {}
+
+  void Run(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    GetFrameCountVisitor visitor(self);
+    visitor.WalkStack(false);
+
+    count = visitor.count;
+  }
+
+  size_t count;
+};
+
+jvmtiError StackUtil::GetFrameCount(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                    jthread java_thread,
+                                    jint* count_ptr) {
+  // It is not great that we have to hold these locks for so long, but it is necessary to ensure
+  // that the thread isn't dying on us.
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
+
+  art::Thread* thread;
+  jvmtiError thread_error = GetThread(art::Thread::Current()->GetJniEnv(),
+                                      soa,
+                                      java_thread,
+                                      &thread);
+
+  if (thread_error != ERR(NONE)) {
+    return thread_error;
+  }
+  DCHECK(thread != nullptr);
+
+  if (count_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  GetFrameCountClosure closure;
+  thread->RequestSynchronousCheckpoint(&closure);
+
+  *count_ptr = closure.count;
+  return ERR(NONE);
+}
+
+// Walks up the stack 'n' callers, when used with Thread::WalkStack.
+struct GetLocationVisitor : public art::StackVisitor {
+  GetLocationVisitor(art::Thread* thread, size_t n_in)
+      : art::StackVisitor(thread, nullptr, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        n(n_in),
+        count(0),
+        caller(nullptr),
+        caller_dex_pc(0) {}
+
+  bool VisitFrame() REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    art::ArtMethod* m = GetMethod();
+    const bool do_count = !(m == nullptr || m->IsRuntimeMethod());
+    if (do_count) {
+      DCHECK(caller == nullptr);
+      if (count == n) {
+        caller = m;
+        caller_dex_pc = GetDexPc(false);
+        return false;
+      }
+      count++;
+    }
+    return true;
+  }
+
+  const size_t n;
+  size_t count;
+  art::ArtMethod* caller;
+  uint32_t caller_dex_pc;
+};
+
+struct GetLocationClosure : public art::Closure {
+ public:
+  explicit GetLocationClosure(size_t n_in) : n(n_in), method(nullptr), dex_pc(0) {}
+
+  void Run(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    GetLocationVisitor visitor(self, n);
+    visitor.WalkStack(false);
+
+    method = visitor.caller;
+    dex_pc = visitor.caller_dex_pc;
+  }
+
+  const size_t n;
+  art::ArtMethod* method;
+  uint32_t dex_pc;
+};
+
+jvmtiError StackUtil::GetFrameLocation(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                       jthread java_thread,
+                                       jint depth,
+                                       jmethodID* method_ptr,
+                                       jlocation* location_ptr) {
+  // It is not great that we have to hold these locks for so long, but it is necessary to ensure
+  // that the thread isn't dying on us.
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
+
+  art::Thread* thread;
+  jvmtiError thread_error = GetThread(art::Thread::Current()->GetJniEnv(),
+                                      soa,
+                                      java_thread,
+                                      &thread);
+  if (thread_error != ERR(NONE)) {
+    return thread_error;
+  }
+  DCHECK(thread != nullptr);
+
+  if (depth < 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  if (method_ptr == nullptr || location_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  GetLocationClosure closure(static_cast<size_t>(depth));
+  thread->RequestSynchronousCheckpoint(&closure);
+
+  if (closure.method == nullptr) {
+    return ERR(NO_MORE_FRAMES);
+  }
+
+  *method_ptr = art::jni::EncodeArtMethod(closure.method);
+  if (closure.method->IsNative()) {
+    *location_ptr = -1;
+  } else {
+    if (closure.dex_pc == art::DexFile::kDexNoIndex) {
+      return ERR(INTERNAL);
+    }
+    *location_ptr = static_cast<jlocation>(closure.dex_pc);
+  }
+
+  return ERR(NONE);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_stack.h b/openjdkjvmti/ti_stack.h
new file mode 100644
index 0000000..2e96b82
--- /dev/null
+++ b/openjdkjvmti/ti_stack.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_STACK_H_
+#define ART_OPENJDKJVMTI_TI_STACK_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+#include "base/mutex.h"
+
+namespace openjdkjvmti {
+
+class StackUtil {
+ public:
+  static jvmtiError GetAllStackTraces(jvmtiEnv* env,
+                                      jint max_frame_count,
+                                      jvmtiStackInfo** stack_info_ptr,
+                                      jint* thread_count_ptr)
+      REQUIRES(!art::Locks::thread_list_lock_);
+
+  static jvmtiError GetFrameCount(jvmtiEnv* env, jthread thread, jint* count_ptr);
+
+  static jvmtiError GetFrameLocation(jvmtiEnv* env,
+                                     jthread thread,
+                                     jint depth,
+                                     jmethodID* method_ptr,
+                                     jlocation* location_ptr);
+
+  static jvmtiError GetStackTrace(jvmtiEnv* env,
+                                  jthread thread,
+                                  jint start_depth,
+                                  jint max_frame_count,
+                                  jvmtiFrameInfo* frame_buffer,
+                                  jint* count_ptr);
+
+  static jvmtiError GetThreadListStackTraces(jvmtiEnv* env,
+                                             jint thread_count,
+                                             const jthread* thread_list,
+                                             jint max_frame_count,
+                                             jvmtiStackInfo** stack_info_ptr);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_STACK_H_
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc
new file mode 100644
index 0000000..6fa73f8
--- /dev/null
+++ b/openjdkjvmti/ti_thread.cc
@@ -0,0 +1,909 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_thread.h"
+
+#include "android-base/strings.h"
+#include "art_field-inl.h"
+#include "art_jvmti.h"
+#include "base/logging.h"
+#include "base/mutex.h"
+#include "events-inl.h"
+#include "gc/system_weak.h"
+#include "gc_root-inl.h"
+#include "jni_internal.h"
+#include "mirror/class.h"
+#include "mirror/object-inl.h"
+#include "mirror/string.h"
+#include "nativehelper/ScopedLocalRef.h"
+#include "obj_ptr.h"
+#include "runtime.h"
+#include "runtime_callbacks.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+#include "thread_list.h"
+#include "ti_phase.h"
+#include "well_known_classes.h"
+
+namespace openjdkjvmti {
+
+art::ArtField* ThreadUtil::context_class_loader_ = nullptr;
+
+struct ThreadCallback : public art::ThreadLifecycleCallback, public art::RuntimePhaseCallback {
+  jthread GetThreadObject(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    if (self->GetPeer() == nullptr) {
+      return nullptr;
+    }
+    return self->GetJniEnv()->AddLocalReference<jthread>(self->GetPeer());
+  }
+  template <ArtJvmtiEvent kEvent>
+  void Post(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    DCHECK_EQ(self, art::Thread::Current());
+    ScopedLocalRef<jthread> thread(self->GetJniEnv(), GetThreadObject(self));
+    art::ScopedThreadSuspension sts(self, art::ThreadState::kNative);
+    event_handler->DispatchEvent<kEvent>(self,
+                                         reinterpret_cast<JNIEnv*>(self->GetJniEnv()),
+                                         thread.get());
+  }
+
+  void ThreadStart(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    if (!started) {
+      // Runtime isn't started. We only expect at most the signal handler or JIT threads to be
+      // started here.
+      if (art::kIsDebugBuild) {
+        std::string name;
+        self->GetThreadName(name);
+        if (name != "JDWP" &&
+            name != "Signal Catcher" &&
+            !android::base::StartsWith(name, "Jit thread pool")) {
+          LOG(FATAL) << "Unexpected thread before start: " << name;
+        }
+      }
+      return;
+    }
+    Post<ArtJvmtiEvent::kThreadStart>(self);
+  }
+
+  void ThreadDeath(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    Post<ArtJvmtiEvent::kThreadEnd>(self);
+  }
+
+  void NextRuntimePhase(RuntimePhase phase) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    if (phase == RuntimePhase::kInit) {
+      // We moved to VMInit. Report the main thread as started (it was attached early, and must
+      // not be reported until Init.
+      started = true;
+      Post<ArtJvmtiEvent::kThreadStart>(art::Thread::Current());
+    }
+  }
+
+  EventHandler* event_handler = nullptr;
+  bool started = false;
+};
+
+ThreadCallback gThreadCallback;
+
+void ThreadUtil::Register(EventHandler* handler) {
+  art::Runtime* runtime = art::Runtime::Current();
+
+  gThreadCallback.started = runtime->IsStarted();
+  gThreadCallback.event_handler = handler;
+
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Add thread callback");
+  runtime->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&gThreadCallback);
+  runtime->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&gThreadCallback);
+}
+
+void ThreadUtil::CacheData() {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ObjPtr<art::mirror::Class> thread_class =
+      soa.Decode<art::mirror::Class>(art::WellKnownClasses::java_lang_Thread);
+  CHECK(thread_class != nullptr);
+  context_class_loader_ = thread_class->FindDeclaredInstanceField("contextClassLoader",
+                                                                  "Ljava/lang/ClassLoader;");
+  CHECK(context_class_loader_ != nullptr);
+}
+
+void ThreadUtil::Unregister() {
+  art::ScopedThreadStateChange stsc(art::Thread::Current(),
+                                    art::ThreadState::kWaitingForDebuggerToAttach);
+  art::ScopedSuspendAll ssa("Remove thread callback");
+  art::Runtime* runtime = art::Runtime::Current();
+  runtime->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&gThreadCallback);
+  runtime->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&gThreadCallback);
+}
+
+jvmtiError ThreadUtil::GetCurrentThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread* thread_ptr) {
+  art::Thread* self = art::Thread::Current();
+
+  art::ScopedObjectAccess soa(self);
+
+  jthread thread_peer;
+  if (self->IsStillStarting()) {
+    thread_peer = nullptr;
+  } else {
+    thread_peer = soa.AddLocalReference<jthread>(self->GetPeer());
+  }
+
+  *thread_ptr = thread_peer;
+  return ERR(NONE);
+}
+
+// Get the native thread. The spec says a null object denotes the current thread.
+art::Thread* ThreadUtil::GetNativeThread(jthread thread,
+                                         const art::ScopedObjectAccessAlreadyRunnable& soa) {
+  if (thread == nullptr) {
+    return art::Thread::Current();
+  }
+
+  return art::Thread::FromManagedThread(soa, thread);
+}
+
+jvmtiError ThreadUtil::GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr) {
+  if (info_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  if (!PhaseUtil::IsLivePhase()) {
+    return JVMTI_ERROR_WRONG_PHASE;
+  }
+
+  art::Thread* self = art::Thread::Current();
+  art::ScopedObjectAccess soa(self);
+  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+
+  art::Thread* target = GetNativeThread(thread, soa);
+  if (target == nullptr && thread == nullptr) {
+    return ERR(INVALID_THREAD);
+  }
+
+  JvmtiUniquePtr<char[]> name_uptr;
+  if (target != nullptr) {
+    // Have a native thread object, this thread is alive.
+    std::string name;
+    target->GetThreadName(name);
+    jvmtiError name_result;
+    name_uptr = CopyString(env, name.c_str(), &name_result);
+    if (name_uptr == nullptr) {
+      return name_result;
+    }
+    info_ptr->name = name_uptr.get();
+
+    info_ptr->priority = target->GetNativePriority();
+
+    info_ptr->is_daemon = target->IsDaemon();
+
+    art::ObjPtr<art::mirror::Object> peer = target->GetPeerFromOtherThread();
+
+    // ThreadGroup.
+    if (peer != nullptr) {
+      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group);
+      CHECK(f != nullptr);
+      art::ObjPtr<art::mirror::Object> group = f->GetObject(peer);
+      info_ptr->thread_group = group == nullptr
+                                   ? nullptr
+                                   : soa.AddLocalReference<jthreadGroup>(group);
+    } else {
+      info_ptr->thread_group = nullptr;
+    }
+
+    // Context classloader.
+    DCHECK(context_class_loader_ != nullptr);
+    art::ObjPtr<art::mirror::Object> ccl = peer != nullptr
+        ? context_class_loader_->GetObject(peer)
+        : nullptr;
+    info_ptr->context_class_loader = ccl == nullptr
+                                         ? nullptr
+                                         : soa.AddLocalReference<jobject>(ccl);
+  } else {
+    // Only the peer. This thread has either not been started, or is dead. Read things from
+    // the Java side.
+    art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread);
+
+    // Name.
+    {
+      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_name);
+      CHECK(f != nullptr);
+      art::ObjPtr<art::mirror::Object> name = f->GetObject(peer);
+      std::string name_cpp;
+      const char* name_cstr;
+      if (name != nullptr) {
+        name_cpp = name->AsString()->ToModifiedUtf8();
+        name_cstr = name_cpp.c_str();
+      } else {
+        name_cstr = "";
+      }
+      jvmtiError name_result;
+      name_uptr = CopyString(env, name_cstr, &name_result);
+      if (name_uptr == nullptr) {
+        return name_result;
+      }
+      info_ptr->name = name_uptr.get();
+    }
+
+    // Priority.
+    {
+      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_priority);
+      CHECK(f != nullptr);
+      info_ptr->priority = static_cast<jint>(f->GetInt(peer));
+    }
+
+    // Daemon.
+    {
+      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_daemon);
+      CHECK(f != nullptr);
+      info_ptr->is_daemon = f->GetBoolean(peer) == 0 ? JNI_FALSE : JNI_TRUE;
+    }
+
+    // ThreadGroup.
+    {
+      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group);
+      CHECK(f != nullptr);
+      art::ObjPtr<art::mirror::Object> group = f->GetObject(peer);
+      info_ptr->thread_group = group == nullptr
+                                   ? nullptr
+                                   : soa.AddLocalReference<jthreadGroup>(group);
+    }
+
+    // Context classloader.
+    DCHECK(context_class_loader_ != nullptr);
+    art::ObjPtr<art::mirror::Object> ccl = peer != nullptr
+        ? context_class_loader_->GetObject(peer)
+        : nullptr;
+    info_ptr->context_class_loader = ccl == nullptr
+                                         ? nullptr
+                                         : soa.AddLocalReference<jobject>(ccl);
+  }
+
+  name_uptr.release();
+
+  return ERR(NONE);
+}
+
+struct InternalThreadState {
+  art::Thread* native_thread;
+  art::ThreadState art_state;
+  int thread_user_code_suspend_count;
+};
+
+// Return the thread's (or current thread, if null) thread state.
+static InternalThreadState GetNativeThreadState(jthread thread,
+                                                const art::ScopedObjectAccessAlreadyRunnable& soa)
+    REQUIRES_SHARED(art::Locks::mutator_lock_)
+    REQUIRES(art::Locks::thread_list_lock_, art::Locks::user_code_suspension_lock_) {
+  art::Thread* self = nullptr;
+  if (thread == nullptr) {
+    self = art::Thread::Current();
+  } else {
+    self = art::Thread::FromManagedThread(soa, thread);
+  }
+  InternalThreadState thread_state = {};
+  art::MutexLock tscl_mu(soa.Self(), *art::Locks::thread_suspend_count_lock_);
+  thread_state.native_thread = self;
+  if (self == nullptr || self->IsStillStarting()) {
+    thread_state.art_state = art::ThreadState::kStarting;
+    thread_state.thread_user_code_suspend_count = 0;
+  } else {
+    thread_state.art_state = self->GetState();
+    thread_state.thread_user_code_suspend_count = self->GetUserCodeSuspendCount();
+  }
+  return thread_state;
+}
+
+static jint GetJvmtiThreadStateFromInternal(const InternalThreadState& state) {
+  art::ThreadState internal_thread_state = state.art_state;
+  jint jvmti_state = JVMTI_THREAD_STATE_ALIVE;
+
+  if (state.thread_user_code_suspend_count != 0) {
+    jvmti_state |= JVMTI_THREAD_STATE_SUSPENDED;
+    // Note: We do not have data about the previous state. Otherwise we should load the previous
+    //       state here.
+  }
+
+  if (state.native_thread->IsInterrupted()) {
+    jvmti_state |= JVMTI_THREAD_STATE_INTERRUPTED;
+  }
+
+  if (internal_thread_state == art::ThreadState::kNative) {
+    jvmti_state |= JVMTI_THREAD_STATE_IN_NATIVE;
+  }
+
+  if (internal_thread_state == art::ThreadState::kRunnable ||
+      internal_thread_state == art::ThreadState::kWaitingWeakGcRootRead ||
+      internal_thread_state == art::ThreadState::kSuspended) {
+    jvmti_state |= JVMTI_THREAD_STATE_RUNNABLE;
+  } else if (internal_thread_state == art::ThreadState::kBlocked) {
+    jvmti_state |= JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
+  } else {
+    // Should be in waiting state.
+    jvmti_state |= JVMTI_THREAD_STATE_WAITING;
+
+    if (internal_thread_state == art::ThreadState::kTimedWaiting ||
+        internal_thread_state == art::ThreadState::kSleeping) {
+      jvmti_state |= JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
+    } else {
+      jvmti_state |= JVMTI_THREAD_STATE_WAITING_INDEFINITELY;
+    }
+
+    if (internal_thread_state == art::ThreadState::kSleeping) {
+      jvmti_state |= JVMTI_THREAD_STATE_SLEEPING;
+    }
+
+    if (internal_thread_state == art::ThreadState::kTimedWaiting ||
+        internal_thread_state == art::ThreadState::kWaiting) {
+      jvmti_state |= JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
+    }
+
+    // TODO: PARKED. We'll have to inspect the stack.
+  }
+
+  return jvmti_state;
+}
+
+static jint GetJavaStateFromInternal(const InternalThreadState& state) {
+  switch (state.art_state) {
+    case art::ThreadState::kTerminated:
+      return JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
+
+    case art::ThreadState::kRunnable:
+    case art::ThreadState::kNative:
+    case art::ThreadState::kWaitingWeakGcRootRead:
+    case art::ThreadState::kSuspended:
+      return JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE;
+
+    case art::ThreadState::kTimedWaiting:
+    case art::ThreadState::kSleeping:
+      return JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING;
+
+    case art::ThreadState::kBlocked:
+      return JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED;
+
+    case art::ThreadState::kStarting:
+      return JVMTI_JAVA_LANG_THREAD_STATE_NEW;
+
+    case art::ThreadState::kWaiting:
+    case art::ThreadState::kWaitingForGcToComplete:
+    case art::ThreadState::kWaitingPerformingGc:
+    case art::ThreadState::kWaitingForCheckPointsToRun:
+    case art::ThreadState::kWaitingForDebuggerSend:
+    case art::ThreadState::kWaitingForDebuggerToAttach:
+    case art::ThreadState::kWaitingInMainDebuggerLoop:
+    case art::ThreadState::kWaitingForDebuggerSuspension:
+    case art::ThreadState::kWaitingForDeoptimization:
+    case art::ThreadState::kWaitingForGetObjectsAllocated:
+    case art::ThreadState::kWaitingForJniOnLoad:
+    case art::ThreadState::kWaitingForSignalCatcherOutput:
+    case art::ThreadState::kWaitingInMainSignalCatcherLoop:
+    case art::ThreadState::kWaitingForMethodTracingStart:
+    case art::ThreadState::kWaitingForVisitObjects:
+    case art::ThreadState::kWaitingForGcThreadFlip:
+      return JVMTI_JAVA_LANG_THREAD_STATE_WAITING;
+  }
+  LOG(FATAL) << "Unreachable";
+  UNREACHABLE();
+}
+
+// Suspends the current thread if it has any suspend requests on it.
+static void SuspendCheck(art::Thread* self)
+    REQUIRES(!art::Locks::mutator_lock_, !art::Locks::user_code_suspension_lock_) {
+  art::ScopedObjectAccess soa(self);
+  // Really this is only needed if we are in FastJNI and actually have the mutator_lock_ already.
+  self->FullSuspendCheck();
+}
+
+jvmtiError ThreadUtil::GetThreadState(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                      jthread thread,
+                                      jint* thread_state_ptr) {
+  if (thread_state_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::Thread* self = art::Thread::Current();
+  InternalThreadState state = {};
+  // Loop since we need to bail out and try again if we would end up getting suspended while holding
+  // the user_code_suspension_lock_ due to a SuspendReason::kForUserCode. In this situation we
+  // release the lock, wait to get resumed and try again.
+  do {
+    SuspendCheck(self);
+    art::MutexLock ucsl_mu(self, *art::Locks::user_code_suspension_lock_);
+    {
+      art::MutexLock tscl_mu(self, *art::Locks::thread_suspend_count_lock_);
+      if (self->GetUserCodeSuspendCount() != 0) {
+        // Make sure we won't be suspended in the middle of holding the thread_suspend_count_lock_
+        // by a user-code suspension. We retry and do another SuspendCheck to clear this.
+        continue;
+      }
+    }
+    art::ScopedObjectAccess soa(self);
+    art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
+    state = GetNativeThreadState(thread, soa);
+    if (state.art_state == art::ThreadState::kStarting) {
+      break;
+    }
+    DCHECK(state.native_thread != nullptr);
+
+    // Translate internal thread state to JVMTI and Java state.
+    jint jvmti_state = GetJvmtiThreadStateFromInternal(state);
+
+    // Java state is derived from nativeGetState.
+    // TODO: Our implementation assigns "runnable" to suspended. As such, we will have slightly
+    //       different mask if a thread got suspended due to user-code. However, this is for
+    //       consistency with the Java view.
+    jint java_state = GetJavaStateFromInternal(state);
+
+    *thread_state_ptr = jvmti_state | java_state;
+
+    return ERR(NONE);
+  } while (true);
+
+  DCHECK_EQ(state.art_state, art::ThreadState::kStarting);
+
+  if (thread == nullptr) {
+    // No native thread, and no Java thread? We must be starting up. Report as wrong phase.
+    return ERR(WRONG_PHASE);
+  }
+
+  art::ScopedObjectAccess soa(self);
+
+  // Need to read the Java "started" field to know whether this is starting or terminated.
+  art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread);
+  art::ObjPtr<art::mirror::Class> klass = peer->GetClass();
+  art::ArtField* started_field = klass->FindDeclaredInstanceField("started", "Z");
+  CHECK(started_field != nullptr);
+  bool started = started_field->GetBoolean(peer) != 0;
+  constexpr jint kStartedState = JVMTI_JAVA_LANG_THREAD_STATE_NEW;
+  constexpr jint kTerminatedState = JVMTI_THREAD_STATE_TERMINATED |
+                                    JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
+  *thread_state_ptr = started ? kTerminatedState : kStartedState;
+  return ERR(NONE);
+}
+
+jvmtiError ThreadUtil::GetAllThreads(jvmtiEnv* env,
+                                     jint* threads_count_ptr,
+                                     jthread** threads_ptr) {
+  if (threads_count_ptr == nullptr || threads_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::Thread* current = art::Thread::Current();
+
+  art::ScopedObjectAccess soa(current);
+
+  art::MutexLock mu(current, *art::Locks::thread_list_lock_);
+  std::list<art::Thread*> thread_list = art::Runtime::Current()->GetThreadList()->GetList();
+
+  std::vector<art::ObjPtr<art::mirror::Object>> peers;
+
+  for (art::Thread* thread : thread_list) {
+    // Skip threads that are still starting.
+    if (thread->IsStillStarting()) {
+      continue;
+    }
+
+    art::ObjPtr<art::mirror::Object> peer = thread->GetPeerFromOtherThread();
+    if (peer != nullptr) {
+      peers.push_back(peer);
+    }
+  }
+
+  if (peers.empty()) {
+    *threads_count_ptr = 0;
+    *threads_ptr = nullptr;
+  } else {
+    unsigned char* data;
+    jvmtiError data_result = env->Allocate(peers.size() * sizeof(jthread), &data);
+    if (data_result != ERR(NONE)) {
+      return data_result;
+    }
+    jthread* threads = reinterpret_cast<jthread*>(data);
+    for (size_t i = 0; i != peers.size(); ++i) {
+      threads[i] = soa.AddLocalReference<jthread>(peers[i]);
+    }
+
+    *threads_count_ptr = static_cast<jint>(peers.size());
+    *threads_ptr = threads;
+  }
+  return ERR(NONE);
+}
+
+// The struct that we store in the art::Thread::custom_tls_ that maps the jvmtiEnvs to the data
+// stored with that thread. This is needed since different jvmtiEnvs are not supposed to share TLS
+// data but we only have a single slot in Thread objects to store data.
+struct JvmtiGlobalTLSData {
+  std::unordered_map<jvmtiEnv*, const void*> data GUARDED_BY(art::Locks::thread_list_lock_);
+};
+
+static void RemoveTLSData(art::Thread* target, void* ctx) REQUIRES(art::Locks::thread_list_lock_) {
+  jvmtiEnv* env = reinterpret_cast<jvmtiEnv*>(ctx);
+  art::Locks::thread_list_lock_->AssertHeld(art::Thread::Current());
+  JvmtiGlobalTLSData* global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS());
+  if (global_tls != nullptr) {
+    global_tls->data.erase(env);
+  }
+}
+
+void ThreadUtil::RemoveEnvironment(jvmtiEnv* env) {
+  art::Thread* self = art::Thread::Current();
+  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+  art::ThreadList* list = art::Runtime::Current()->GetThreadList();
+  list->ForEach(RemoveTLSData, env);
+}
+
+jvmtiError ThreadUtil::SetThreadLocalStorage(jvmtiEnv* env, jthread thread, const void* data) {
+  art::Thread* self = art::Thread::Current();
+  art::ScopedObjectAccess soa(self);
+  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+  art::Thread* target = GetNativeThread(thread, soa);
+  if (target == nullptr && thread == nullptr) {
+    return ERR(INVALID_THREAD);
+  }
+  if (target == nullptr) {
+    return ERR(THREAD_NOT_ALIVE);
+  }
+
+  JvmtiGlobalTLSData* global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS());
+  if (global_tls == nullptr) {
+    target->SetCustomTLS(new JvmtiGlobalTLSData);
+    global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS());
+  }
+
+  global_tls->data[env] = data;
+
+  return ERR(NONE);
+}
+
+jvmtiError ThreadUtil::GetThreadLocalStorage(jvmtiEnv* env,
+                                             jthread thread,
+                                             void** data_ptr) {
+  if (data_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::Thread* self = art::Thread::Current();
+  art::ScopedObjectAccess soa(self);
+  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+  art::Thread* target = GetNativeThread(thread, soa);
+  if (target == nullptr && thread == nullptr) {
+    return ERR(INVALID_THREAD);
+  }
+  if (target == nullptr) {
+    return ERR(THREAD_NOT_ALIVE);
+  }
+
+  JvmtiGlobalTLSData* global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS());
+  if (global_tls == nullptr) {
+    *data_ptr = nullptr;
+    return OK;
+  }
+  auto it = global_tls->data.find(env);
+  if (it != global_tls->data.end()) {
+    *data_ptr = const_cast<void*>(it->second);
+  } else {
+    *data_ptr = nullptr;
+  }
+
+  return ERR(NONE);
+}
+
+struct AgentData {
+  const void* arg;
+  jvmtiStartFunction proc;
+  jthread thread;
+  JavaVM* java_vm;
+  jvmtiEnv* jvmti_env;
+  jint priority;
+};
+
+static void* AgentCallback(void* arg) {
+  std::unique_ptr<AgentData> data(reinterpret_cast<AgentData*>(arg));
+  CHECK(data->thread != nullptr);
+
+  // We already have a peer. So call our special Attach function.
+  art::Thread* self = art::Thread::Attach("JVMTI Agent thread", true, data->thread);
+  CHECK(self != nullptr);
+  // The name in Attach() is only for logging. Set the thread name. This is important so
+  // that the thread is no longer seen as starting up.
+  {
+    art::ScopedObjectAccess soa(self);
+    self->SetThreadName("JVMTI Agent thread");
+  }
+
+  // Release the peer.
+  JNIEnv* env = self->GetJniEnv();
+  env->DeleteGlobalRef(data->thread);
+  data->thread = nullptr;
+
+  // Run the agent code.
+  data->proc(data->jvmti_env, env, const_cast<void*>(data->arg));
+
+  // Detach the thread.
+  int detach_result = data->java_vm->DetachCurrentThread();
+  CHECK_EQ(detach_result, 0);
+
+  return nullptr;
+}
+
+jvmtiError ThreadUtil::RunAgentThread(jvmtiEnv* jvmti_env,
+                                      jthread thread,
+                                      jvmtiStartFunction proc,
+                                      const void* arg,
+                                      jint priority) {
+  if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) {
+    return ERR(INVALID_PRIORITY);
+  }
+  JNIEnv* env = art::Thread::Current()->GetJniEnv();
+  if (thread == nullptr || !env->IsInstanceOf(thread, art::WellKnownClasses::java_lang_Thread)) {
+    return ERR(INVALID_THREAD);
+  }
+  if (proc == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  std::unique_ptr<AgentData> data(new AgentData);
+  data->arg = arg;
+  data->proc = proc;
+  // We need a global ref for Java objects, as local refs will be invalid.
+  data->thread = env->NewGlobalRef(thread);
+  data->java_vm = art::Runtime::Current()->GetJavaVM();
+  data->jvmti_env = jvmti_env;
+  data->priority = priority;
+
+  pthread_t pthread;
+  int pthread_create_result = pthread_create(&pthread,
+                                             nullptr,
+                                             &AgentCallback,
+                                             reinterpret_cast<void*>(data.get()));
+  if (pthread_create_result != 0) {
+    return ERR(INTERNAL);
+  }
+  data.release();
+
+  return ERR(NONE);
+}
+
+jvmtiError ThreadUtil::SuspendOther(art::Thread* self,
+                                    jthread target_jthread) {
+  // Loop since we need to bail out and try again if we would end up getting suspended while holding
+  // the user_code_suspension_lock_ due to a SuspendReason::kForUserCode. In this situation we
+  // release the lock, wait to get resumed and try again.
+  do {
+    // Suspend ourself if we have any outstanding suspends. This is so we won't suspend due to
+    // another SuspendThread in the middle of suspending something else potentially causing a
+    // deadlock. We need to do this in the loop because if we ended up back here then we had
+    // outstanding SuspendReason::kForUserCode suspensions and we should wait for them to be cleared
+    // before continuing.
+    SuspendCheck(self);
+    art::MutexLock mu(self, *art::Locks::user_code_suspension_lock_);
+    {
+      art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
+      // Make sure we won't be suspended in the middle of holding the thread_suspend_count_lock_ by
+      // a user-code suspension. We retry and do another SuspendCheck to clear this.
+      if (self->GetUserCodeSuspendCount() != 0) {
+        continue;
+      }
+      // We are not going to be suspended by user code from now on.
+    }
+    {
+      art::ScopedObjectAccess soa(self);
+      art::MutexLock thread_list_mu(self, *art::Locks::thread_list_lock_);
+      art::Thread* target = GetNativeThread(target_jthread, soa);
+      art::ThreadState state = target->GetState();
+      if (state == art::ThreadState::kTerminated || state == art::ThreadState::kStarting) {
+        return ERR(THREAD_NOT_ALIVE);
+      } else {
+        art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
+        if (target->GetUserCodeSuspendCount() != 0) {
+          return ERR(THREAD_SUSPENDED);
+        }
+      }
+    }
+    bool timeout = true;
+    art::Thread* ret_target = art::Runtime::Current()->GetThreadList()->SuspendThreadByPeer(
+        target_jthread,
+        /* request_suspension */ true,
+        art::SuspendReason::kForUserCode,
+        &timeout);
+    if (ret_target == nullptr && !timeout) {
+      // TODO It would be good to get more information about why exactly the thread failed to
+      // suspend.
+      return ERR(INTERNAL);
+    } else if (!timeout) {
+      // we didn't time out and got a result.
+      return OK;
+    }
+    // We timed out. Just go around and try again.
+  } while (true);
+  UNREACHABLE();
+}
+
+jvmtiError ThreadUtil::SuspendSelf(art::Thread* self) {
+  CHECK(self == art::Thread::Current());
+  {
+    art::MutexLock mu(self, *art::Locks::user_code_suspension_lock_);
+    art::MutexLock thread_list_mu(self, *art::Locks::thread_suspend_count_lock_);
+    if (self->GetUserCodeSuspendCount() != 0) {
+      // This can only happen if we race with another thread to suspend 'self' and we lose.
+      return ERR(THREAD_SUSPENDED);
+    }
+    // We shouldn't be able to fail this.
+    if (!self->ModifySuspendCount(self, +1, nullptr, art::SuspendReason::kForUserCode)) {
+      // TODO More specific error would be nice.
+      return ERR(INTERNAL);
+    }
+  }
+  // Once we have requested the suspend we actually go to sleep. We need to do this after releasing
+  // the suspend_lock to make sure we can be woken up. This call gains the mutator lock causing us
+  // to go to sleep until we are resumed.
+  SuspendCheck(self);
+  return OK;
+}
+
+jvmtiError ThreadUtil::SuspendThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread thread) {
+  art::Thread* self = art::Thread::Current();
+  bool target_is_self = false;
+  {
+    art::ScopedObjectAccess soa(self);
+    art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+    art::Thread* target = GetNativeThread(thread, soa);
+    if (target == nullptr) {
+      return ERR(INVALID_THREAD);
+    } else if (target == self) {
+      target_is_self = true;
+    }
+  }
+  if (target_is_self) {
+    return SuspendSelf(self);
+  } else {
+    return SuspendOther(self, thread);
+  }
+}
+
+jvmtiError ThreadUtil::ResumeThread(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                    jthread thread) {
+  if (thread == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  art::Thread* self = art::Thread::Current();
+  art::Thread* target;
+  // Retry until we know we won't get suspended by user code while resuming something.
+  do {
+    SuspendCheck(self);
+    art::MutexLock ucsl_mu(self, *art::Locks::user_code_suspension_lock_);
+    {
+      art::MutexLock tscl_mu(self, *art::Locks::thread_suspend_count_lock_);
+      // Make sure we won't be suspended in the middle of holding the thread_suspend_count_lock_ by
+      // a user-code suspension. We retry and do another SuspendCheck to clear this.
+      if (self->GetUserCodeSuspendCount() != 0) {
+        continue;
+      }
+    }
+    // From now on we know we cannot get suspended by user-code.
+    {
+      // NB This does a SuspendCheck (during thread state change) so we need to make sure we don't
+      // have the 'suspend_lock' locked here.
+      art::ScopedObjectAccess soa(self);
+      art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
+      target = GetNativeThread(thread, soa);
+      if (target == nullptr) {
+        return ERR(INVALID_THREAD);
+      } else if (target == self) {
+        // We would have paused until we aren't suspended anymore due to the ScopedObjectAccess so
+        // we can just return THREAD_NOT_SUSPENDED. Unfortunately we cannot do any real DCHECKs
+        // about current state since it's all concurrent.
+        return ERR(THREAD_NOT_SUSPENDED);
+      } else if (target->GetState() == art::ThreadState::kTerminated) {
+        return ERR(THREAD_NOT_ALIVE);
+      }
+      // The JVMTI spec requires us to return THREAD_NOT_SUSPENDED if it is alive but we really
+      // cannot tell why resume failed.
+      {
+        art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
+        if (target->GetUserCodeSuspendCount() == 0) {
+          return ERR(THREAD_NOT_SUSPENDED);
+        }
+      }
+    }
+    // It is okay that we don't have a thread_list_lock here since we know that the thread cannot
+    // die since it is currently held suspended by a SuspendReason::kForUserCode suspend.
+    DCHECK(target != self);
+    if (!art::Runtime::Current()->GetThreadList()->Resume(target,
+                                                          art::SuspendReason::kForUserCode)) {
+      // TODO Give a better error.
+      // This is most likely THREAD_NOT_SUSPENDED but we cannot really be sure.
+      return ERR(INTERNAL);
+    } else {
+      return OK;
+    }
+  } while (true);
+}
+
+// Suspends all the threads in the list at the same time. Getting this behavior is a little tricky
+// since we can have threads in the list multiple times. This generally doesn't matter unless the
+// current thread is present multiple times. In that case we need to suspend only once and either
+// return the same error code in all the other slots if it failed or return ERR(THREAD_SUSPENDED) if
+// it didn't. We also want to handle the current thread last to make the behavior of the code
+// simpler to understand.
+jvmtiError ThreadUtil::SuspendThreadList(jvmtiEnv* env,
+                                         jint request_count,
+                                         const jthread* threads,
+                                         jvmtiError* results) {
+  if (request_count == 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  } else if (results == nullptr || threads == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  // This is the list of the indexes in 'threads' and 'results' that correspond to the currently
+  // running thread. These indexes we need to handle specially since we need to only actually
+  // suspend a single time.
+  std::vector<jint> current_thread_indexes;
+  art::Thread* self = art::Thread::Current();
+  for (jint i = 0; i < request_count; i++) {
+    {
+      art::ScopedObjectAccess soa(self);
+      art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+      if (threads[i] == nullptr || GetNativeThread(threads[i], soa) == self) {
+        current_thread_indexes.push_back(i);
+        continue;
+      }
+    }
+    results[i] = env->SuspendThread(threads[i]);
+  }
+  if (!current_thread_indexes.empty()) {
+    jint first_current_thread_index = current_thread_indexes[0];
+    // Suspend self.
+    jvmtiError res = env->SuspendThread(threads[first_current_thread_index]);
+    results[first_current_thread_index] = res;
+    // Fill in the rest of the error values as appropriate.
+    jvmtiError other_results = (res != OK) ? res : ERR(THREAD_SUSPENDED);
+    for (auto it = ++current_thread_indexes.begin(); it != current_thread_indexes.end(); ++it) {
+      results[*it] = other_results;
+    }
+  }
+  return OK;
+}
+
+jvmtiError ThreadUtil::ResumeThreadList(jvmtiEnv* env,
+                                        jint request_count,
+                                        const jthread* threads,
+                                        jvmtiError* results) {
+  if (request_count == 0) {
+    return ERR(ILLEGAL_ARGUMENT);
+  } else if (results == nullptr || threads == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  for (jint i = 0; i < request_count; i++) {
+    results[i] = env->ResumeThread(threads[i]);
+  }
+  return OK;
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_thread.h b/openjdkjvmti/ti_thread.h
new file mode 100644
index 0000000..03c49d7
--- /dev/null
+++ b/openjdkjvmti/ti_thread.h
@@ -0,0 +1,116 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_THREAD_H_
+#define ART_OPENJDKJVMTI_TI_THREAD_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+#include "base/macros.h"
+#include "base/mutex.h"
+
+namespace art {
+class ArtField;
+class ScopedObjectAccessAlreadyRunnable;
+class Thread;
+}  // namespace art
+
+namespace openjdkjvmti {
+
+class EventHandler;
+
+class ThreadUtil {
+ public:
+  static void Register(EventHandler* event_handler);
+  static void Unregister();
+
+  // To be called when it is safe to cache data.
+  static void CacheData();
+
+  // Handle a jvmtiEnv going away.
+  static void RemoveEnvironment(jvmtiEnv* env);
+
+  static jvmtiError GetAllThreads(jvmtiEnv* env, jint* threads_count_ptr, jthread** threads_ptr);
+
+  static jvmtiError GetCurrentThread(jvmtiEnv* env, jthread* thread_ptr);
+
+  static jvmtiError GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr);
+
+  static jvmtiError GetThreadState(jvmtiEnv* env, jthread thread, jint* thread_state_ptr);
+
+  static jvmtiError SetThreadLocalStorage(jvmtiEnv* env, jthread thread, const void* data);
+  static jvmtiError GetThreadLocalStorage(jvmtiEnv* env, jthread thread, void** data_ptr);
+
+  static jvmtiError RunAgentThread(jvmtiEnv* env,
+                                   jthread thread,
+                                   jvmtiStartFunction proc,
+                                   const void* arg,
+                                   jint priority);
+
+  static jvmtiError SuspendThread(jvmtiEnv* env, jthread thread);
+  static jvmtiError ResumeThread(jvmtiEnv* env, jthread thread);
+
+  static jvmtiError SuspendThreadList(jvmtiEnv* env,
+                                      jint request_count,
+                                      const jthread* threads,
+                                      jvmtiError* results);
+  static jvmtiError ResumeThreadList(jvmtiEnv* env,
+                                     jint request_count,
+                                     const jthread* threads,
+                                     jvmtiError* results);
+
+  static art::Thread* GetNativeThread(jthread thread,
+                                      const art::ScopedObjectAccessAlreadyRunnable& soa)
+      REQUIRES_SHARED(art::Locks::mutator_lock_)
+      REQUIRES(art::Locks::thread_list_lock_);
+
+ private:
+  // We need to make sure only one thread tries to suspend threads at a time so we can get the
+  // 'suspend-only-once' behavior the spec requires. Internally, ART considers suspension to be a
+  // counted state, allowing a single thread to be suspended multiple times by different users. This
+  // makes mapping into the JVMTI idea of thread suspension difficult. We have decided to split the
+  // difference and ensure that JVMTI tries to treat suspension as the boolean flag as much as
+  // possible with the suspend/resume methods but only do best effort. On the other hand
+  // GetThreadState will be totally accurate as much as possible. This means that calling
+  // ResumeThread on a thread that has state JVMTI_THREAD_STATE_SUSPENDED will not necessarily
+  // cause the thread to wake up if the thread is suspended for the debugger or gc or something.
+  static jvmtiError SuspendSelf(art::Thread* self)
+      REQUIRES(!art::Locks::mutator_lock_, !art::Locks::user_code_suspension_lock_);
+  static jvmtiError SuspendOther(art::Thread* self, jthread target_jthread)
+      REQUIRES(!art::Locks::mutator_lock_, !art::Locks::user_code_suspension_lock_);
+
+  static art::ArtField* context_class_loader_;
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_THREAD_H_
diff --git a/openjdkjvmti/ti_threadgroup.cc b/openjdkjvmti/ti_threadgroup.cc
new file mode 100644
index 0000000..c0597ad
--- /dev/null
+++ b/openjdkjvmti/ti_threadgroup.cc
@@ -0,0 +1,279 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_threadgroup.h"
+
+#include "art_field-inl.h"
+#include "art_jvmti.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/mutex.h"
+#include "handle_scope-inl.h"
+#include "jni_internal.h"
+#include "mirror/class.h"
+#include "mirror/object-inl.h"
+#include "mirror/string.h"
+#include "obj_ptr.h"
+#include "object_lock.h"
+#include "runtime.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+#include "thread_list.h"
+#include "well_known_classes.h"
+
+namespace openjdkjvmti {
+
+
+jvmtiError ThreadGroupUtil::GetTopThreadGroups(jvmtiEnv* env,
+                                               jint* group_count_ptr,
+                                               jthreadGroup** groups_ptr) {
+  // We only have a single top group. So we can take the current thread and move upwards.
+  if (group_count_ptr == nullptr || groups_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::Runtime* runtime = art::Runtime::Current();
+  if (runtime == nullptr) {
+    // Must be starting the runtime, or dying.
+    return ERR(WRONG_PHASE);
+  }
+
+  jobject sys_thread_group = runtime->GetSystemThreadGroup();
+  if (sys_thread_group == nullptr) {
+    // Seems we're still starting up.
+    return ERR(WRONG_PHASE);
+  }
+
+  unsigned char* data;
+  jvmtiError result = env->Allocate(sizeof(jthreadGroup), &data);
+  if (result != ERR(NONE)) {
+    return result;
+  }
+
+  jthreadGroup* groups = reinterpret_cast<jthreadGroup*>(data);
+  *groups =
+      reinterpret_cast<JNIEnv*>(art::Thread::Current()->GetJniEnv())->NewLocalRef(sys_thread_group);
+  *groups_ptr = groups;
+  *group_count_ptr = 1;
+
+  return ERR(NONE);
+}
+
+jvmtiError ThreadGroupUtil::GetThreadGroupInfo(jvmtiEnv* env,
+                                               jthreadGroup group,
+                                               jvmtiThreadGroupInfo* info_ptr) {
+  if (group == nullptr) {
+    return ERR(INVALID_THREAD_GROUP);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  if (soa.Env()->IsInstanceOf(group, art::WellKnownClasses::java_lang_ThreadGroup) == JNI_FALSE) {
+    return ERR(INVALID_THREAD_GROUP);
+  }
+
+  art::ObjPtr<art::mirror::Object> obj = soa.Decode<art::mirror::Object>(group);
+
+  // Do the name first. It's the only thing that can fail.
+  {
+    art::ArtField* name_field =
+        art::jni::DecodeArtField(art::WellKnownClasses::java_lang_ThreadGroup_name);
+    CHECK(name_field != nullptr);
+    art::ObjPtr<art::mirror::String> name_obj =
+        art::ObjPtr<art::mirror::String>::DownCast(name_field->GetObject(obj));
+    std::string tmp_str;
+    const char* tmp_cstr;
+    if (name_obj == nullptr) {
+      tmp_cstr = "";
+    } else {
+      tmp_str = name_obj->ToModifiedUtf8();
+      tmp_cstr = tmp_str.c_str();
+    }
+    jvmtiError result;
+    JvmtiUniquePtr<char[]> copy = CopyString(env, tmp_cstr, &result);
+    if (copy == nullptr) {
+      return result;
+    }
+    info_ptr->name = copy.release();
+  }
+
+  // Parent.
+  {
+    art::ArtField* parent_field =
+        art::jni::DecodeArtField(art::WellKnownClasses::java_lang_ThreadGroup_parent);
+    CHECK(parent_field != nullptr);
+    art::ObjPtr<art::mirror::Object> parent_group = parent_field->GetObject(obj);
+    info_ptr->parent = parent_group == nullptr
+                           ? nullptr
+                           : soa.AddLocalReference<jthreadGroup>(parent_group);
+  }
+
+  // Max priority.
+  {
+    art::ArtField* prio_field = obj->GetClass()->FindDeclaredInstanceField("maxPriority", "I");
+    CHECK(prio_field != nullptr);
+    info_ptr->max_priority = static_cast<jint>(prio_field->GetInt(obj));
+  }
+
+  // Daemon.
+  {
+    art::ArtField* daemon_field = obj->GetClass()->FindDeclaredInstanceField("daemon", "Z");
+    CHECK(daemon_field != nullptr);
+    info_ptr->is_daemon = daemon_field->GetBoolean(obj) == 0 ? JNI_FALSE : JNI_TRUE;
+  }
+
+  return ERR(NONE);
+}
+
+
+static bool IsInDesiredThreadGroup(art::Handle<art::mirror::Object> desired_thread_group,
+                                   art::ObjPtr<art::mirror::Object> peer)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  CHECK(desired_thread_group != nullptr);
+
+  art::ArtField* thread_group_field =
+      art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group);
+  DCHECK(thread_group_field != nullptr);
+  art::ObjPtr<art::mirror::Object> group = thread_group_field->GetObject(peer);
+  return (group == desired_thread_group.Get());
+}
+
+static void GetThreads(art::Handle<art::mirror::Object> thread_group,
+                       std::vector<art::ObjPtr<art::mirror::Object>>* thread_peers)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) REQUIRES(!art::Locks::thread_list_lock_) {
+  CHECK(thread_group != nullptr);
+
+  art::MutexLock mu(art::Thread::Current(), *art::Locks::thread_list_lock_);
+  for (art::Thread* t : art::Runtime::Current()->GetThreadList()->GetList()) {
+    if (t->IsStillStarting()) {
+      continue;
+    }
+    art::ObjPtr<art::mirror::Object> peer = t->GetPeerFromOtherThread();
+    if (peer == nullptr) {
+      continue;
+    }
+    if (IsInDesiredThreadGroup(thread_group, peer)) {
+      thread_peers->push_back(peer);
+    }
+  }
+}
+
+static void GetChildThreadGroups(art::Handle<art::mirror::Object> thread_group,
+                                 std::vector<art::ObjPtr<art::mirror::Object>>* thread_groups)
+    REQUIRES_SHARED(art::Locks::mutator_lock_) {
+  CHECK(thread_group != nullptr);
+
+  // Get the ThreadGroup[] "groups" out of this thread group...
+  art::ArtField* groups_field =
+      art::jni::DecodeArtField(art::WellKnownClasses::java_lang_ThreadGroup_groups);
+  art::ObjPtr<art::mirror::Object> groups_array = groups_field->GetObject(thread_group.Get());
+
+  if (groups_array == nullptr) {
+    return;
+  }
+  CHECK(groups_array->IsObjectArray());
+
+  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> groups_array_as_array =
+      groups_array->AsObjectArray<art::mirror::Object>();
+
+  // Copy all non-null elements.
+  for (int32_t i = 0; i < groups_array_as_array->GetLength(); ++i) {
+    art::ObjPtr<art::mirror::Object> entry = groups_array_as_array->Get(i);
+    if (entry != nullptr) {
+      thread_groups->push_back(entry);
+    }
+  }
+}
+
+jvmtiError ThreadGroupUtil::GetThreadGroupChildren(jvmtiEnv* env,
+                                                   jthreadGroup group,
+                                                   jint* thread_count_ptr,
+                                                   jthread** threads_ptr,
+                                                   jint* group_count_ptr,
+                                                   jthreadGroup** groups_ptr) {
+  if (group == nullptr) {
+    return ERR(INVALID_THREAD_GROUP);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+
+  if (!soa.Env()->IsInstanceOf(group, art::WellKnownClasses::java_lang_ThreadGroup)) {
+    return ERR(INVALID_THREAD_GROUP);
+  }
+
+  art::StackHandleScope<1> hs(soa.Self());
+  art::Handle<art::mirror::Object> thread_group = hs.NewHandle(
+      soa.Decode<art::mirror::Object>(group));
+
+  art::ObjectLock<art::mirror::Object> thread_group_lock(soa.Self(), thread_group);
+
+  std::vector<art::ObjPtr<art::mirror::Object>> thread_peers;
+  GetThreads(thread_group, &thread_peers);
+
+  std::vector<art::ObjPtr<art::mirror::Object>> thread_groups;
+  GetChildThreadGroups(thread_group, &thread_groups);
+
+  JvmtiUniquePtr<jthread[]> peers_uptr;
+  if (!thread_peers.empty()) {
+    jvmtiError res;
+    peers_uptr = AllocJvmtiUniquePtr<jthread[]>(env, thread_peers.size(), &res);
+    if (peers_uptr == nullptr) {
+      return res;
+    }
+  }
+
+  JvmtiUniquePtr<jthreadGroup[]> group_uptr;
+  if (!thread_groups.empty()) {
+    jvmtiError res;
+    group_uptr = AllocJvmtiUniquePtr<jthreadGroup[]>(env, thread_groups.size(), &res);
+    if (group_uptr == nullptr) {
+      return res;
+    }
+  }
+
+  // Can't fail anymore from here on.
+
+  // Copy data into out buffers.
+  for (size_t i = 0; i != thread_peers.size(); ++i) {
+    peers_uptr[i] = soa.AddLocalReference<jthread>(thread_peers[i]);
+  }
+  for (size_t i = 0; i != thread_groups.size(); ++i) {
+    group_uptr[i] = soa.AddLocalReference<jthreadGroup>(thread_groups[i]);
+  }
+
+  *thread_count_ptr = static_cast<jint>(thread_peers.size());
+  *threads_ptr = peers_uptr.release();
+  *group_count_ptr = static_cast<jint>(thread_groups.size());
+  *groups_ptr = group_uptr.release();
+
+  return ERR(NONE);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_threadgroup.h b/openjdkjvmti/ti_threadgroup.h
new file mode 100644
index 0000000..4911566
--- /dev/null
+++ b/openjdkjvmti/ti_threadgroup.h
@@ -0,0 +1,60 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_THREADGROUP_H_
+#define ART_OPENJDKJVMTI_TI_THREADGROUP_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class ThreadGroupUtil {
+ public:
+  static jvmtiError GetTopThreadGroups(jvmtiEnv* env,
+                                       jint* group_count_ptr,
+                                       jthreadGroup** groups_ptr);
+
+  static jvmtiError GetThreadGroupInfo(jvmtiEnv* env,
+                                       jthreadGroup group,
+                                       jvmtiThreadGroupInfo* info_ptr);
+
+  static jvmtiError GetThreadGroupChildren(jvmtiEnv* env,
+                                           jthreadGroup group,
+                                           jint* thread_count_ptr,
+                                           jthread** threads_ptr,
+                                           jint* group_count_ptr,
+                                           jthreadGroup** groups_ptr);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_THREADGROUP_H_
diff --git a/openjdkjvmti/ti_timers.cc b/openjdkjvmti/ti_timers.cc
new file mode 100644
index 0000000..24fb041
--- /dev/null
+++ b/openjdkjvmti/ti_timers.cc
@@ -0,0 +1,93 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "ti_timers.h"
+
+#include <limits>
+
+#ifndef __APPLE__
+#include <time.h>
+#else
+#include <sys/time.h>
+#endif
+#include <unistd.h>
+
+#include "art_jvmti.h"
+#include "base/macros.h"
+
+namespace openjdkjvmti {
+
+jvmtiError TimerUtil::GetAvailableProcessors(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                             jint* processor_count_ptr) {
+  if (processor_count_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  *processor_count_ptr = static_cast<jint>(sysconf(_SC_NPROCESSORS_CONF));
+
+  return ERR(NONE);
+}
+
+jvmtiError TimerUtil::GetTimerInfo(jvmtiEnv* env ATTRIBUTE_UNUSED, jvmtiTimerInfo* info_ptr) {
+  if (info_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  info_ptr->max_value = static_cast<jlong>(std::numeric_limits<uint64_t>::max());
+  info_ptr->may_skip_forward = JNI_TRUE;
+  info_ptr->may_skip_backward = JNI_TRUE;
+  info_ptr->kind = jvmtiTimerKind::JVMTI_TIMER_ELAPSED;
+
+  return ERR(NONE);
+}
+
+jvmtiError TimerUtil::GetTime(jvmtiEnv* env ATTRIBUTE_UNUSED, jlong* nanos_ptr) {
+  if (nanos_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+#ifndef __APPLE__
+  // Use the same implementation as System.nanoTime.
+  struct timespec now;
+  clock_gettime(CLOCK_MONOTONIC, &now);
+  *nanos_ptr = now.tv_sec * 1000000000LL + now.tv_nsec;
+#else
+  // No CLOCK_MONOTONIC support on older Mac OS.
+  struct timeval t;
+  t.tv_sec = t.tv_usec = 0;
+  gettimeofday(&t, NULL);
+  *nanos_ptr = static_cast<jlong>(t.tv_sec)*1000000000LL + static_cast<jlong>(t.tv_usec)*1000LL;
+#endif
+
+  return ERR(NONE);
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_timers.h b/openjdkjvmti/ti_timers.h
new file mode 100644
index 0000000..892205a
--- /dev/null
+++ b/openjdkjvmti/ti_timers.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TI_TIMERS_H_
+#define ART_OPENJDKJVMTI_TI_TIMERS_H_
+
+#include "jni.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+class TimerUtil {
+ public:
+  static jvmtiError GetAvailableProcessors(jvmtiEnv* env, jint* processor_count_ptr);
+
+  static jvmtiError GetTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr);
+
+  static jvmtiError GetTime(jvmtiEnv* env, jlong* nanos_ptr);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TI_TIMERS_H_
diff --git a/openjdkjvmti/transform.cc b/openjdkjvmti/transform.cc
new file mode 100644
index 0000000..1d7f137
--- /dev/null
+++ b/openjdkjvmti/transform.cc
@@ -0,0 +1,152 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <unordered_map>
+#include <unordered_set>
+
+#include "transform.h"
+
+#include "art_method.h"
+#include "base/array_ref.h"
+#include "class_linker.h"
+#include "dex_file.h"
+#include "dex_file_types.h"
+#include "events-inl.h"
+#include "gc_root-inl.h"
+#include "globals.h"
+#include "jni_env_ext-inl.h"
+#include "jvalue.h"
+#include "jvmti.h"
+#include "linear_alloc.h"
+#include "mem_map.h"
+#include "mirror/array.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_ext.h"
+#include "mirror/class_loader-inl.h"
+#include "mirror/string-inl.h"
+#include "oat_file.h"
+#include "scoped_thread_state_change-inl.h"
+#include "stack.h"
+#include "thread_list.h"
+#include "ti_redefine.h"
+#include "transform.h"
+#include "utf.h"
+#include "utils/dex_cache_arrays_layout-inl.h"
+
+namespace openjdkjvmti {
+
+jvmtiError Transformer::RetransformClassesDirect(
+      ArtJvmTiEnv* env,
+      EventHandler* event_handler,
+      art::Thread* self,
+      /*in-out*/std::vector<ArtClassDefinition>* definitions) {
+  for (ArtClassDefinition& def : *definitions) {
+    jint new_len = -1;
+    unsigned char* new_data = nullptr;
+    art::ArrayRef<const unsigned char> dex_data = def.GetDexData();
+    event_handler->DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookRetransformable>(
+        self,
+        GetJniEnv(env),
+        def.GetClass(),
+        def.GetLoader(),
+        def.GetName().c_str(),
+        def.GetProtectionDomain(),
+        static_cast<jint>(dex_data.size()),
+        dex_data.data(),
+        /*out*/&new_len,
+        /*out*/&new_data);
+    def.SetNewDexData(env, new_len, new_data);
+  }
+  return OK;
+}
+
+jvmtiError Transformer::RetransformClasses(ArtJvmTiEnv* env,
+                                           EventHandler* event_handler,
+                                           art::Runtime* runtime,
+                                           art::Thread* self,
+                                           jint class_count,
+                                           const jclass* classes,
+                                           /*out*/std::string* error_msg) {
+  if (env == nullptr) {
+    *error_msg = "env was null!";
+    return ERR(INVALID_ENVIRONMENT);
+  } else if (class_count < 0) {
+    *error_msg = "class_count was less then 0";
+    return ERR(ILLEGAL_ARGUMENT);
+  } else if (class_count == 0) {
+    // We don't actually need to do anything. Just return OK.
+    return OK;
+  } else if (classes == nullptr) {
+    *error_msg = "null classes!";
+    return ERR(NULL_POINTER);
+  }
+  // A holder that will Deallocate all the class bytes buffers on destruction.
+  std::vector<ArtClassDefinition> definitions;
+  jvmtiError res = OK;
+  for (jint i = 0; i < class_count; i++) {
+    jboolean is_modifiable = JNI_FALSE;
+    res = env->IsModifiableClass(classes[i], &is_modifiable);
+    if (res != OK) {
+      return res;
+    } else if (!is_modifiable) {
+      return ERR(UNMODIFIABLE_CLASS);
+    }
+    ArtClassDefinition def;
+    res = def.Init(env, classes[i]);
+    if (res != OK) {
+      return res;
+    }
+    definitions.push_back(std::move(def));
+  }
+  res = RetransformClassesDirect(env, event_handler, self, &definitions);
+  if (res != OK) {
+    return res;
+  }
+  return Redefiner::RedefineClassesDirect(env, runtime, self, definitions, error_msg);
+}
+
+// TODO Move this somewhere else, ti_class?
+jvmtiError GetClassLocation(ArtJvmTiEnv* env, jclass klass, /*out*/std::string* location) {
+  JNIEnv* jni_env = nullptr;
+  jint ret = env->art_vm->GetEnv(reinterpret_cast<void**>(&jni_env), JNI_VERSION_1_1);
+  if (ret != JNI_OK) {
+    // TODO Different error might be better?
+    return ERR(INTERNAL);
+  }
+  art::ScopedObjectAccess soa(jni_env);
+  art::StackHandleScope<1> hs(art::Thread::Current());
+  art::Handle<art::mirror::Class> hs_klass(hs.NewHandle(soa.Decode<art::mirror::Class>(klass)));
+  const art::DexFile& dex = hs_klass->GetDexFile();
+  *location = dex.GetLocation();
+  return OK;
+}
+
+}  // namespace openjdkjvmti
diff --git a/openjdkjvmti/transform.h b/openjdkjvmti/transform.h
new file mode 100644
index 0000000..6bbe60a
--- /dev/null
+++ b/openjdkjvmti/transform.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_OPENJDKJVMTI_TRANSFORM_H_
+#define ART_OPENJDKJVMTI_TRANSFORM_H_
+
+#include <string>
+
+#include <jni.h>
+#include "jvmti.h"
+
+#include "art_jvmti.h"
+#include "ti_class_definition.h"
+
+namespace openjdkjvmti {
+
+class EventHandler;
+
+jvmtiError GetClassLocation(ArtJvmTiEnv* env, jclass klass, /*out*/std::string* location);
+
+class Transformer {
+ public:
+  static jvmtiError RetransformClassesDirect(
+      ArtJvmTiEnv* env,
+      EventHandler* event_handler,
+      art::Thread* self,
+      /*in-out*/std::vector<ArtClassDefinition>* definitions);
+
+  static jvmtiError RetransformClasses(ArtJvmTiEnv* env,
+                                       EventHandler* event_handler,
+                                       art::Runtime* runtime,
+                                       art::Thread* self,
+                                       jint class_count,
+                                       const jclass* classes,
+                                       /*out*/std::string* error_msg);
+};
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_OPENJDKJVMTI_TRANSFORM_H_
+
