Clean up ArtClassDefinition
This struct was somewhat messy. Clean it up and consolidate functions
into it.
Bug: 31455788
Test: ./test.py --host -j40
Change-Id: Ia3abe92dcf3313677de5e200f673252f8e41d69e
diff --git a/runtime/openjdkjvmti/transform.cc b/runtime/openjdkjvmti/transform.cc
index 8e38a36..15d8dd0 100644
--- a/runtime/openjdkjvmti/transform.cc
+++ b/runtime/openjdkjvmti/transform.cc
@@ -39,7 +39,6 @@
#include "dex_file.h"
#include "dex_file_types.h"
#include "events-inl.h"
-#include "fixed_up_dex_file.h"
#include "gc_root-inl.h"
#include "globals.h"
#include "jni_env_ext-inl.h"
@@ -53,7 +52,6 @@
#include "mirror/class_loader-inl.h"
#include "mirror/string-inl.h"
#include "oat_file.h"
-#include "reflection.h"
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread_list.h"
@@ -72,17 +70,18 @@
for (ArtClassDefinition& def : *definitions) {
jint new_len = -1;
unsigned char* new_data = nullptr;
+ art::ArraySlice<const unsigned char> dex_data = def.GetDexData();
event_handler->DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookRetransformable>(
self,
GetJniEnv(env),
- def.klass,
- def.loader,
- def.name.c_str(),
- def.protection_domain,
- def.dex_len,
- static_cast<const unsigned char*>(def.dex_data.get()),
- &new_len,
- &new_data);
+ def.GetClass(),
+ def.GetLoader(),
+ def.GetName().c_str(),
+ def.GetProtectionDomain(),
+ static_cast<jint>(dex_data.size()),
+ &dex_data.At(0),
+ /*out*/&new_len,
+ /*out*/&new_data);
def.SetNewDexData(env, new_len, new_data);
}
return OK;
@@ -120,7 +119,7 @@
return ERR(UNMODIFIABLE_CLASS);
}
ArtClassDefinition def;
- res = FillInTransformationData(env, classes[i], &def);
+ res = def.Init(env, classes[i]);
if (res != OK) {
return res;
}
@@ -149,112 +148,4 @@
return OK;
}
-jvmtiError Transformer::GetDexDataForRetransformation(ArtJvmTiEnv* env,
- art::Handle<art::mirror::Class> klass,
- /*out*/jint* dex_data_len,
- /*out*/unsigned char** dex_data) {
- 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_EQ(orig_dex->GetClass()->GetPrimitiveType(), art::Primitive::kPrimLong);
- 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);
-}
-
-// 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());
- std::string descriptor_store;
- std::string descriptor(hs_klass->GetDescriptor(&descriptor_store));
- def->name = descriptor.substr(1, descriptor.size() - 2);
- // 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);
- // TODO This whole thing is a bit of a mess.
- // We need to keep track of what the runtime should think an unmodified dex file is since
- // we need to be able to tell if anything changes. This might be different then the currently
- // loaded dex file since we need to un-quicken stuff.
- if (hs_klass->GetExtData() == nullptr ||
- hs_klass->GetExtData()->GetOriginalDexFile() == nullptr) {
- // We have never redefined 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 = env->Allocate(def->dex_len, &original_data_memory);
- if (res != OK) {
- return res;
- }
- memcpy(original_data_memory, new_data, def->dex_len);
- def->original_dex_file_memory = MakeJvmtiUniquePtr(env, original_data_memory);
- def->original_dex_file = art::ArraySlice<const unsigned char>(original_data_memory,
- def->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.
- def->original_dex_file = art::ArraySlice<const unsigned char>(
- hs_klass->GetDexFile().Begin(), hs_klass->GetDexFile().Size());
- }
- } else {
- return res;
- }
- }
- return OK;
-}
-
} // namespace openjdkjvmti