Revert "Implement RetransformClasses"

This reverts commit a6c5e97a4395352bc8684e6af9cecb62b80c316c.

Reason for revert: Accidently introduces double-free bug in RedefineClasses.

Change-Id: I021336c4fcf0cfb304915b0ffc5eaba5f91fdd5e
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index 32e3948..90467db 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -631,17 +631,7 @@
   }
 
   static jvmtiError RetransformClasses(jvmtiEnv* env, jint class_count, const jclass* classes) {
-    std::string error_msg;
-    jvmtiError res = Transformer::RetransformClasses(ArtJvmTiEnv::AsArtJvmTiEnv(env),
-                                                     art::Runtime::Current(),
-                                                     art::Thread::Current(),
-                                                     class_count,
-                                                     classes,
-                                                     &error_msg);
-    if (res != OK) {
-      LOG(WARNING) << "FAILURE TO RETRANFORM " << error_msg;
-    }
-    return res;
+    return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError RedefineClasses(jvmtiEnv* env,
@@ -1265,6 +1255,78 @@
     *format_ptr = jvmtiJlocationFormat::JVMTI_JLOCATION_JVMBCI;
     return ERR(NONE);
   }
+
+  // TODO Remove this once events are working.
+  static jvmtiError RetransformClassWithHook(jvmtiEnv* env,
+                                             jclass klass,
+                                             jvmtiEventClassFileLoadHook hook) {
+    std::vector<jclass> classes;
+    classes.push_back(klass);
+    return RetransformClassesWithHook(reinterpret_cast<ArtJvmTiEnv*>(env), classes, hook);
+  }
+
+  // TODO This will be called by the event handler for the art::ti Event Load Event
+  static jvmtiError RetransformClassesWithHook(ArtJvmTiEnv* env,
+                                               const std::vector<jclass>& classes,
+                                               jvmtiEventClassFileLoadHook hook) {
+    if (!IsValidEnv(env)) {
+      return ERR(INVALID_ENVIRONMENT);
+    }
+    jvmtiError res = OK;
+    std::string error;
+    for (jclass klass : classes) {
+      JNIEnv* jni_env = nullptr;
+      jobject loader = nullptr;
+      std::string name;
+      jobject protection_domain = nullptr;
+      jint data_len = 0;
+      unsigned char* dex_data = nullptr;
+      jvmtiError ret = OK;
+      std::string location;
+      if ((ret = GetTransformationData(env,
+                                       klass,
+                                       /*out*/&location,
+                                       /*out*/&jni_env,
+                                       /*out*/&loader,
+                                       /*out*/&name,
+                                       /*out*/&protection_domain,
+                                       /*out*/&data_len,
+                                       /*out*/&dex_data)) != OK) {
+        // TODO Do something more here? Maybe give log statements?
+        return ret;
+      }
+      jint new_data_len = 0;
+      unsigned char* new_dex_data = nullptr;
+      hook(env,
+           jni_env,
+           klass,
+           loader,
+           name.c_str(),
+           protection_domain,
+           data_len,
+           dex_data,
+           /*out*/&new_data_len,
+           /*out*/&new_dex_data);
+      // Check if anything actually changed.
+      if ((new_data_len != 0 || new_dex_data != nullptr) && new_dex_data != dex_data) {
+        jvmtiClassDefinition def = { klass, new_data_len, new_dex_data };
+        res = Redefiner::RedefineClasses(env,
+                                         art::Runtime::Current(),
+                                         art::Thread::Current(),
+                                         1,
+                                         &def,
+                                         &error);
+        env->Deallocate(new_dex_data);
+      }
+      // Deallocate the old dex data.
+      env->Deallocate(dex_data);
+      if (res != OK) {
+        LOG(ERROR) << "FAILURE TO REDEFINE " << error;
+        return res;
+      }
+    }
+    return OK;
+  }
 };
 
 static bool IsJvmtiVersion(jint version) {
@@ -1307,7 +1369,10 @@
 
 // The actual struct holding all of the entrypoints into the jvmti interface.
 const jvmtiInterface_1 gJvmtiInterface = {
-  nullptr,  // reserved1
+  // SPECIAL FUNCTION: RetransformClassWithHook Is normally reserved1
+  // TODO Remove once we have events working.
+  reinterpret_cast<void*>(JvmtiFunctions::RetransformClassWithHook),
+  // nullptr,  // reserved1
   JvmtiFunctions::SetEventNotificationMode,
   nullptr,  // reserved3
   JvmtiFunctions::GetAllThreads,
diff --git a/runtime/openjdkjvmti/art_jvmti.h b/runtime/openjdkjvmti/art_jvmti.h
index 1c84d4d..5eadc5a 100644
--- a/runtime/openjdkjvmti/art_jvmti.h
+++ b/runtime/openjdkjvmti/art_jvmti.h
@@ -47,7 +47,6 @@
 namespace openjdkjvmti {
 
 extern const jvmtiInterface_1 gJvmtiInterface;
-extern EventHandler gEventHandler;
 
 // A structure that is a jvmtiEnv with additional information for the runtime.
 struct ArtJvmTiEnv : public jvmtiEnv {
@@ -125,29 +124,6 @@
   return ret;
 }
 
-struct ArtClassDefinition {
-  jclass klass;
-  jobject loader;
-  std::string name;
-  jobject protection_domain;
-  jint dex_len;
-  JvmtiUniquePtr dex_data;
-  bool modified;
-
-  ArtClassDefinition() = default;
-  ArtClassDefinition(ArtClassDefinition&& o) = default;
-
-  void SetNewDexData(ArtJvmTiEnv* env, jint new_dex_len, unsigned char* new_dex_data) {
-    if (new_dex_data == nullptr) {
-      return;
-    } else if (new_dex_data != dex_data.get() || new_dex_len != dex_len) {
-      modified = true;
-      dex_len = new_dex_len;
-      dex_data = MakeJvmtiUniquePtr(env, new_dex_data);
-    }
-  }
-};
-
 const jvmtiCapabilities kPotentialCapabilities = {
     .can_tag_objects                                 = 1,
     .can_generate_field_modification_events          = 0,
@@ -158,7 +134,7 @@
     .can_get_current_contended_monitor               = 0,
     .can_get_monitor_info                            = 0,
     .can_pop_frame                                   = 0,
-    .can_redefine_classes                            = 1,
+    .can_redefine_classes                            = 0,
     .can_signal_thread                               = 0,
     .can_get_source_file_name                        = 0,
     .can_get_line_numbers                            = 0,
@@ -186,7 +162,7 @@
     .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_classes                         = 0,
     .can_retransform_any_class                       = 0,
     .can_generate_resource_exhaustion_heap_events    = 0,
     .can_generate_resource_exhaustion_threads_events = 0,
diff --git a/runtime/openjdkjvmti/events-inl.h b/runtime/openjdkjvmti/events-inl.h
index 21ec731..1e07bc6 100644
--- a/runtime/openjdkjvmti/events-inl.h
+++ b/runtime/openjdkjvmti/events-inl.h
@@ -115,95 +115,9 @@
 }
 
 template <typename ...Args>
-inline void EventHandler::DispatchClassFileLoadHookEvent(art::Thread*,
-                                                         ArtJvmtiEvent event,
-                                                         Args... args ATTRIBUTE_UNUSED) const {
-  CHECK(event == ArtJvmtiEvent::kClassFileLoadHookRetransformable ||
-        event == ArtJvmtiEvent::kClassFileLoadHookNonRetransformable);
-  LOG(FATAL) << "Incorrect arguments to ClassFileLoadHook!";
-}
-
-// TODO Locking of some type!
-template <>
-inline void EventHandler::DispatchClassFileLoadHookEvent(art::Thread* thread,
-                                                         ArtJvmtiEvent event,
-                                                         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 {
-  CHECK(event == ArtJvmtiEvent::kClassFileLoadHookRetransformable ||
-        event == ArtJvmtiEvent::kClassFileLoadHookNonRetransformable);
-  using FnType = void(jvmtiEnv*            /* jvmti_env */,
-                      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 */);
-  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 (ShouldDispatch(event, env, thread)) {
-      jint new_len;
-      unsigned char* new_data;
-      FnType* callback = GetCallback<FnType>(env, event);
-      callback(env,
-               jnienv,
-               class_being_redefined,
-               loader,
-               name,
-               protection_domain,
-               current_len,
-               current_class_data,
-               &new_len,
-               &new_data);
-      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;
-  }
-}
-
-template <typename ...Args>
 inline void EventHandler::DispatchEvent(art::Thread* thread,
                                         ArtJvmtiEvent event,
                                         Args... args) const {
-  switch (event) {
-    case ArtJvmtiEvent::kClassFileLoadHookRetransformable:
-    case ArtJvmtiEvent::kClassFileLoadHookNonRetransformable:
-      return DispatchClassFileLoadHookEvent(thread, event, args...);
-    default:
-      return GenericDispatchEvent(thread, event, args...);
-  }
-}
-
-// TODO Locking of some type!
-template <typename ...Args>
-inline void EventHandler::GenericDispatchEvent(art::Thread* thread,
-                                               ArtJvmtiEvent event,
-                                               Args... args) const {
   using FnType = void(jvmtiEnv*, Args...);
   for (ArtJvmTiEnv* env : envs) {
     if (ShouldDispatch(event, env, thread)) {
diff --git a/runtime/openjdkjvmti/events.h b/runtime/openjdkjvmti/events.h
index 08a8765..7990141 100644
--- a/runtime/openjdkjvmti/events.h
+++ b/runtime/openjdkjvmti/events.h
@@ -178,15 +178,6 @@
   ALWAYS_INLINE
   inline void RecalculateGlobalEventMask(ArtJvmtiEvent event);
 
-  template <typename ...Args>
-  ALWAYS_INLINE inline void GenericDispatchEvent(art::Thread* thread,
-                                                 ArtJvmtiEvent event,
-                                                 Args... args) const;
-  template <typename ...Args>
-  ALWAYS_INLINE inline void DispatchClassFileLoadHookEvent(art::Thread* thread,
-                                                           ArtJvmtiEvent event,
-                                                           Args... args) const;
-
   void HandleEventType(ArtJvmtiEvent event, bool enable);
 
   // List of all JvmTiEnv objects that have been created, in their creation order.
diff --git a/runtime/openjdkjvmti/ti_redefine.cc b/runtime/openjdkjvmti/ti_redefine.cc
index 28ea267..6af51c4 100644
--- a/runtime/openjdkjvmti/ti_redefine.cc
+++ b/runtime/openjdkjvmti/ti_redefine.cc
@@ -242,12 +242,14 @@
   }
 }
 
+// TODO This should handle doing multiple classes at once so we need to do less cleanup when things
+// go wrong.
 jvmtiError Redefiner::RedefineClasses(ArtJvmTiEnv* env,
                                       art::Runtime* runtime,
                                       art::Thread* self,
                                       jint class_count,
                                       const jvmtiClassDefinition* definitions,
-                                      /*out*/std::string* error_msg) {
+                                      std::string* error_msg) {
   if (env == nullptr) {
     *error_msg = "env was null!";
     return ERR(INVALID_ENVIRONMENT);
@@ -261,83 +263,46 @@
     *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++) {
-    ArtClassDefinition def;
-    def.dex_len = definitions[i].class_byte_count;
-    def.dex_data = MakeJvmtiUniquePtr(env, const_cast<unsigned char*>(definitions[i].class_bytes));
-    // We are definitely modified.
-    def.modified = true;
-    jvmtiError res = Transformer::FillInTransformationData(env, definitions[i].klass, &def);
-    if (res != OK) {
-      return res;
-    }
-    def_vector.push_back(std::move(def));
-  }
-  // Call all the transformation events.
-  jvmtiError res = Transformer::RetransformClassesDirect(env,
-                                                         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);
   std::vector<Redefiner::ClassRedefinition> redefinitions;
-  redefinitions.reserve(definitions.size());
+  redefinitions.reserve(class_count);
   Redefiner r(runtime, self, error_msg);
-  for (const ArtClassDefinition& def : definitions) {
-    // Only try to transform classes that have been modified.
-    if (def.modified) {
-      jvmtiError res = r.AddRedefinition(env, def);
-      if (res != OK) {
-        return res;
-      }
+  for (jint i = 0; i < class_count; i++) {
+    jvmtiError res = r.AddRedefinition(env, definitions[i]);
+    if (res != OK) {
+      return res;
     }
   }
   return r.Run();
 }
 
-jvmtiError Redefiner::AddRedefinition(ArtJvmTiEnv* env, const ArtClassDefinition& def) {
+jvmtiError Redefiner::AddRedefinition(ArtJvmTiEnv* env, const jvmtiClassDefinition& def) {
   std::string original_dex_location;
   jvmtiError ret = OK;
   if ((ret = GetClassLocation(env, def.klass, &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.klass, &signature_ptr, &generic_ptr_unused)) != OK) {
-    *error_msg_ = "Unable to get class signature!";
-    return ret;
-  }
-  JvmtiUniquePtr generic_unique_ptr(MakeJvmtiUniquePtr(env, generic_ptr_unused));
-  JvmtiUniquePtr signature_unique_ptr(MakeJvmtiUniquePtr(env, signature_ptr));
   std::unique_ptr<art::MemMap> map(MoveDataToMemMap(original_dex_location,
-                                                    def.dex_len,
-                                                    def.dex_data.get(),
+                                                    def.class_byte_count,
+                                                    def.class_bytes,
                                                     error_msg_));
   std::ostringstream os;
+  char* generic_ptr_unused = nullptr;
+  char* signature_ptr = nullptr;
+  if (env->GetClassSignature(def.klass, &signature_ptr, &generic_ptr_unused) != OK) {
+    *error_msg_ = "A jclass passed in does not seem to be valid";
+    return ERR(INVALID_CLASS);
+  }
+  // These will make sure we deallocate the signature.
+  JvmtiUniquePtr sig_unique_ptr(MakeJvmtiUniquePtr(env, signature_ptr));
+  JvmtiUniquePtr generic_unique_ptr(MakeJvmtiUniquePtr(env, generic_ptr_unused));
   if (map.get() == nullptr) {
-    os << "Failed to create anonymous mmap for modified dex file of class " << def.name
+    os << "Failed to create anonymous mmap for modified dex file of class " << signature_ptr
        << "in dex file " << original_dex_location << " because: " << *error_msg_;
     *error_msg_ = os.str();
     return ERR(OUT_OF_MEMORY);
@@ -354,7 +319,7 @@
                                                                   /*verify_checksum*/true,
                                                                   error_msg_));
   if (dex_file.get() == nullptr) {
-    os << "Unable to load modified dex file for " << def.name << ": " << *error_msg_;
+    os << "Unable to load modified dex file for " << signature_ptr << ": " << *error_msg_;
     *error_msg_ = os.str();
     return ERR(INVALID_CLASS_FORMAT);
   }
@@ -1024,16 +989,17 @@
 // 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) {
-  DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
-  const art::DexFile::ClassDef& class_def = dex_file_->GetClassDef(0);
-  UpdateMethods(mclass, new_dex_cache, class_def);
+  const art::DexFile::ClassDef* class_def = art::OatFile::OatDexFile::FindClassDef(
+      *dex_file_, class_sig_.c_str(), art::ComputeModifiedUtf8Hash(class_sig_.c_str()));
+  DCHECK(class_def != nullptr);
+  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->SetDexClassDefIndex(dex_file_->GetIndexForClassDef(*class_def));
   mclass->SetDexTypeIndex(dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(class_sig_.c_str())));
 }
 
diff --git a/runtime/openjdkjvmti/ti_redefine.h b/runtime/openjdkjvmti/ti_redefine.h
index f8d51ad..8626bc5 100644
--- a/runtime/openjdkjvmti/ti_redefine.h
+++ b/runtime/openjdkjvmti/ti_redefine.h
@@ -72,25 +72,13 @@
  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.
-  // TODO Check modified flag of the definitions.
-  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.
-  // TODO This function should call the transformation events.
   static jvmtiError RedefineClasses(ArtJvmTiEnv* env,
                                     art::Runtime* runtime,
                                     art::Thread* self,
                                     jint class_count,
                                     const jvmtiClassDefinition* definitions,
-                                    /*out*/std::string* error_msg);
+                                    std::string* error_msg);
 
   static jvmtiError IsModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_redefinable);
 
@@ -221,7 +209,7 @@
         redefinitions_(),
         error_msg_(error_msg) { }
 
-  jvmtiError AddRedefinition(ArtJvmTiEnv* env, const ArtClassDefinition& def)
+  jvmtiError AddRedefinition(ArtJvmTiEnv* env, const jvmtiClassDefinition& def)
       REQUIRES_SHARED(art::Locks::mutator_lock_);
 
   static jvmtiError GetClassRedefinitionError(art::Handle<art::mirror::Class> klass,
diff --git a/runtime/openjdkjvmti/transform.cc b/runtime/openjdkjvmti/transform.cc
index 2809cb6..f545125 100644
--- a/runtime/openjdkjvmti/transform.cc
+++ b/runtime/openjdkjvmti/transform.cc
@@ -38,7 +38,6 @@
 #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"
@@ -53,76 +52,12 @@
 #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,
-      art::Thread* self,
-      /*in-out*/std::vector<ArtClassDefinition>* definitions) {
-  for (ArtClassDefinition& def : *definitions) {
-    jint new_len = -1;
-    unsigned char* new_data = nullptr;
-    // Static casts are so that we get the right template initialization for the special event
-    // handling code required by the ClassFileLoadHooks.
-    gEventHandler.DispatchEvent(self,
-                                ArtJvmtiEvent::kClassFileLoadHookRetransformable,
-                                GetJniEnv(env),
-                                static_cast<jclass>(def.klass),
-                                static_cast<jobject>(def.loader),
-                                static_cast<const char*>(def.name.c_str()),
-                                static_cast<jobject>(def.protection_domain),
-                                static_cast<jint>(def.dex_len),
-                                static_cast<const unsigned char*>(def.dex_data.get()),
-                                static_cast<jint*>(&new_len),
-                                static_cast<unsigned char**>(&new_data));
-    def.SetNewDexData(env, new_len, new_data);
-  }
-  return OK;
-}
-
-jvmtiError Transformer::RetransformClasses(ArtJvmTiEnv* env,
-                                           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++) {
-    ArtClassDefinition def;
-    res = FillInTransformationData(env, classes[i], &def);
-    if (res != OK) {
-      return res;
-    }
-    definitions.push_back(std::move(def));
-  }
-  res = RetransformClassesDirect(env, 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);
@@ -138,61 +73,42 @@
   return OK;
 }
 
-// TODO Implement this for real once transformed dex data is actually saved.
-jvmtiError Transformer::GetDexDataForRetransformation(ArtJvmTiEnv* env,
-                                                      art::Handle<art::mirror::Class> klass,
-                                                      /*out*/jint* dex_data_len,
-                                                      /*out*/unsigned char** dex_data) {
-  // TODO De-quicken the dex file before passing it to the agents.
-  LOG(WARNING) << "Dex file is not de-quickened yet! Quickened dex instructions might be present";
-  LOG(WARNING) << "Caching of initial dex data is not yet performed! Dex data might have been "
-               << "transformed by agent already";
-  const art::DexFile& dex = klass->GetDexFile();
-  *dex_data_len = static_cast<jint>(dex.Size());
-  unsigned char* new_dex_data = nullptr;
-  jvmtiError alloc_error = env->Allocate(*dex_data_len, &new_dex_data);
+// TODO Move this function somewhere more appropriate.
+// Gets the data surrounding the given class.
+jvmtiError GetTransformationData(ArtJvmTiEnv* env,
+                                 jclass klass,
+                                 /*out*/std::string* location,
+                                 /*out*/JNIEnv** jni_env_ptr,
+                                 /*out*/jobject* loader,
+                                 /*out*/std::string* name,
+                                 /*out*/jobject* protection_domain,
+                                 /*out*/jint* data_len,
+                                 /*out*/unsigned char** dex_data) {
+  jint ret = env->art_vm->GetEnv(reinterpret_cast<void**>(jni_env_ptr), JNI_VERSION_1_1);
+  if (ret != JNI_OK) {
+    // TODO Different error might be better?
+    return ERR(INTERNAL);
+  }
+  JNIEnv* jni_env = *jni_env_ptr;
+  art::ScopedObjectAccess soa(jni_env);
+  art::StackHandleScope<3> hs(art::Thread::Current());
+  art::Handle<art::mirror::Class> hs_klass(hs.NewHandle(soa.Decode<art::mirror::Class>(klass)));
+  *loader = soa.AddLocalReference<jobject>(hs_klass->GetClassLoader());
+  *name = art::mirror::Class::ComputeName(hs_klass)->ToModifiedUtf8();
+  // TODO is this always null?
+  *protection_domain = nullptr;
+  const art::DexFile& dex = hs_klass->GetDexFile();
+  *location = dex.GetLocation();
+  *data_len = static_cast<jint>(dex.Size());
+  // TODO We should maybe change env->Allocate to allow us to mprotect this memory and stop writes.
+  jvmtiError alloc_error = env->Allocate(*data_len, dex_data);
   if (alloc_error != OK) {
     return alloc_error;
   }
   // Copy the data into a temporary buffer.
-  memcpy(reinterpret_cast<void*>(new_dex_data),
-         reinterpret_cast<const void*>(dex.Begin()),
-         *dex_data_len);
-  *dex_data = new_dex_data;
-  return OK;
-}
-
-// TODO Move this function somewhere more appropriate.
-// Gets the data surrounding the given class.
-// TODO Make this less magical.
-jvmtiError Transformer::FillInTransformationData(ArtJvmTiEnv* env,
-                                                 jclass klass,
-                                                 ArtClassDefinition* def) {
-  JNIEnv* jni_env = GetJniEnv(env);
-  if (jni_env == nullptr) {
-    // TODO Different error might be better?
-    return ERR(INTERNAL);
-  }
-  art::ScopedObjectAccess soa(jni_env);
-  art::StackHandleScope<3> hs(art::Thread::Current());
-  art::Handle<art::mirror::Class> hs_klass(hs.NewHandle(soa.Decode<art::mirror::Class>(klass)));
-  if (hs_klass.IsNull()) {
-    return ERR(INVALID_CLASS);
-  }
-  def->klass = klass;
-  def->loader = soa.AddLocalReference<jobject>(hs_klass->GetClassLoader());
-  def->name = art::mirror::Class::ComputeName(hs_klass)->ToModifiedUtf8();
-  // TODO is this always null?
-  def->protection_domain = nullptr;
-  if (def->dex_data.get() == nullptr) {
-    unsigned char* new_data;
-    jvmtiError res = GetDexDataForRetransformation(env, hs_klass, &def->dex_len, &new_data);
-    if (res == OK) {
-      def->dex_data = MakeJvmtiUniquePtr(env, new_data);
-    } else {
-      return res;
-    }
-  }
+  memcpy(reinterpret_cast<void*>(*dex_data),
+          reinterpret_cast<const void*>(dex.Begin()),
+          *data_len);
   return OK;
 }
 
diff --git a/runtime/openjdkjvmti/transform.h b/runtime/openjdkjvmti/transform.h
index 0ff2bd1..0ad5099 100644
--- a/runtime/openjdkjvmti/transform.h
+++ b/runtime/openjdkjvmti/transform.h
@@ -43,30 +43,16 @@
 
 jvmtiError GetClassLocation(ArtJvmTiEnv* env, jclass klass, /*out*/std::string* location);
 
-class Transformer {
- public:
-  static jvmtiError RetransformClassesDirect(
-      ArtJvmTiEnv* env, art::Thread* self, /*in-out*/std::vector<ArtClassDefinition>* definitions);
-
-  static jvmtiError RetransformClasses(ArtJvmTiEnv* env,
-                                       art::Runtime* runtime,
-                                       art::Thread* self,
-                                       jint class_count,
-                                       const jclass* classes,
-                                       /*out*/std::string* error_msg);
-
-  // Gets the data surrounding the given class.
-  static jvmtiError FillInTransformationData(ArtJvmTiEnv* env,
-                                             jclass klass,
-                                             ArtClassDefinition* def);
-
- private:
-  static jvmtiError GetDexDataForRetransformation(ArtJvmTiEnv* env,
-                                                  art::Handle<art::mirror::Class> klass,
-                                                  /*out*/jint* dex_data_length,
-                                                  /*out*/unsigned char** dex_data)
-      REQUIRES_SHARED(art::Locks::mutator_lock_);
-};
+// Gets the data surrounding the given class.
+jvmtiError GetTransformationData(ArtJvmTiEnv* env,
+                                 jclass klass,
+                                 /*out*/std::string* location,
+                                 /*out*/JNIEnv** jni_env_ptr,
+                                 /*out*/jobject* loader,
+                                 /*out*/std::string* name,
+                                 /*out*/jobject* protection_domain,
+                                 /*out*/jint* data_len,
+                                 /*out*/unsigned char** dex_data);
 
 }  // namespace openjdkjvmti