diff options
author | 2019-12-03 08:47:26 +0000 | |
---|---|---|
committer | 2019-12-03 08:47:45 +0000 | |
commit | 664999a12d6fc8a8ef5c0519b12ec1e8a51bb085 (patch) | |
tree | f4ae1b0844ac075807229db9695ead7dec07ff8a | |
parent | 642af13b1b14794d8ab0db5cc82206213e648fa1 (diff) |
Revert "Revert^2 "Allow structural redefinition on non-final classes.""
This reverts commit f1b809ce611e943f926fff97cefe0930226ffcc2.
Reason for revert: Tests still fail
Bug: 134162467
Bug: 144168550
Change-Id: Icdebc826b8630920b716afbfd6f338a29669fcc2
47 files changed, 170 insertions, 1518 deletions
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc index 49ac2f571d..842716fac3 100644 --- a/compiler/utils/assembler_thumb_test_expected.cc.inc +++ b/compiler/utils/assembler_thumb_test_expected.cc.inc @@ -76,7 +76,7 @@ const char* const VixlJniHelpersResults[] = { " f0: f1bc 0f00 cmp.w ip, #0\n", " f4: bf18 it ne\n", " f6: f20d 4c01 addwne ip, sp, #1025 ; 0x401\n", - " fa: f8d9 c0a4 ldr.w ip, [r9, #164] ; 0xa4\n", + " fa: f8d9 c09c ldr.w ip, [r9, #156] ; 0x9c\n", " fe: f1bc 0f00 cmp.w ip, #0\n", " 102: d171 bne.n 1e8 <VixlJniHelpers+0x1e8>\n", " 104: f8cd c7ff str.w ip, [sp, #2047] ; 0x7ff\n", @@ -153,7 +153,7 @@ const char* const VixlJniHelpersResults[] = { " 21c: f8d9 8034 ldr.w r8, [r9, #52] ; 0x34\n", " 220: 4770 bx lr\n", " 222: 4660 mov r0, ip\n", - " 224: f8d9 c2ec ldr.w ip, [r9, #748] ; 0x2ec\n", + " 224: f8d9 c2e4 ldr.w ip, [r9, #740] ; 0x2e4\n", " 228: 47e0 blx ip\n", nullptr }; diff --git a/libartbase/base/iteration_range.h b/libartbase/base/iteration_range.h index eaed8b06a8..cd87d85f68 100644 --- a/libartbase/base/iteration_range.h +++ b/libartbase/base/iteration_range.h @@ -49,11 +49,6 @@ inline IterationRange<Iter> MakeIterationRange(const Iter& begin_it, const Iter& return IterationRange<Iter>(begin_it, end_it); } -template<typename List> -inline IterationRange<typename List::iterator> MakeIterationRange(List& list) { - return IterationRange<typename List::iterator>(list.begin(), list.end()); -} - template <typename Iter> inline IterationRange<Iter> MakeEmptyIterationRange(const Iter& it) { return IterationRange<Iter>(it, it); diff --git a/openjdkjvmti/ti_extension.cc b/openjdkjvmti/ti_extension.cc index 130169711f..058a188630 100644 --- a/openjdkjvmti/ti_extension.cc +++ b/openjdkjvmti/ti_extension.cc @@ -423,31 +423,29 @@ jvmtiError ExtensionUtil::GetExtensionFunctions(jvmtiEnv* env, reinterpret_cast<jvmtiExtensionFunction>(Redefiner::StructurallyRedefineClasses), "com.android.art.class.structurally_redefine_classes", "Entrypoint for structural class redefinition. Has the same signature as RedefineClasses." - " Currently does not support redefining a class and any of its supertypes at the same time." - " Only supports additive changes, methods and fields may not be removed. Supertypes and" - " implemented interfaces may not be changed. After calling this" - " com.android.art.structural_dex_file_load_hook events will be triggered, followed by" - " re-transformable ClassFileLoadHook events. After this method completes subsequent" - " RetransformClasses calls will use the input to this function as the initial class" - " definition.", + " Currently this only supports adding new static fields to a class without any instance" + " fields or methods. After calling this com.android.art.structural_dex_file_load_hook" + " events will be triggered, followed by re-transformable ClassFileLoadHook events. After" + " this method completes subsequent RetransformClasses calls will use the input to this" + " function as the initial class definition.", { - { "num_classes", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false }, - { "class_definitions", JVMTI_KIND_IN_BUF, JVMTI_TYPE_CVOID, false }, + { "num_classes", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false }, + { "class_definitions", JVMTI_KIND_IN_BUF, JVMTI_TYPE_CVOID, false }, }, { - ERR(CLASS_LOADER_UNSUPPORTED), - ERR(FAILS_VERIFICATION), - ERR(ILLEGAL_ARGUMENT), - ERR(INVALID_CLASS), - ERR(MUST_POSSESS_CAPABILITY), - ERR(MUST_POSSESS_CAPABILITY), - ERR(NULL_POINTER), - ERR(OUT_OF_MEMORY), - ERR(UNMODIFIABLE_CLASS), - ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), - ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED), - ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED), - ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED), + ERR(CLASS_LOADER_UNSUPPORTED), + ERR(FAILS_VERIFICATION), + ERR(ILLEGAL_ARGUMENT), + ERR(INVALID_CLASS), + ERR(MUST_POSSESS_CAPABILITY), + ERR(MUST_POSSESS_CAPABILITY), + ERR(NULL_POINTER), + ERR(OUT_OF_MEMORY), + ERR(UNMODIFIABLE_CLASS), + ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), + ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED), + ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED), + ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED), }); if (error != ERR(NONE)) { return error; diff --git a/openjdkjvmti/ti_heap.cc b/openjdkjvmti/ti_heap.cc index e1f349a5ac..b25b4d11e2 100644 --- a/openjdkjvmti/ti_heap.cc +++ b/openjdkjvmti/ti_heap.cc @@ -1653,10 +1653,6 @@ static void ReplaceObjectReferences(const ObjectMap& map) // We don't want to update the declaring class of any objects. They will be replaced // in the heap and we need the declaring class to know its size. return; - } else if (UNLIKELY(!is_static && off == art::mirror::Class::SuperClassOffset() && - obj->IsClass())) { - // We don't want to be messing with the class hierarcy either. - return; } VLOG(plugin) << "Updating field at offset " << off.Uint32Value() << " of type " << obj->GetClass()->PrettyClass(); diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index 53bf4df3d1..3d24c831a4 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -54,10 +54,7 @@ #include "base/casts.h" #include "base/enums.h" #include "base/globals.h" -#include "base/iteration_range.h" #include "base/length_prefixed_array.h" -#include "base/locks.h" -#include "base/stl_util.h" #include "base/utils.h" #include "class_linker-inl.h" #include "class_linker.h" @@ -464,6 +461,36 @@ jvmtiError Redefiner::GetClassRedefinitionError(art::Handle<art::mirror::Class> "safe to structurally redefine it."; return ERR(UNMODIFIABLE_CLASS); } + // Check for already existing non-static fields/methods. + // TODO Remove this once we support generic method/field addition. + if (!klass->IsFinal()) { + bool non_static_method = false; + klass->VisitMethods([&](art::ArtMethod* m) REQUIRES_SHARED(art::Locks::mutator_lock_) { + // Since direct-methods (ie privates + <init> are not in any vtable/iftable we can update + // them). + if (!m->IsDirect()) { + non_static_method = true; + *error_msg = StringPrintf("%s has a non-direct function %s", + klass->PrettyClass().c_str(), + m->PrettyMethod().c_str()); + } + }, art::kRuntimePointerSize); + if (non_static_method) { + return ERR(UNMODIFIABLE_CLASS); + } + bool non_static_field = false; + klass->VisitFields([&](art::ArtField* f) REQUIRES_SHARED(art::Locks::mutator_lock_) { + if (!f->IsStatic()) { + non_static_field = true; + *error_msg = StringPrintf("%s has a non-static field %s", + klass->PrettyClass().c_str(), + f->PrettyField().c_str()); + } + }); + if (non_static_field) { + return ERR(UNMODIFIABLE_CLASS); + } + } // Check for fields/methods which were returned before moving to index jni id type. // TODO We might want to rework how this is done. Once full redefinition is implemented we will // need to check any subtypes too. @@ -947,7 +974,8 @@ bool Redefiner::ClassRedefinition::CheckMethods() { RecordHasVirtualMembers(); } if (old_iter == old_methods.cend()) { - if (is_structural) { + // TODO Support adding non-static methods. + if (is_structural && (new_method.IsStaticOrDirect() || h_klass->IsFinal())) { RecordNewMethodAdded(); } else { RecordFailure( @@ -1010,7 +1038,8 @@ bool Redefiner::ClassRedefinition::CheckFields() { RecordHasVirtualMembers(); } if (old_iter == old_fields.cend()) { - if (driver_->IsStructuralRedefinition()) { + // TODO Support adding non-static fields. + if (driver_->IsStructuralRedefinition() && (new_field.IsStatic() || h_klass->IsFinal())) { RecordNewFieldAdded(); } else { RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED), @@ -1169,11 +1198,9 @@ class RedefinitionDataHolder { kSlotNewClassObject = 8, kSlotOldInstanceObjects = 9, kSlotNewInstanceObjects = 10, - kSlotOldClasses = 11, - kSlotNewClasses = 12, // Must be last one. - kNumSlots = 13, + kNumSlots = 11, }; // This needs to have a HandleScope passed in that is capable of creating a new Handle without @@ -1250,16 +1277,6 @@ class RedefinitionDataHolder { return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>>::DownCast( GetSlot(klass_index, kSlotNewInstanceObjects)); } - art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetOldClasses(jint klass_index) const - REQUIRES_SHARED(art::Locks::mutator_lock_) { - return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>>::DownCast( - GetSlot(klass_index, kSlotOldClasses)); - } - art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetNewClasses(jint klass_index) const - REQUIRES_SHARED(art::Locks::mutator_lock_) { - return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>>::DownCast( - GetSlot(klass_index, kSlotNewClasses)); - } void SetSourceClassLoader(jint klass_index, art::ObjPtr<art::mirror::ClassLoader> loader) REQUIRES_SHARED(art::Locks::mutator_lock_) { @@ -1310,16 +1327,6 @@ class RedefinitionDataHolder { REQUIRES_SHARED(art::Locks::mutator_lock_) { SetSlot(klass_index, kSlotNewInstanceObjects, objs); } - void SetOldClasses(jint klass_index, - art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses) - REQUIRES_SHARED(art::Locks::mutator_lock_) { - SetSlot(klass_index, kSlotOldClasses, klasses); - } - void SetNewClasses(jint klass_index, - art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses) - REQUIRES_SHARED(art::Locks::mutator_lock_) { - SetSlot(klass_index, kSlotNewClasses, klasses); - } int32_t Length() const REQUIRES_SHARED(art::Locks::mutator_lock_) { return arr_->GetLength() / kNumSlots; } @@ -1463,14 +1470,6 @@ class RedefinitionDataIter { REQUIRES_SHARED(art::Locks::mutator_lock_) { return holder_.GetNewInstanceObjects(idx_); } - art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetOldClasses() const - REQUIRES_SHARED(art::Locks::mutator_lock_) { - return holder_.GetOldClasses(idx_); - } - art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetNewClasses() const - REQUIRES_SHARED(art::Locks::mutator_lock_) { - return holder_.GetNewClasses(idx_); - } int32_t GetIndex() const { return idx_; } @@ -1519,14 +1518,6 @@ class RedefinitionDataIter { REQUIRES_SHARED(art::Locks::mutator_lock_) { holder_.SetNewInstanceObjects(idx_, objs); } - void SetOldClasses(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses) - REQUIRES_SHARED(art::Locks::mutator_lock_) { - holder_.SetOldClasses(idx_, klasses); - } - void SetNewClasses(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses) - REQUIRES_SHARED(art::Locks::mutator_lock_) { - holder_.SetNewClasses(idx_, klasses); - } private: int32_t idx_; @@ -1637,104 +1628,23 @@ bool Redefiner::ClassRedefinition::CollectAndCreateNewInstances( art::VariableSizedHandleScope hs(driver_->self_); art::Handle<art::mirror::Class> old_klass(hs.NewHandle(cur_data->GetMirrorClass())); std::vector<art::Handle<art::mirror::Object>> old_instances; - std::vector<art::Handle<art::mirror::Class>> old_types; art::gc::Heap* heap = driver_->runtime_->GetHeap(); - auto is_subtype = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) { - // We've already waited for class defines to be finished and paused them. All classes should be - // either resolved or error. We don't need to do anything with error classes, since they cannot - // be accessed in any observable way. - return obj->IsClass() && obj->AsClass()->IsResolved() && - old_klass->IsAssignableFrom(obj->AsClass()); - }; auto is_instance = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) { - return obj->InstanceOf(old_klass.Get()); + if (HasVirtualMembers()) { + return old_klass->IsAssignableFrom(obj->GetClass()); + } else { + // We don't need to deal with objects of subtypes when we don't modify virtuals since the + // vtable + field layout will remain the same. + return old_klass.Get() == obj->GetClass(); + } }; heap->VisitObjects([&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) { if (is_instance(obj)) { + CHECK(old_klass.Get() == obj->GetClass()) << "No support for subtypes yet!"; old_instances.push_back(hs.NewHandle(obj)); - } else if (is_subtype(obj)) { - old_types.push_back(hs.NewHandle(obj->AsClass())); } }); VLOG(plugin) << "Collected " << old_instances.size() << " instances to recreate!"; - VLOG(plugin) << "Found " << old_types.size() << " types that are/are subtypes of " - << old_klass->PrettyClass(); - - art::Handle<art::mirror::Class> cls_array_class( - hs.NewHandle(art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Class>>( - driver_->runtime_->GetClassLinker()))); - art::Handle<art::mirror::ObjectArray<art::mirror::Class>> old_classes_arr( - hs.NewHandle(art::mirror::ObjectArray<art::mirror::Class>::Alloc( - driver_->self_, cls_array_class.Get(), old_types.size()))); - if (old_classes_arr.IsNull()) { - driver_->self_->AssertPendingOOMException(); - driver_->self_->ClearException(); - RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate old_classes arrays!"); - return false; - } - // Sort the old_types topologically. - { - art::ScopedAssertNoThreadSuspension sants("Sort classes"); - auto count_distance = - [&](art::ObjPtr<art::mirror::Class> c) REQUIRES_SHARED(art::Locks::mutator_lock_) { - uint32_t res = 0; - while (c != old_klass.Get()) { - DCHECK_NE(c, art::GetClassRoot<art::mirror::Object>()); - res++; - c = c->GetSuperClass(); - } - return res; - }; - auto compare_handles = [&](auto l, auto r) REQUIRES_SHARED(art::Locks::mutator_lock_) { - return count_distance(l.Get()) < count_distance(r.Get()); - }; - // Sort them by the distance to the base-class. This ensures that any class occurs before any of - // its subtypes. - std::sort(old_types.begin(), old_types.end(), compare_handles); - } - for (uint32_t i = 0; i < old_types.size(); ++i) { - old_classes_arr->Set(i, old_types[i].Get()); - } - cur_data->SetOldClasses(old_classes_arr.Get()); - art::Handle<art::mirror::ObjectArray<art::mirror::Class>> new_classes_arr( - hs.NewHandle(art::mirror::ObjectArray<art::mirror::Class>::Alloc( - driver_->self_, cls_array_class.Get(), old_types.size()))); - if (new_classes_arr.IsNull()) { - driver_->self_->AssertPendingOOMException(); - driver_->self_->ClearException(); - RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate new_classes arrays!"); - return false; - } - art::MutableHandle<art::mirror::DexCache> dch(hs.NewHandle<art::mirror::DexCache>(nullptr)); - art::MutableHandle<art::mirror::Class> superclass(hs.NewHandle<art::mirror::Class>(nullptr)); - for (size_t i = 0; i < old_types.size(); i++) { - art::Handle<art::mirror::Class>& old_class = old_types[i]; - if (old_class.Get() == cur_data->GetMirrorClass()) { - CHECK_EQ(i, 0u) << "original class not at index 0. Bad sort!"; - new_classes_arr->Set(i, cur_data->GetNewClassObject()); - continue; - } else { - auto old_super = std::find_if(old_types.begin(), - old_types.begin() + i, - [&](art::Handle<art::mirror::Class>& v) - REQUIRES_SHARED(art::Locks::mutator_lock_) { - return v.Get() == old_class->GetSuperClass(); - }); - // Only the GetMirrorClass should not be in this list. - CHECK(old_super != old_types.begin() + i) - << "from first " << i << " could not find super of " << old_class->PrettyClass() - << " expected to find " << old_class->GetSuperClass()->PrettyClass(); - superclass.Assign(new_classes_arr->Get(std::distance(old_types.begin(), old_super))); - dch.Assign(old_class->GetDexCache()); - art::ObjPtr<art::mirror::Class> new_class( - AllocateNewClassObject(old_class, superclass, dch, old_class->GetDexClassDefIndex())); - if (new_class == nullptr) { - return false; - } - new_classes_arr->Set(i, new_class); - } - } - cur_data->SetNewClasses(new_classes_arr.Get()); art::Handle<art::mirror::Class> obj_array_class( hs.NewHandle(art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>( @@ -1762,18 +1672,9 @@ bool Redefiner::ClassRedefinition::CollectAndCreateNewInstances( RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate new_instance arrays!"); return false; } - for (auto pair : art::ZipCount(art::IterationRange(old_instances.begin(), old_instances.end()))) { - art::Handle<art::mirror::Object> hinstance(pair.first); - int32_t i = pair.second; - auto iterator = art::ZipLeft(old_classes_arr.Iterate<art::mirror::Class>(), - new_classes_arr.Iterate<art::mirror::Class>()); - auto [_, new_type] = - *(std::find_if(iterator.begin(), - iterator.end(), - [&](auto class_pair) REQUIRES_SHARED(art::Locks::mutator_lock_) { - return class_pair.first == hinstance->GetClass(); - })); - art::ObjPtr<art::mirror::Object> new_instance(new_type->AllocObject(driver_->self_)); + art::Handle<art::mirror::Class> new_klass(hs.NewHandle(cur_data->GetNewClassObject())); + for (uint32_t i = 0; i < old_instances.size(); ++i) { + art::ObjPtr<art::mirror::Object> new_instance(new_klass->AllocObject(driver_->self_)); if (new_instance.IsNull()) { driver_->self_->AssertPendingOOMException(); driver_->self_->ClearException(); @@ -1833,6 +1734,8 @@ bool Redefiner::ClassRedefinition::FinishRemainingAllocations( art::Handle<art::mirror::Class> nc(hs.NewHandle( AllocateNewClassObject(hs.NewHandle(cur_data->GetNewDexCache())))); if (nc.IsNull()) { + driver_->self_->ClearException(); + RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate new class object"); return false; } @@ -1846,15 +1749,18 @@ bool Redefiner::ClassRedefinition::FinishRemainingAllocations( return true; } -uint32_t Redefiner::ClassRedefinition::GetNewClassSize(art::ClassAccessor& accessor) { +uint32_t Redefiner::ClassRedefinition::GetNewClassSize(bool with_embedded_tables, + art::Handle<art::mirror::Class> old_klass) { + // TODO Once we can add methods this won't work any more. + uint32_t num_vtable_entries = old_klass->GetVTableLength(); uint32_t num_8bit_static_fields = 0; uint32_t num_16bit_static_fields = 0; uint32_t num_32bit_static_fields = 0; uint32_t num_64bit_static_fields = 0; uint32_t num_ref_static_fields = 0; + art::ClassAccessor accessor(*dex_file_, dex_file_->GetClassDef(0)); for (const art::ClassAccessor::Field& f : accessor.GetStaticFields()) { - std::string_view desc(accessor.GetDexFile().GetFieldTypeDescriptor( - accessor.GetDexFile().GetFieldId(f.GetIndex()))); + std::string_view desc(dex_file_->GetFieldTypeDescriptor(dex_file_->GetFieldId(f.GetIndex()))); if (desc[0] == 'L' || desc[0] == '[') { num_ref_static_fields++; } else if (desc == "Z" || desc == "B") { @@ -1870,8 +1776,8 @@ uint32_t Redefiner::ClassRedefinition::GetNewClassSize(art::ClassAccessor& acces } } - return art::mirror::Class::ComputeClassSize(/*has_embedded_vtable=*/ false, - /*num_vtable_entries=*/ 0, + return art::mirror::Class::ComputeClassSize(with_embedded_tables, + with_embedded_tables ? num_vtable_entries : 0, num_8bit_static_fields, num_16bit_static_fields, num_32bit_static_fields, @@ -1882,41 +1788,23 @@ uint32_t Redefiner::ClassRedefinition::GetNewClassSize(art::ClassAccessor& acces art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::AllocateNewClassObject(art::Handle<art::mirror::DexCache> cache) { - art::StackHandleScope<2> hs(driver_->self_); - art::Handle<art::mirror::Class> old_class(hs.NewHandle(GetMirrorClass())); - art::Handle<art::mirror::Class> super_class(hs.NewHandle(old_class->GetSuperClass())); - return AllocateNewClassObject(old_class, super_class, cache, /*dex_class_def_index*/0); -} - -art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::AllocateNewClassObject( - art::Handle<art::mirror::Class> old_class, - art::Handle<art::mirror::Class> super_class, - art::Handle<art::mirror::DexCache> cache, - uint16_t dex_class_def_index) { // This is a stripped down DefineClass. We don't want to use DefineClass directly because it needs // to perform a lot of extra steps to tell the ClassTable and the jit and everything about a new // class. For now we will need to rely on our tests catching any issues caused by changes in how // class_linker sets up classes. // TODO Unify/move this into ClassLinker maybe. - art::StackHandleScope<3> hs(driver_->self_); + art::StackHandleScope<5> hs(driver_->self_); art::ClassLinker* linker = driver_->runtime_->GetClassLinker(); - const art::DexFile* dex_file = cache->GetDexFile(); - art::ClassAccessor accessor(*dex_file, dex_class_def_index); + art::Handle<art::mirror::Class> old_class(hs.NewHandle(GetMirrorClass())); art::Handle<art::mirror::Class> new_class(hs.NewHandle(linker->AllocClass( - driver_->self_, GetNewClassSize(accessor)))); + driver_->self_, GetNewClassSize(/*with_embedded_tables=*/false, old_class)))); if (new_class.IsNull()) { driver_->self_->AssertPendingOOMException(); - RecordFailure( - ERR(OUT_OF_MEMORY), - "Unable to allocate class object for redefinition of " + old_class->PrettyClass()); - driver_->self_->ClearException(); + JVMTI_LOG(ERROR, driver_->env_) << "Unable to allocate new class object!"; return nullptr; } new_class->SetDexCache(cache.Get()); - linker->SetupClass(*dex_file, - dex_file->GetClassDef(dex_class_def_index), - new_class, - old_class->GetClassLoader()); + linker->SetupClass(*dex_file_, dex_file_->GetClassDef(0), new_class, old_class->GetClassLoader()); // Make sure we are ready for linking. The lock isn't really needed since this isn't visible to // other threads but the linker expects it. @@ -1924,46 +1812,31 @@ art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::AllocateNewClassOb new_class->SetClinitThreadId(driver_->self_->GetTid()); // Make sure we have a valid empty iftable even if there are errors. new_class->SetIfTable(art::GetClassRoot<art::mirror::Object>(linker)->GetIfTable()); - linker->LoadClass( - driver_->self_, *dex_file, dex_file->GetClassDef(dex_class_def_index), new_class); + linker->LoadClass(driver_->self_, *dex_file_, dex_file_->GetClassDef(0), new_class); // NB. We know the interfaces and supers didn't change! :) art::MutableHandle<art::mirror::Class> linked_class(hs.NewHandle<art::mirror::Class>(nullptr)); art::Handle<art::mirror::ObjectArray<art::mirror::Class>> proxy_ifaces( hs.NewHandle<art::mirror::ObjectArray<art::mirror::Class>>(nullptr)); // No changing hierarchy so everything is loaded. - new_class->SetSuperClass(super_class.Get()); + new_class->SetSuperClass(old_class->GetSuperClass()); art::mirror::Class::SetStatus(new_class, art::ClassStatus::kLoaded, nullptr); if (!linker->LinkClass(driver_->self_, nullptr, new_class, proxy_ifaces, &linked_class)) { - std::ostringstream oss; - oss << "failed to link class due to " + JVMTI_LOG(ERROR, driver_->env_) + << "failed to link class due to " << (driver_->self_->IsExceptionPending() ? driver_->self_->GetException()->Dump() : " unknown"); - RecordFailure(ERR(INTERNAL), oss.str()); driver_->self_->ClearException(); return nullptr; } - // Everything is already resolved. + // We will initialize it manually. art::ObjectLock<art::mirror::Class> objlock(driver_->self_, linked_class); + // We already verified the class earlier. No need to do it again. + linked_class->SetVerificationAttempted(); // Mark the class as initialized. - CHECK(old_class->IsResolved()) - << "Attempting to redefine an unresolved class " << old_class->PrettyClass() + CHECK(old_class->IsInitialized()) + << "Attempting to redefine an uninitalized class " << old_class->PrettyClass() << " status=" << old_class->GetStatus(); - CHECK(linked_class->IsResolved()); - if (old_class->WasVerificationAttempted()) { - // Match verification-attempted flag - linked_class->SetVerificationAttempted(); - } - if (old_class->ShouldSkipHiddenApiChecks()) { - // Match skip hiddenapi flag - linked_class->SetSkipHiddenApiChecks(); - } - if (old_class->IsInitialized()) { - // We already verified the class earlier. No need to do it again. - linker->ForceClassInitialized(driver_->self_, linked_class); - } else if (old_class->GetStatus() > linked_class->GetStatus()) { - // We want to match the old status. - art::mirror::Class::SetStatus(linked_class, old_class->GetStatus(), driver_->self_); - } + linker->ForceClassInitialized(driver_->self_, linked_class); // Make sure we have ext-data space for method & field ids. We won't know if we need them until // it's too late to create them. // TODO We might want to remove these arrays if they're not needed. @@ -1972,9 +1845,7 @@ art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::AllocateNewClassOb !art::mirror::Class::EnsureMethodIds(linked_class)) { driver_->self_->AssertPendingOOMException(); driver_->self_->ClearException(); - RecordFailure( - ERR(OUT_OF_MEMORY), - "Unable to allocate jni-id arrays for redefinition of " + old_class->PrettyClass()); + JVMTI_LOG(ERROR, driver_->env_) << "Unable to allocate jni-id arrays!"; return nullptr; } // Finish setting up methods. @@ -1991,9 +1862,6 @@ art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::AllocateNewClassOb DCHECK_EQ(f->GetDeclaringClass(), linked_class.Get()); }); } - // Reset ClinitThreadId back to the thread that loaded the old class. This is needed if we are in - // the middle of initializing a class. - linked_class->SetClinitThreadId(old_class->GetClinitThreadId()); return linked_class.Get(); } @@ -2024,39 +1892,9 @@ bool Redefiner::CheckAllRedefinitionAreValid() { return false; } } - if (std::any_of( - redefinitions_.begin(), - redefinitions_.end(), - std::function<bool(ClassRedefinition&)>(&ClassRedefinition::IsStructuralRedefinition))) { - return CheckClassHierarchy(); - } return true; } -bool Redefiner::CheckClassHierarchy() { - return std::all_of( - redefinitions_.begin(), - redefinitions_.end(), - [&](ClassRedefinition& r) REQUIRES_SHARED(art::Locks::mutator_lock_) { - return std::none_of( - redefinitions_.begin(), - redefinitions_.end(), - [&](ClassRedefinition& r2) REQUIRES_SHARED(art::Locks::mutator_lock_) { - bool related = &r2 != &r && - r2.GetMirrorClass()->IsAssignableFrom(r.GetMirrorClass()) && - r2.IsStructuralRedefinition(); - if (related) { - std::ostringstream oss; - oss << "Structurally redefining " << r2.GetMirrorClass()->PrettyClass() - << " which is a superclass of " << r.GetMirrorClass()->PrettyClass() - << ". This is not currently supported"; - r2.RecordFailure(ERR(INTERNAL), oss.str()); - } - return related; - }); - }); -} - void Redefiner::RestoreObsoleteMethodMapsIfUnneeded(RedefinitionDataHolder& holder) { for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) { data.GetRedefinition().RestoreObsoleteMethodMapsIfUnneeded(&data); @@ -2130,142 +1968,6 @@ class ScopedDisableConcurrentAndMovingGc { art::Thread* self_; }; -class ClassDefinitionPauser : public art::ClassLoadCallback { - public: - explicit ClassDefinitionPauser(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) - : self_(self), - is_running_(false), - barrier_(0), - release_mu_("SuspendClassDefinition lock", art::kGenericBottomLock), - release_barrier_(0), - release_cond_("SuspendClassDefinition condvar", release_mu_), - count_(0), - release_(false) { - art::Locks::mutator_lock_->AssertSharedHeld(self_); - } - ~ClassDefinitionPauser() REQUIRES_SHARED(art::Locks::mutator_lock_) { - art::Locks::mutator_lock_->AssertSharedHeld(self_); - if (is_running_) { - uint32_t count; - // Wake up everything. - { - art::MutexLock mu(self_, release_mu_); - release_ = true; - count = count_; - release_cond_.Broadcast(self_); - } - // Wait for all threads to leave this structs code. - art::ScopedThreadSuspension sts(self_, art::ThreadState::kWaiting); - VLOG(plugin) << "Resuming " << count << " threads paused before class-allocation!"; - release_barrier_.Increment(self_, count); - } - } - void BeginDefineClass() override REQUIRES_SHARED(art::Locks::mutator_lock_) { - art::Thread* this_thread = art::Thread::Current(); - if (this_thread == self_) { - // Allow the redefining thread to do whatever. - return; - } - if (this_thread->GetDefineClassCount() != 0) { - // We are in the middle of a recursive define-class. Don't suspend now allow it to finish. - VLOG(plugin) << "Recursive DefineClass in " << *this_thread - << " allowed to proceed despite class-def pause initiated by " << *self_; - return; - } - art::ScopedThreadSuspension sts(this_thread, art::ThreadState::kSuspended); - { - art::MutexLock mu(this_thread, release_mu_); - if (release_) { - // Count already retrieved, no need to pass. - return; - } - VLOG(plugin) << "Suspending " << *this_thread << " due to class definition. class-def pause " - << "initiated by " << *self_; - count_++; - while (!release_) { - release_cond_.Wait(this_thread); - } - } - release_barrier_.Pass(this_thread); - } - void EndDefineClass() override REQUIRES_SHARED(art::Locks::mutator_lock_) { - art::Thread* this_thread = art::Thread::Current(); - if (this_thread == self_) { - // Allow the redefining thread to do whatever. - return; - } - if (this_thread->GetDefineClassCount() == 0) { - // We are done with defining classes. - barrier_.Pass(this_thread); - } - } - - void ClassLoad(art::Handle<art::mirror::Class> klass ATTRIBUTE_UNUSED) override {} - void ClassPrepare(art::Handle<art::mirror::Class> klass1 ATTRIBUTE_UNUSED, - art::Handle<art::mirror::Class> klass2 ATTRIBUTE_UNUSED) override {} - - void SetRunning() { - is_running_ = true; - } - void WaitFor(uint32_t t) REQUIRES(!art::Locks::mutator_lock_) { - barrier_.Increment(self_, t); - } - - private: - art::Thread* self_; - bool is_running_; - art::Barrier barrier_; - art::Mutex release_mu_; - art::Barrier release_barrier_; - art::ConditionVariable release_cond_; - uint32_t count_ GUARDED_BY(release_mu_); - bool release_; -}; - -class ScopedSuspendClassLoading { - public: - ScopedSuspendClassLoading(art::Thread* self, art::Runtime* runtime, RedefinitionDataHolder& h) - REQUIRES_SHARED(art::Locks::mutator_lock_) - : self_(self), runtime_(runtime), paused_(false), pauser_(self_) { - if (std::any_of(h.begin(), h.end(), [](auto r) REQUIRES_SHARED(art::Locks::mutator_lock_) { - return r.GetRedefinition().IsStructuralRedefinition(); - })) { - VLOG(plugin) << "Pausing Class loading for structural redefinition."; - paused_ = true; - { - art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative); - uint32_t in_progress_defines = 0; - { - art::ScopedSuspendAll ssa(__FUNCTION__); - pauser_.SetRunning(); - runtime_->GetRuntimeCallbacks()->AddClassLoadCallback(&pauser_); - art::MutexLock mu(self_, *art::Locks::thread_list_lock_); - runtime_->GetThreadList()->ForEach([&](art::Thread* t) { - if (t != self_ && t->GetDefineClassCount() != 0) { - in_progress_defines++; - } - }); - VLOG(plugin) << "Waiting for " << in_progress_defines << " in progress class-loads to finish"; - } - pauser_.WaitFor(in_progress_defines); - } - } - } - ~ScopedSuspendClassLoading() { - if (paused_) { - art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative); - art::ScopedSuspendAll ssa(__FUNCTION__); - runtime_->GetRuntimeCallbacks()->RemoveClassLoadCallback(&pauser_); - } - } - - private: - art::Thread* self_; - art::Runtime* runtime_; - bool paused_; - ClassDefinitionPauser pauser_; -}; - class ScopedSuspendAllocations { public: ScopedSuspendAllocations(art::Runtime* runtime, RedefinitionDataHolder& h) @@ -2320,7 +2022,6 @@ jvmtiError Redefiner::Run() { return result_; } - ScopedSuspendClassLoading suspend_class_load(self_, runtime_, holder); ScopedSuspendAllocations suspend_alloc(runtime_, holder); if (!CollectAndCreateNewInstances(holder)) { return result_; @@ -2452,28 +2153,27 @@ void Redefiner::ClassRedefinition::CollectNewFieldAndMethodMappings( const RedefinitionDataIter& data, std::map<art::ArtMethod*, art::ArtMethod*>* method_map, std::map<art::ArtField*, art::ArtField*>* field_map) { - for (auto [new_cls, old_cls] : - art::ZipLeft(data.GetNewClasses()->Iterate(), data.GetOldClasses()->Iterate())) { - for (art::ArtField& f : old_cls->GetSFields()) { - (*field_map)[&f] = new_cls->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor()); - } - for (art::ArtField& f : old_cls->GetIFields()) { - (*field_map)[&f] = new_cls->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor()); - } - auto new_methods = new_cls->GetMethods(art::kRuntimePointerSize); - for (art::ArtMethod& m : old_cls->GetMethods(art::kRuntimePointerSize)) { - // No support for finding methods in this way since it's generally not needed. Just do it the - // easy way. - auto nm_iter = std::find_if( - new_methods.begin(), - new_methods.end(), - [&](art::ArtMethod& cand) REQUIRES_SHARED(art::Locks::mutator_lock_) { - return cand.GetNameView() == m.GetNameView() && cand.GetSignature() == m.GetSignature(); - }); - CHECK(nm_iter != new_methods.end()) - << "Could not find redefined version of " << m.PrettyMethod(); - (*method_map)[&m] = &(*nm_iter); - } + art::ObjPtr<art::mirror::Class> old_cls(data.GetMirrorClass()); + art::ObjPtr<art::mirror::Class> new_cls(data.GetNewClassObject()); + for (art::ArtField& f : old_cls->GetSFields()) { + (*field_map)[&f] = new_cls->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor()); + } + for (art::ArtField& f : old_cls->GetIFields()) { + (*field_map)[&f] = new_cls->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor()); + } + auto new_methods = new_cls->GetMethods(art::kRuntimePointerSize); + for (art::ArtMethod& m : old_cls->GetMethods(art::kRuntimePointerSize)) { + // No support for finding methods in this way since it's generally not needed. Just do it the + // easy way. + auto nm_iter = std::find_if( + new_methods.begin(), + new_methods.end(), + [&](art::ArtMethod& cand) REQUIRES_SHARED(art::Locks::mutator_lock_) { + return cand.GetNameView() == m.GetNameView() && cand.GetSignature() == m.GetSignature(); + }); + CHECK(nm_iter != new_methods.end()) + << "Could not find redefined version of " << m.PrettyMethod(); + (*method_map)[&m] = &(*nm_iter); } } @@ -2600,8 +2300,6 @@ void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDat art::ScopedAssertNoThreadSuspension sants(__FUNCTION__); art::ObjPtr<art::mirror::Class> orig(holder.GetMirrorClass()); art::ObjPtr<art::mirror::Class> replacement(holder.GetNewClassObject()); - art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> new_classes(holder.GetNewClasses()); - art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> old_classes(holder.GetOldClasses()); // Collect mappings from old to new fields/methods std::map<art::ArtMethod*, art::ArtMethod*> method_map; std::map<art::ArtField*, art::ArtField*> field_map; @@ -2612,26 +2310,13 @@ void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDat holder.GetOldInstanceObjects()); CHECK(!orig.IsNull()); CHECK(!replacement.IsNull()); - // Once we do the ReplaceReferences old_classes will have the new_classes in it. We want to keep - // ahold of the old classes so copy them now. - std::vector<art::ObjPtr<art::mirror::Class>> old_classes_vec(old_classes->Iterate().begin(), - old_classes->Iterate().end()); // Copy over the static fields of the class and all the instance fields. - for (auto [new_class, old_class] : art::ZipLeft(new_classes->Iterate(), old_classes->Iterate())) { - CHECK(!new_class.IsNull()); - CHECK(!old_class.IsNull()); - CHECK(!old_class->IsErroneous()); - if (old_class->GetStatus() > new_class->GetStatus()) { - // Some verification/initialization step happened during interval between - // creating the new class and now. Just copy the new status. - new_class->SetStatusLocked(old_class->GetStatus()); - } - CopyAndClearFields(true, new_class, new_class, old_class, old_class); - } + CopyAndClearFields(/*is_static=*/true, replacement, replacement, orig, orig); // Copy and clear the fields of the old-instances. - for (auto [new_instance, old_instance] : - art::ZipLeft(new_instances->Iterate(), old_instances->Iterate())) { + for (int32_t i = 0; i < old_instances->GetLength(); i++) { + art::ObjPtr<art::mirror::Object> old_instance(old_instances->Get(i)); + art::ObjPtr<art::mirror::Object> new_instance(new_instances->Get(i)); CopyAndClearFields(/*is_static=*/false, new_instance, new_instance->GetClass(), @@ -2639,15 +2324,12 @@ void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDat old_instance->GetClass()); } // Mark old class obsolete. - for (auto old_class : old_classes->Iterate()) { - old_class->SetObsoleteObject(); - // Mark methods obsolete. We need to wait until later to actually clear the jit data. - for (art::ArtMethod& m : old_class->GetMethods(art::kRuntimePointerSize)) { - m.SetIsObsolete(); - if (m.IsInvokable()) { - m.SetDontCompile(); - } - } + orig->SetObsoleteObject(); + // Mark methods obsolete. We need to wait until later to actually clear the jit data. + for (art::ArtMethod& m : orig->GetMethods(art::kRuntimePointerSize)) { + m.SetIsObsolete(); + m.SetDontCompile(); + DCHECK_EQ(orig, m.GetDeclaringClass()); } // Update live pointers in ART code. auto could_change_resolution_of = [&](auto* field_or_method, @@ -2736,16 +2418,9 @@ void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDat std::unordered_map<art::ObjPtr<art::mirror::Object>, art::ObjPtr<art::mirror::Object>, art::HashObjPtr> map; - for (auto [new_class, old_class] : art::ZipLeft(new_classes->Iterate(), old_classes->Iterate())) { - map.emplace(old_class, new_class); - } - for (auto [new_instance, old_instance] : - art::ZipLeft(new_instances->Iterate(), old_instances->Iterate())) { - map.emplace(old_instance, new_instance); - // Bare-bones check that the mapping is correct. - CHECK(new_instance->GetClass() == map[old_instance->GetClass()]->AsClass()) - << new_instance->GetClass()->PrettyClass() << " vs " - << map[old_instance->GetClass()]->AsClass()->PrettyClass(); + map.emplace(orig, replacement); + for (int32_t i = 0; i < old_instances->GetLength(); i++) { + map.emplace(old_instances->Get(i), new_instances->Get(i)); } // Actually perform the general replacement. This doesn't affect ArtMethod/ArtFields. It does @@ -2755,10 +2430,8 @@ void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDat // Save the old class so that the JIT gc doesn't get confused by it being collected before the // jit code. This is also needed to keep the dex-caches of any obsolete methods live. - for (auto [new_class, old_class] : - art::ZipLeft(new_classes->Iterate(), art::MakeIterationRange(old_classes_vec))) { - new_class->GetExtData()->SetObsoleteClass(old_class); - } + replacement->GetExtData()->SetObsoleteClass(orig); + art::jit::Jit* jit = driver_->runtime_->GetJit(); if (jit != nullptr) { @@ -2781,10 +2454,6 @@ void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDat // Just make sure we didn't screw up any of the now obsolete methods or fields. We need their // declaring-class to still be the obolete class orig->VisitMethods([&](art::ArtMethod* method) REQUIRES_SHARED(art::Locks::mutator_lock_) { - if (method->IsCopied()) { - // Copied methods have interfaces as their declaring class. - return; - } DCHECK_EQ(method->GetDeclaringClass(), orig) << method->GetDeclaringClass()->PrettyClass() << " vs " << orig->PrettyClass(); }, art::kRuntimePointerSize); diff --git a/openjdkjvmti/ti_redefine.h b/openjdkjvmti/ti_redefine.h index 36bc9d3dd4..cedce92806 100644 --- a/openjdkjvmti/ti_redefine.h +++ b/openjdkjvmti/ti_redefine.h @@ -52,7 +52,6 @@ #include "obj_ptr.h" namespace art { -class ClassAccessor; namespace dex { struct ClassDef; } // namespace dex @@ -169,15 +168,10 @@ class Redefiner { void FindAndAllocateObsoleteMethods(art::ObjPtr<art::mirror::Class> art_klass) REQUIRES(art::Locks::mutator_lock_); - art::ObjPtr<art::mirror::Class> AllocateNewClassObject( - art::Handle<art::mirror::Class> old_class, - art::Handle<art::mirror::Class> super_class, - art::Handle<art::mirror::DexCache> cache, - uint16_t dex_class_def_index) REQUIRES_SHARED(art::Locks::mutator_lock_); art::ObjPtr<art::mirror::Class> AllocateNewClassObject(art::Handle<art::mirror::DexCache> cache) REQUIRES_SHARED(art::Locks::mutator_lock_); - uint32_t GetNewClassSize(art::ClassAccessor& accessor) + uint32_t GetNewClassSize(bool with_embedded_tables, art::Handle<art::mirror::Class> old_class) REQUIRES_SHARED(art::Locks::mutator_lock_); // Checks that the dex file contains only the single expected class and that the top-level class @@ -323,7 +317,6 @@ class Redefiner { jvmtiError Run() REQUIRES_SHARED(art::Locks::mutator_lock_); bool CheckAllRedefinitionAreValid() REQUIRES_SHARED(art::Locks::mutator_lock_); - bool CheckClassHierarchy() REQUIRES_SHARED(art::Locks::mutator_lock_); bool CheckAllClassesAreVerified(RedefinitionDataHolder& holder) REQUIRES_SHARED(art::Locks::mutator_lock_); bool EnsureAllClassAllocationsFinished(RedefinitionDataHolder& holder) diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index a0a2365408..3f7c9b1f3f 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -3367,57 +3367,12 @@ static bool IsReservedBootClassPathDescriptor(const char* descriptor) { StartsWith(descriptor_sv, "Landroid/media/"); } -// Helper for maintaining DefineClass counting. We need to notify callbacks when we start/end a -// define-class and how many recursive DefineClasses we are at in order to allow for doing things -// like pausing class definition. -struct ScopedDefiningClass { - public: - explicit ScopedDefiningClass(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) - : self_(self), returned_(false) { - Locks::mutator_lock_->AssertSharedHeld(self_); - Runtime::Current()->GetRuntimeCallbacks()->BeginDefineClass(); - self_->IncrDefineClassCount(); - } - ~ScopedDefiningClass() REQUIRES_SHARED(Locks::mutator_lock_) { - Locks::mutator_lock_->AssertSharedHeld(self_); - CHECK(returned_); - } - - ObjPtr<mirror::Class> Finish(Handle<mirror::Class> h_klass) - REQUIRES_SHARED(Locks::mutator_lock_) { - CHECK(!returned_); - self_->DecrDefineClassCount(); - Runtime::Current()->GetRuntimeCallbacks()->EndDefineClass(); - Thread::PoisonObjectPointersIfDebug(); - returned_ = true; - return h_klass.Get(); - } - - ObjPtr<mirror::Class> Finish(ObjPtr<mirror::Class> klass) - REQUIRES_SHARED(Locks::mutator_lock_) { - StackHandleScope<1> hs(self_); - Handle<mirror::Class> h_klass(hs.NewHandle(klass)); - return Finish(h_klass); - } - - ObjPtr<mirror::Class> Finish(nullptr_t np ATTRIBUTE_UNUSED) - REQUIRES_SHARED(Locks::mutator_lock_) { - ScopedNullHandle<mirror::Class> snh; - return Finish(snh); - } - - private: - Thread* self_; - bool returned_; -}; - ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, const char* descriptor, size_t hash, Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file, const dex::ClassDef& dex_class_def) { - ScopedDefiningClass sdc(self); StackHandleScope<3> hs(self); auto klass = hs.NewHandle<mirror::Class>(nullptr); @@ -3448,7 +3403,7 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, ObjPtr<mirror::Throwable> pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError(); self->SetException(pre_allocated); - return sdc.Finish(nullptr); + return nullptr; } // This is to prevent the calls to ClassLoad and ClassPrepare which can cause java/user-supplied @@ -3459,7 +3414,7 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, ObjPtr<mirror::Throwable> pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError(); self->SetException(pre_allocated); - return sdc.Finish(nullptr); + return nullptr; } if (klass == nullptr) { @@ -3470,12 +3425,12 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, if (CanAllocClass()) { klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def))); } else { - return sdc.Finish(nullptr); + return nullptr; } } if (UNLIKELY(klass == nullptr)) { self->AssertPendingOOMException(); - return sdc.Finish(nullptr); + return nullptr; } // Get the real dex file. This will return the input if there aren't any callbacks or they do // nothing. @@ -3492,12 +3447,12 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, &new_class_def); // Check to see if an exception happened during runtime callbacks. Return if so. if (self->IsExceptionPending()) { - return sdc.Finish(nullptr); + return nullptr; } ObjPtr<mirror::DexCache> dex_cache = RegisterDexFile(*new_dex_file, class_loader.Get()); if (dex_cache == nullptr) { self->AssertPendingException(); - return sdc.Finish(nullptr); + return nullptr; } klass->SetDexCache(dex_cache); SetupClass(*new_dex_file, *new_class_def, klass, class_loader.Get()); @@ -3519,7 +3474,7 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, if (existing != nullptr) { // We failed to insert because we raced with another thread. Calling EnsureResolved may cause // this thread to block. - return sdc.Finish(EnsureResolved(self, descriptor, existing)); + return EnsureResolved(self, descriptor, existing); } // Load the fields and other things after we are inserted in the table. This is so that we don't @@ -3534,7 +3489,7 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, if (!klass->IsErroneous()) { mirror::Class::SetStatus(klass, ClassStatus::kErrorUnresolved, self); } - return sdc.Finish(nullptr); + return nullptr; } // Finish loading (if necessary) by finding parents @@ -3544,7 +3499,7 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, if (!klass->IsErroneous()) { mirror::Class::SetStatus(klass, ClassStatus::kErrorUnresolved, self); } - return sdc.Finish(nullptr); + return nullptr; } CHECK(klass->IsLoaded()); @@ -3563,7 +3518,7 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, if (!klass->IsErroneous()) { mirror::Class::SetStatus(klass, ClassStatus::kErrorUnresolved, self); } - return sdc.Finish(nullptr); + return nullptr; } self->AssertNoPendingException(); CHECK(h_new_class != nullptr) << descriptor; @@ -3597,7 +3552,7 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, // Notify native debugger of the new class and its layout. jit::Jit::NewTypeLoadedIfUsingJit(h_new_class.Get()); - return sdc.Finish(h_new_class); + return h_new_class.Get(); } uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file, diff --git a/runtime/class_linker.h b/runtime/class_linker.h index fc954da1be..49e14300c7 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -1441,10 +1441,6 @@ class ClassLoadCallback { public: virtual ~ClassLoadCallback() {} - // Called immediately before beginning class-definition and immediately before returning from it. - virtual void BeginDefineClass() REQUIRES_SHARED(Locks::mutator_lock_) {} - virtual void EndDefineClass() REQUIRES_SHARED(Locks::mutator_lock_) {} - // If set we will replace initial_class_def & initial_dex_file with the final versions. The // callback author is responsible for ensuring these are allocated in such a way they can be // cleaned up if another transformation occurs. Note that both must be set or null/unchanged on diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index c67b1b0791..cc1a7f88e5 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -358,8 +358,7 @@ inline ArtField* FindFieldFromCode(uint32_t field_idx, DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return nullptr; // Failure. } - if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class) && - !referring_class->IsObsoleteVersionOf(fields_class))) { + if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) { ThrowIllegalAccessErrorFinalField(referrer, resolved_field); return nullptr; // Failure. } else { diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 79d767d9f1..db5cbce647 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -550,22 +550,6 @@ inline bool Class::CheckResolvedMethodAccess(ObjPtr<Class> access_to, access_to, method, dex_cache, method_idx, throw_invoke_type); } -inline bool Class::IsObsoleteVersionOf(ObjPtr<Class> klass) { - DCHECK(!klass->IsObsoleteObject()) << klass->PrettyClass() << " is obsolete!"; - if (LIKELY(!IsObsoleteObject())) { - return false; - } - ObjPtr<Class> current(klass); - do { - if (UNLIKELY(current == this)) { - return true; - } else { - current = current->GetObsoleteClass(); - } - } while (!current.IsNull()); - return false; -} - inline bool Class::IsSubClass(ObjPtr<Class> klass) { // Since the SubtypeCheck::IsSubtypeOf needs to lookup the Depth, // it is always O(Depth) in terms of speed to do the check. diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index e57cc982a3..b7429ddb4b 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -188,57 +188,28 @@ ObjPtr<ClassExt> Class::EnsureExtDataPresent(Handle<Class> h_this, Thread* self) } } -template <typename T> -static void CheckSetStatus(Thread* self, T thiz, ClassStatus new_status, ClassStatus old_status) - REQUIRES_SHARED(Locks::mutator_lock_) { - if (UNLIKELY(new_status <= old_status && new_status != ClassStatus::kErrorUnresolved && - new_status != ClassStatus::kErrorResolved && new_status != ClassStatus::kRetired)) { - LOG(FATAL) << "Unexpected change back of class status for " << thiz->PrettyClass() << " " - << old_status << " -> " << new_status; - } - if (old_status == ClassStatus::kInitialized) { - // We do not hold the lock for making the class visibly initialized - // as this is unnecessary and could lead to deadlocks. - CHECK_EQ(new_status, ClassStatus::kVisiblyInitialized); - } else if ((new_status >= ClassStatus::kResolved || old_status >= ClassStatus::kResolved) && - !Locks::mutator_lock_->IsExclusiveHeld(self)) { - // When classes are being resolved the resolution code should hold the - // lock or have everything else suspended - CHECK_EQ(thiz->GetLockOwnerThreadId(), self->GetThreadId()) - << "Attempt to change status of class while not holding its lock: " << thiz->PrettyClass() - << " " << old_status << " -> " << new_status; - } - if (UNLIKELY(Locks::mutator_lock_->IsExclusiveHeld(self))) { - CHECK(!Class::IsErroneous(new_status)) - << "status " << new_status - << " cannot be set while suspend-all is active. Would require allocations."; - CHECK(thiz->IsResolved()) - << thiz->PrettyClass() - << " not resolved during suspend-all status change. Waiters might be missed!"; - } -} - -void Class::SetStatusLocked(ClassStatus new_status) { - ClassStatus old_status = GetStatus(); - CheckSetStatus(Thread::Current(), this, new_status, old_status); - if (kBitstringSubtypeCheckEnabled) { - // FIXME: This looks broken with respect to aborted transactions. - SubtypeCheck<ObjPtr<mirror::Class>>::WriteStatus(this, new_status); - } else { - // The ClassStatus is always in the 4 most-significant bits of status_. - static_assert(sizeof(status_) == sizeof(uint32_t), "Size of status_ not equal to uint32"); - uint32_t new_status_value = static_cast<uint32_t>(new_status) << (32 - kClassStatusBitSize); - DCHECK(!Runtime::Current()->IsActiveTransaction()); - SetField32Volatile<false>(StatusOffset(), new_status_value); - } -} - void Class::SetStatus(Handle<Class> h_this, ClassStatus new_status, Thread* self) { ClassStatus old_status = h_this->GetStatus(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); bool class_linker_initialized = class_linker != nullptr && class_linker->IsInitialized(); if (LIKELY(class_linker_initialized)) { - CheckSetStatus(self, h_this, new_status, old_status); + if (UNLIKELY(new_status <= old_status && + new_status != ClassStatus::kErrorUnresolved && + new_status != ClassStatus::kErrorResolved && + new_status != ClassStatus::kRetired)) { + LOG(FATAL) << "Unexpected change back of class status for " << h_this->PrettyClass() + << " " << old_status << " -> " << new_status; + } + if (old_status == ClassStatus::kInitialized) { + // We do not hold the lock for making the class visibly initialized + // as this is unnecessary and could lead to deadlocks. + CHECK_EQ(new_status, ClassStatus::kVisiblyInitialized); + } else if (new_status >= ClassStatus::kResolved || old_status >= ClassStatus::kResolved) { + // When classes are being resolved the resolution code should hold the lock. + CHECK_EQ(h_this->GetLockOwnerThreadId(), self->GetThreadId()) + << "Attempt to change status of class while not holding its lock: " + << h_this->PrettyClass() << " " << old_status << " -> " << new_status; + } } if (UNLIKELY(IsErroneous(new_status))) { CHECK(!h_this->IsErroneous()) @@ -365,15 +336,6 @@ void Class::SetClassSize(uint32_t new_class_size) { SetField32Transaction(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size); } -ObjPtr<Class> Class::GetObsoleteClass() { - ObjPtr<ClassExt> ext(GetExtData()); - if (ext.IsNull()) { - return nullptr; - } else { - return ext->GetObsoleteClass(); - } -} - // Return the class' name. The exact format is bizarre, but it's the specified behavior for // Class.getName: keywords for primitive types, regular "[I" form for primitive arrays (so "int" // but "[I"), and arrays of reference types written between "L" and ";" but with dots rather than diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index f5c2614908..a8b8235ee3 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -105,10 +105,6 @@ class MANAGED Class final : public Object { static void SetStatus(Handle<Class> h_this, ClassStatus new_status, Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); - // Used for structural redefinition to directly set the class-status while - // holding a strong mutator-lock. - void SetStatusLocked(ClassStatus new_status) REQUIRES(Locks::mutator_lock_); - void SetStatusForPrimitiveOrArray(ClassStatus new_status) REQUIRES_SHARED(Locks::mutator_lock_); static constexpr MemberOffset StatusOffset() { @@ -621,11 +617,6 @@ class MANAGED Class final : public Object { // to themselves. Classes for primitive types may not assign to each other. ALWAYS_INLINE bool IsAssignableFrom(ObjPtr<Class> src) REQUIRES_SHARED(Locks::mutator_lock_); - // Checks if 'klass' is a redefined version of this. - bool IsObsoleteVersionOf(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); - - ObjPtr<Class> GetObsoleteClass() REQUIRES_SHARED(Locks::mutator_lock_); - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, ReadBarrierOption kReadBarrierOption = kWithReadBarrier> ALWAYS_INLINE ObjPtr<Class> GetSuperClass() REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/runtime_callbacks.cc b/runtime/runtime_callbacks.cc index e0f57c013d..ac73364ff0 100644 --- a/runtime/runtime_callbacks.cc +++ b/runtime/runtime_callbacks.cc @@ -228,19 +228,6 @@ void RuntimeCallbacks::ClassLoad(Handle<mirror::Class> klass) { } } -void RuntimeCallbacks::EndDefineClass() { - for (ClassLoadCallback* cb : COPY(class_callbacks_)) { - cb->EndDefineClass(); - } -} - -void RuntimeCallbacks::BeginDefineClass() { - for (ClassLoadCallback* cb : COPY(class_callbacks_)) { - cb->BeginDefineClass(); - } -} - - void RuntimeCallbacks::ClassPreDefine(const char* descriptor, Handle<mirror::Class> temp_class, Handle<mirror::ClassLoader> loader, diff --git a/runtime/runtime_callbacks.h b/runtime/runtime_callbacks.h index 3cadd974e1..7111ba0085 100644 --- a/runtime/runtime_callbacks.h +++ b/runtime/runtime_callbacks.h @@ -181,8 +181,6 @@ class RuntimeCallbacks { void AddClassLoadCallback(ClassLoadCallback* cb) REQUIRES(Locks::mutator_lock_); void RemoveClassLoadCallback(ClassLoadCallback* cb) REQUIRES(Locks::mutator_lock_); - void BeginDefineClass() REQUIRES_SHARED(Locks::mutator_lock_); - void EndDefineClass() REQUIRES_SHARED(Locks::mutator_lock_); void ClassLoad(Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); void ClassPrepare(Handle<mirror::Class> temp_klass, Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/thread.h b/runtime/thread.h index 09e88107bd..29375e51f4 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -263,17 +263,6 @@ class Thread { (state_and_flags.as_struct.flags & kSuspendRequest) != 0; } - void DecrDefineClassCount() { - tls32_.define_class_counter--; - } - - void IncrDefineClassCount() { - tls32_.define_class_counter++; - } - uint32_t GetDefineClassCount() const { - return tls32_.define_class_counter; - } - // If delta > 0 and (this != self or suspend_barrier is not null), this function may temporarily // release thread_suspend_count_lock_ internally. ALWAYS_INLINE @@ -1561,8 +1550,7 @@ class Thread { user_code_suspend_count(0), force_interpreter_count(0), use_mterp(0), - make_visibly_initialized_counter(0), - define_class_counter(0) {} + make_visibly_initialized_counter(0) {} union StateAndFlags state_and_flags; static_assert(sizeof(union StateAndFlags) == sizeof(int32_t), @@ -1660,10 +1648,6 @@ class Thread { // initialized but not visibly initialized for a long time even if no more classes are // being initialized anymore. uint32_t make_visibly_initialized_counter; - - // Counter for how many nested define-classes are ongoing in this thread. Used to allow waiting - // for threads to be done with class-definition work. - uint32_t define_class_counter; } tls32_; struct PACKED(8) tls_64bit_sized_values { diff --git a/test/1983-structural-redefinition-failures/expected.txt b/test/1983-structural-redefinition-failures/expected.txt index 222aac45d5..40a0914278 100644 --- a/test/1983-structural-redefinition-failures/expected.txt +++ b/test/1983-structural-redefinition-failures/expected.txt @@ -24,13 +24,13 @@ Is Structurally modifiable class java.lang.Throwable false Is Structurally modifiable class java.lang.invoke.VarHandle false Is Structurally modifiable class java.lang.invoke.FieldVarHandle false Checking non-mirror'd classes -Is Structurally modifiable class java.util.ArrayList true +Is Structurally modifiable class java.util.ArrayList false Is Structurally modifiable class java.util.Objects true Is Structurally modifiable class java.util.Arrays true Is Structurally modifiable class [Ljava.lang.Object; false Is Structurally modifiable class java.lang.Integer true -Is Structurally modifiable class java.lang.Number true +Is Structurally modifiable class java.lang.Number false Is Structurally modifiable class art.Test1983$NoVirtuals true -Is Structurally modifiable class art.Test1983$WithVirtuals true -Is Structurally modifiable class art.Test1983$SubWithVirtuals true +Is Structurally modifiable class art.Test1983$WithVirtuals false +Is Structurally modifiable class art.Test1983$SubWithVirtuals false Is Structurally modifiable class java.lang.invoke.MethodHandles true diff --git a/test/1993-fallback-non-structural/expected.txt b/test/1993-fallback-non-structural/expected.txt index f523e706b2..7e2cdf4ee5 100644 --- a/test/1993-fallback-non-structural/expected.txt +++ b/test/1993-fallback-non-structural/expected.txt @@ -1,3 +1,3 @@ -Can structurally Redefine: true +Can structurally Redefine: false hello Goodbye diff --git a/test/1993-fallback-non-structural/src/art/Test1993.java b/test/1993-fallback-non-structural/src/art/Test1993.java index e2a8f6e8e6..f4420993f7 100644 --- a/test/1993-fallback-non-structural/src/art/Test1993.java +++ b/test/1993-fallback-non-structural/src/art/Test1993.java @@ -17,7 +17,6 @@ package art; import java.util.Base64; -import java.lang.reflect.*; public class Test1993 { static class Transform { @@ -62,25 +61,17 @@ public class Test1993 { "AAAASAEAAAMgAAACAAAAgAEAAAEQAAABAAAAjAEAAAIgAAAVAAAAkgEAAAQgAAACAAAALAMAAAAg" + "AAABAAAAOwMAAAMQAAACAAAATAMAAAYgAAABAAAAXAMAAAAQAAABAAAAbAMAAA=="); - public static void run() throws Exception { + public static void run() { Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE); doTest(new Transform()); } - public static void doTest(Transform t) throws Exception { + public static void doTest(Transform t) { + // TODO Remove this once the class is structurally modifiable. System.out.println("Can structurally Redefine: " + Redefinition.isStructurallyModifiable(Transform.class)); t.sayHi(); Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); t.sayHi(); - // Check and make sure we didn't structurally redefine by looking for ClassExt.obsoleteClass - Field ext_data_field = Class.class.getDeclaredField("extData"); - ext_data_field.setAccessible(true); - Object ext_data = ext_data_field.get(Transform.class); - Field obsolete_class_field = ext_data.getClass().getDeclaredField("obsoleteClass"); - obsolete_class_field.setAccessible(true); - if (obsolete_class_field.get(ext_data) != null) { - System.out.println("Expected no ClassExt.obsoleteClass but got " + obsolete_class_field.get(ext_data)); - } } } diff --git a/test/1999-virtual-structural/expected.txt b/test/1999-virtual-structural/expected.txt deleted file mode 100644 index 335b5d73d9..0000000000 --- a/test/1999-virtual-structural/expected.txt +++ /dev/null @@ -1,4 +0,0 @@ -Hi(SubTransform called 1 times) -Hi(SubTransform called 2 times) -Hi(SubTransform called 3 times) -Hello (Transform called 1 times)(SubTransform called 4 times) diff --git a/test/1999-virtual-structural/info.txt b/test/1999-virtual-structural/info.txt deleted file mode 100644 index 606c984f7a..0000000000 --- a/test/1999-virtual-structural/info.txt +++ /dev/null @@ -1,3 +0,0 @@ -Tests basic functions in the jvmti plugin. - -Tests that using the structural redefinition can add new virtual methods and fields. diff --git a/test/1999-virtual-structural/run b/test/1999-virtual-structural/run deleted file mode 100755 index 0d416328d4..0000000000 --- a/test/1999-virtual-structural/run +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -# -# Copyright 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. - -# TODO(b/144168550) This test uses access patterns that can be replaced by -# invoke-virtual-quick during dex2dex compilation. This breaks the test since the -# -quick opcode encodes the exact byte offset of vtable methods. Since this test -# changes the offset this causes problems. -./default-run "$@" --jvmti --runtime-option -Xopaque-jni-ids:true -Xcompiler-option --debuggable diff --git a/test/1999-virtual-structural/src/Main.java b/test/1999-virtual-structural/src/Main.java deleted file mode 100644 index 86a492bcb6..0000000000 --- a/test/1999-virtual-structural/src/Main.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -public class Main { - public static void main(String[] args) throws Exception { - art.Test1999.run(); - } -} diff --git a/test/1999-virtual-structural/src/art/Redefinition.java b/test/1999-virtual-structural/src/art/Redefinition.java deleted file mode 120000 index 81eaf31bbb..0000000000 --- a/test/1999-virtual-structural/src/art/Redefinition.java +++ /dev/null @@ -1 +0,0 @@ -../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/1999-virtual-structural/src/art/Test1999.java b/test/1999-virtual-structural/src/art/Test1999.java deleted file mode 100644 index f6811a90cd..0000000000 --- a/test/1999-virtual-structural/src/art/Test1999.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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. - */ - -package art; - -import java.util.Base64; -public class Test1999 { - - public static class Transform { - public String getGreeting() { - return "Hi"; - } - } - - public static class SubTransform extends Transform { - private int count = 0; - public void sayHi() { - System.out.println(getGreeting() + "(SubTransform called " + (++count) + " times)"); - } - } - - /** - * base64 encoded class/dex file for - * public static class Transform { - * private int count; - * public String getGreeting() { - * return "Hello (Transform called " + incrCount() + " times)"; - * } - * protected int incrCount() { - * return ++count; - * } - * } - */ - private static final byte[] DEX_BYTES = Base64.getDecoder().decode( -"ZGV4CjAzNQAwwbMpPdPdWkU+6UJnvqa7v4VBdcuq2vkMBQAAcAAAAHhWNBIAAAAAAAAAAEgEAAAa" + -"AAAAcAAAAAkAAADYAAAABQAAAPwAAAABAAAAOAEAAAgAAABAAQAAAQAAAIABAABsAwAAoAEAADoC" + -"AABDAgAASwIAAGUCAABoAgAAawIAAG8CAABzAgAAjQIAAJ0CAADBAgAA4QIAAPUCAAAJAwAAJAMA" + -"ADMDAAA+AwAAQQMAAE4DAABWAwAAXQMAAGoDAAB1AwAAewMAAIUDAACMAwAAAwAAAAcAAAAIAAAA" + -"CQAAAAoAAAALAAAADAAAAA0AAAAQAAAAAwAAAAAAAAAAAAAABAAAAAYAAAAAAAAABQAAAAcAAAAs" + -"AgAABgAAAAcAAAA0AgAAEAAAAAgAAAAAAAAAAQAAABMAAAABAAQAAQAAAAEAAQAUAAAAAQAAABUA" + -"AAAFAAQAAQAAAAcABAABAAAABwACABIAAAAHAAMAEgAAAAcAAQAXAAAAAQAAAAEAAAAFAAAAAAAA" + -"AA4AAAA4BAAAEwQAAAAAAAACAAEAAAAAACgCAAAHAAAAUhAAANgAAAFZEAAADwAAAAQAAQACAAAA" + -"JAIAABsAAABuEAIAAwAKACIBBwBwEAQAAQAaAgIAbiAGACEAbiAFAAEAGgAAAG4gBgABAG4QBwAB" + -"AAwAEQAAAAEAAQABAAAAIAIAAAQAAABwEAMAAAAOAAMADgAGAA4ACQAOAAEAAAAAAAAAAQAAAAYA" + -"ByB0aW1lcykABjxpbml0PgAYSGVsbG8gKFRyYW5zZm9ybSBjYWxsZWQgAAFJAAFMAAJMSQACTEwA" + -"GExhcnQvVGVzdDE5OTkkVHJhbnNmb3JtOwAOTGFydC9UZXN0MTk5OTsAIkxkYWx2aWsvYW5ub3Rh" + -"dGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwASTGph" + -"dmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAGUxqYXZhL2xhbmcvU3RyaW5nQnVp" + -"bGRlcjsADVRlc3QxOTk5LmphdmEACVRyYW5zZm9ybQABVgALYWNjZXNzRmxhZ3MABmFwcGVuZAAF" + -"Y291bnQAC2dldEdyZWV0aW5nAAlpbmNyQ291bnQABG5hbWUACHRvU3RyaW5nAAV2YWx1ZQB2fn5E" + -"OHsiY29tcGlsYXRpb24tbW9kZSI6ImRlYnVnIiwibWluLWFwaSI6MSwic2hhLTEiOiI2MGRhNGQ2" + -"N2IzODFjNDI0Njc3NTdjNDlmYjZlNTU3NTZkODhhMmYzIiwidmVyc2lvbiI6IjEuNy4xMi1kZXYi" + -"fQACAwEYGAICBAIRBAkWFw8AAQECAAIAgYAEiAQBAcADAQSgAwAAAAAAAgAAAAQEAAAKBAAALAQA" + -"AAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAAAAAAABAAAAGgAAAHAAAAACAAAACQAAANgAAAADAAAA" + -"BQAAAPwAAAAEAAAAAQAAADgBAAAFAAAACAAAAEABAAAGAAAAAQAAAIABAAABIAAAAwAAAKABAAAD" + -"IAAAAwAAACACAAABEAAAAgAAACwCAAACIAAAGgAAADoCAAAEIAAAAgAAAAQEAAAAIAAAAQAAABME" + -"AAADEAAAAgAAACgEAAAGIAAAAQAAADgEAAAAEAAAAQAAAEgEAAA="); - - - public static void run() { - Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE); - doTest(new SubTransform()); - } - - public static void doTest(SubTransform t) { - t.sayHi(); - t.sayHi(); - t.sayHi(); - Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); - t.sayHi(); - } -} diff --git a/test/2000-virtual-list-structural/AbstractCollection.patch b/test/2000-virtual-list-structural/AbstractCollection.patch deleted file mode 100644 index 7507c7d862..0000000000 --- a/test/2000-virtual-list-structural/AbstractCollection.patch +++ /dev/null @@ -1,16 +0,0 @@ ---- ../../../libcore/ojluni/src/main/java/java/util/AbstractCollection.java 2019-05-31 10:36:26.634361294 -0700 -+++ src-ex/java/util/AbstractCollection.java 2019-11-18 13:04:48.253575013 -0800 -@@ -63,7 +63,13 @@ - * Sole constructor. (For invocation by subclass constructors, typically - * implicit.) - */ -+ public static volatile int TOTAL_COUNT; -+ public int cnt; -+ - protected AbstractCollection() { -+ synchronized (Collection.class) { -+ cnt = ++TOTAL_COUNT; -+ } - } - - // Query Operations diff --git a/test/2000-virtual-list-structural/build b/test/2000-virtual-list-structural/build deleted file mode 100755 index 87d6acc2f5..0000000000 --- a/test/2000-virtual-list-structural/build +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 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. - -# Stop on failure. -set -e - -# Deref the symlink. -mv src-ex/java/util/AbstractCollection.java src-ex/java/util/AbstractCollection.bak -cp src-ex/java/util/AbstractCollection.bak src-ex/java/util/AbstractCollection.java - -# Patch the copied version. -patch src-ex/java/util/AbstractCollection.java AbstractCollection.patch - -DESUGAR=false ./default-build "$@" - -# restore the symlink -rm src-ex/java/util/AbstractCollection.java -mv src-ex/java/util/AbstractCollection.bak src-ex/java/util/AbstractCollection.java diff --git a/test/2000-virtual-list-structural/expected.txt b/test/2000-virtual-list-structural/expected.txt deleted file mode 100644 index 9d3e1b6a4a..0000000000 --- a/test/2000-virtual-list-structural/expected.txt +++ /dev/null @@ -1,5 +0,0 @@ -List is: [a, b, c, d] -List is: [1, 2, 3, 4] -List is: [1, 2, 3, 4, xyz: 0, xyz: 1, xyz: 2, xyz: 3, xyz: 4, xyz: 5, xyz: 6, xyz: 7, xyz: 8, xyz: 9, xyz: 10, xyz: 11, xyz: 12, xyz: 13, xyz: 14, xyz: 15, xyz: 16, xyz: 17, xyz: 18, xyz: 19, xyz: 20, xyz: 21, xyz: 22, xyz: 23, xyz: 24, xyz: 25, xyz: 26, xyz: 27, xyz: 28, xyz: 29, xyz: 30, xyz: 31, xyz: 32, xyz: 33, xyz: 34, xyz: 35, xyz: 36, xyz: 37, xyz: 38, xyz: 39, xyz: 40, xyz: 41, xyz: 42, xyz: 43, xyz: 44, xyz: 45, xyz: 46, xyz: 47, xyz: 48, xyz: 49, xyz: 50, xyz: 51, xyz: 52, xyz: 53, xyz: 54, xyz: 55, xyz: 56, xyz: 57, xyz: 58, xyz: 59, xyz: 60, xyz: 61, xyz: 62, xyz: 63, xyz: 64, xyz: 65, xyz: 66, xyz: 67, xyz: 68, xyz: 69, xyz: 70, xyz: 71, xyz: 72, xyz: 73, xyz: 74, xyz: 75, xyz: 76, xyz: 77, xyz: 78, xyz: 79, xyz: 80, xyz: 81, xyz: 82, xyz: 83, xyz: 84, xyz: 85, xyz: 86, xyz: 87, xyz: 88, xyz: 89, xyz: 90, xyz: 91, xyz: 92, xyz: 93, xyz: 94, xyz: 95, xyz: 96, xyz: 97, xyz: 98, xyz: 99, xyz: 100, xyz: 101, xyz: 102, xyz: 103, xyz: 104, xyz: 105, xyz: 106, xyz: 107, xyz: 108, xyz: 109, xyz: 110, xyz: 111, xyz: 112, xyz: 113, xyz: 114, xyz: 115, xyz: 116, xyz: 117, xyz: 118, xyz: 119, xyz: 120, xyz: 121, xyz: 122, xyz: 123, xyz: 124, xyz: 125, xyz: 126, xyz: 127, xyz: 128, xyz: 129, xyz: 130, xyz: 131, xyz: 132, xyz: 133, xyz: 134, xyz: 135, xyz: 136, xyz: 137, xyz: 138, xyz: 139, xyz: 140, xyz: 141, xyz: 142, xyz: 143, xyz: 144, xyz: 145, xyz: 146, xyz: 147, xyz: 148, xyz: 149, xyz: 150, xyz: 151, xyz: 152, xyz: 153, xyz: 154, xyz: 155, xyz: 156, xyz: 157, xyz: 158, xyz: 159, xyz: 160, xyz: 161, xyz: 162, xyz: 163, xyz: 164, xyz: 165, xyz: 166, xyz: 167, xyz: 168, xyz: 169, xyz: 170, xyz: 171, xyz: 172, xyz: 173, xyz: 174, xyz: 175, xyz: 176, xyz: 177, xyz: 178, xyz: 179, xyz: 180, xyz: 181, xyz: 182, xyz: 183, xyz: 184, xyz: 185, xyz: 186, xyz: 187, xyz: 188, xyz: 189, xyz: 190, xyz: 191, xyz: 192, xyz: 193, xyz: 194, xyz: 195, xyz: 196, xyz: 197, xyz: 198, xyz: 199, xyz: 200, xyz: 201, xyz: 202, xyz: 203, xyz: 204, xyz: 205, xyz: 206, xyz: 207, xyz: 208, xyz: 209, xyz: 210, xyz: 211, xyz: 212, xyz: 213, xyz: 214, xyz: 215, xyz: 216, xyz: 217, xyz: 218, xyz: 219, xyz: 220, xyz: 221, xyz: 222, xyz: 223, xyz: 224, xyz: 225, xyz: 226, xyz: 227, xyz: 228, xyz: 229, xyz: 230, xyz: 231, xyz: 232, xyz: 233, xyz: 234, xyz: 235, xyz: 236, xyz: 237, xyz: 238, xyz: 239, xyz: 240, xyz: 241, xyz: 242, xyz: 243, xyz: 244, xyz: 245, xyz: 246, xyz: 247, xyz: 248, xyz: 249, xyz: 250, xyz: 251, xyz: 252, xyz: 253, xyz: 254, xyz: 255, xyz: 256, xyz: 257, xyz: 258, xyz: 259, xyz: 260, xyz: 261, xyz: 262, xyz: 263, xyz: 264, xyz: 265, xyz: 266, xyz: 267, xyz: 268, xyz: 269, xyz: 270, xyz: 271, xyz: 272, xyz: 273, xyz: 274, xyz: 275, xyz: 276, xyz: 277, xyz: 278, xyz: 279, xyz: 280, xyz: 281, xyz: 282, xyz: 283, xyz: 284, xyz: 285, xyz: 286, xyz: 287, xyz: 288, xyz: 289, xyz: 290, xyz: 291, xyz: 292, xyz: 293, xyz: 294, xyz: 295, xyz: 296, xyz: 297, xyz: 298, xyz: 299, xyz: 300, xyz: 301, xyz: 302, xyz: 303, xyz: 304, xyz: 305, xyz: 306, xyz: 307, xyz: 308, xyz: 309, xyz: 310, xyz: 311, xyz: 312, xyz: 313, xyz: 314, xyz: 315, xyz: 316, xyz: 317, xyz: 318, xyz: 319, xyz: 320, xyz: 321, xyz: 322, xyz: 323, xyz: 324, xyz: 325, xyz: 326, xyz: 327, xyz: 328, xyz: 329, xyz: 330, xyz: 331, xyz: 332, xyz: 333, xyz: 334, xyz: 335, xyz: 336, xyz: 337, xyz: 338, xyz: 339, xyz: 340, xyz: 341, xyz: 342, xyz: 343, xyz: 344, xyz: 345, xyz: 346, xyz: 347, xyz: 348, xyz: 349, xyz: 350, xyz: 351, xyz: 352, xyz: 353, xyz: 354, xyz: 355, xyz: 356, xyz: 357, xyz: 358, xyz: 359, xyz: 360, xyz: 361, xyz: 362, xyz: 363, xyz: 364, xyz: 365, xyz: 366, xyz: 367, xyz: 368, xyz: 369, xyz: 370, xyz: 371, xyz: 372, xyz: 373, xyz: 374, xyz: 375, xyz: 376, xyz: 377, xyz: 378, xyz: 379, xyz: 380, xyz: 381, xyz: 382, xyz: 383, xyz: 384, xyz: 385, xyz: 386, xyz: 387, xyz: 388, xyz: 389, xyz: 390, xyz: 391, xyz: 392, xyz: 393, xyz: 394, xyz: 395, xyz: 396, xyz: 397, xyz: 398, xyz: 399, xyz: 400, xyz: 401, xyz: 402, xyz: 403, xyz: 404, xyz: 405, xyz: 406, xyz: 407, xyz: 408, xyz: 409, xyz: 410, xyz: 411, xyz: 412, xyz: 413, xyz: 414, xyz: 415, xyz: 416, xyz: 417, xyz: 418, xyz: 419, xyz: 420, xyz: 421, xyz: 422, xyz: 423, xyz: 424, xyz: 425, xyz: 426, xyz: 427, xyz: 428, xyz: 429, xyz: 430, xyz: 431, xyz: 432, xyz: 433, xyz: 434, xyz: 435, xyz: 436, xyz: 437, xyz: 438, xyz: 439, xyz: 440, xyz: 441, xyz: 442, xyz: 443, xyz: 444, xyz: 445, xyz: 446, xyz: 447, xyz: 448, xyz: 449, xyz: 450, xyz: 451, xyz: 452, xyz: 453, xyz: 454, xyz: 455, xyz: 456, xyz: 457, xyz: 458, xyz: 459, xyz: 460, xyz: 461, xyz: 462, xyz: 463, xyz: 464, xyz: 465, xyz: 466, xyz: 467, xyz: 468, xyz: 469, xyz: 470, xyz: 471, xyz: 472, xyz: 473, xyz: 474, xyz: 475, xyz: 476, xyz: 477, xyz: 478, xyz: 479, xyz: 480, xyz: 481, xyz: 482, xyz: 483, xyz: 484, xyz: 485, xyz: 486, xyz: 487, xyz: 488, xyz: 489, xyz: 490, xyz: 491, xyz: 492, xyz: 493, xyz: 494, xyz: 495, xyz: 496, xyz: 497, xyz: 498, xyz: 499, xyz: 500, xyz: 501, xyz: 502, xyz: 503, xyz: 504, xyz: 505, xyz: 506, xyz: 507, xyz: 508, xyz: 509, xyz: 510, xyz: 511, xyz: 512, xyz: 513, xyz: 514, xyz: 515, xyz: 516, xyz: 517, xyz: 518, xyz: 519, xyz: 520, xyz: 521, xyz: 522, xyz: 523, xyz: 524, xyz: 525, xyz: 526, xyz: 527, xyz: 528, xyz: 529, xyz: 530, xyz: 531, xyz: 532, xyz: 533, xyz: 534, xyz: 535, xyz: 536, xyz: 537, xyz: 538, xyz: 539, xyz: 540, xyz: 541, xyz: 542, xyz: 543, xyz: 544, xyz: 545, xyz: 546, xyz: 547, xyz: 548, xyz: 549, xyz: 550, xyz: 551, xyz: 552, xyz: 553, xyz: 554, xyz: 555, xyz: 556, xyz: 557, xyz: 558, xyz: 559, xyz: 560, xyz: 561, xyz: 562, xyz: 563, xyz: 564, xyz: 565, xyz: 566, xyz: 567, xyz: 568, xyz: 569, xyz: 570, xyz: 571, xyz: 572, xyz: 573, xyz: 574, xyz: 575, xyz: 576, xyz: 577, xyz: 578, xyz: 579, xyz: 580, xyz: 581, xyz: 582, xyz: 583, xyz: 584, xyz: 585, xyz: 586, xyz: 587, xyz: 588, xyz: 589, xyz: 590, xyz: 591, xyz: 592, xyz: 593, xyz: 594, xyz: 595, xyz: 596, xyz: 597, xyz: 598, xyz: 599, xyz: 600, xyz: 601, xyz: 602, xyz: 603, xyz: 604, xyz: 605, xyz: 606, xyz: 607, xyz: 608, xyz: 609, xyz: 610, xyz: 611, xyz: 612, xyz: 613, xyz: 614, xyz: 615, xyz: 616, xyz: 617, xyz: 618, xyz: 619, xyz: 620, xyz: 621, xyz: 622, xyz: 623, xyz: 624, xyz: 625, xyz: 626, xyz: 627, xyz: 628, xyz: 629, xyz: 630, xyz: 631, xyz: 632, xyz: 633, xyz: 634, xyz: 635, xyz: 636, xyz: 637, xyz: 638, xyz: 639, xyz: 640, xyz: 641, xyz: 642, xyz: 643, xyz: 644, xyz: 645, xyz: 646, xyz: 647, xyz: 648, xyz: 649, xyz: 650, xyz: 651, xyz: 652, xyz: 653, xyz: 654, xyz: 655, xyz: 656, xyz: 657, xyz: 658, xyz: 659, xyz: 660, xyz: 661, xyz: 662, xyz: 663, xyz: 664, xyz: 665, xyz: 666, xyz: 667, xyz: 668, xyz: 669, xyz: 670, xyz: 671, xyz: 672, xyz: 673, xyz: 674, xyz: 675, xyz: 676, xyz: 677, xyz: 678, xyz: 679, xyz: 680, xyz: 681, xyz: 682, xyz: 683, xyz: 684, xyz: 685, xyz: 686, xyz: 687, xyz: 688, xyz: 689, xyz: 690, xyz: 691, xyz: 692, xyz: 693, xyz: 694, xyz: 695, xyz: 696, xyz: 697, xyz: 698, xyz: 699, xyz: 700, xyz: 701, xyz: 702, xyz: 703, xyz: 704, xyz: 705, xyz: 706, xyz: 707, xyz: 708, xyz: 709, xyz: 710, xyz: 711, xyz: 712, xyz: 713, xyz: 714, xyz: 715, xyz: 716, xyz: 717, xyz: 718, xyz: 719, xyz: 720, xyz: 721, xyz: 722, xyz: 723, xyz: 724, xyz: 725, xyz: 726, xyz: 727, xyz: 728, xyz: 729, xyz: 730, xyz: 731, xyz: 732, xyz: 733, xyz: 734, xyz: 735, xyz: 736, xyz: 737, xyz: 738, xyz: 739, xyz: 740, xyz: 741, xyz: 742, xyz: 743, xyz: 744, xyz: 745, xyz: 746, xyz: 747, xyz: 748, xyz: 749, xyz: 750, xyz: 751, xyz: 752, xyz: 753, xyz: 754, xyz: 755, xyz: 756, xyz: 757, xyz: 758, xyz: 759, xyz: 760, xyz: 761, xyz: 762, xyz: 763, xyz: 764, xyz: 765, xyz: 766, xyz: 767, xyz: 768, xyz: 769, xyz: 770, xyz: 771, xyz: 772, xyz: 773, xyz: 774, xyz: 775, xyz: 776, xyz: 777, xyz: 778, xyz: 779, xyz: 780, xyz: 781, xyz: 782, xyz: 783, xyz: 784, xyz: 785, xyz: 786, xyz: 787, xyz: 788, xyz: 789, xyz: 790, xyz: 791, xyz: 792, xyz: 793, xyz: 794, xyz: 795, xyz: 796, xyz: 797, xyz: 798, xyz: 799, xyz: 800, xyz: 801, xyz: 802, xyz: 803, xyz: 804, xyz: 805, xyz: 806, xyz: 807, xyz: 808, xyz: 809, xyz: 810, xyz: 811, xyz: 812, xyz: 813, xyz: 814, xyz: 815, xyz: 816, xyz: 817, xyz: 818, xyz: 819, xyz: 820, xyz: 821, xyz: 822, xyz: 823, xyz: 824, xyz: 825, xyz: 826, xyz: 827, xyz: 828, xyz: 829, xyz: 830, xyz: 831, xyz: 832, xyz: 833, xyz: 834, xyz: 835, xyz: 836, xyz: 837, xyz: 838, xyz: 839, xyz: 840, xyz: 841, xyz: 842, xyz: 843, xyz: 844, xyz: 845, xyz: 846, xyz: 847, xyz: 848, xyz: 849, xyz: 850, xyz: 851, xyz: 852, xyz: 853, xyz: 854, xyz: 855, xyz: 856, xyz: 857, xyz: 858, xyz: 859, xyz: 860, xyz: 861, xyz: 862, xyz: 863, xyz: 864, xyz: 865, xyz: 866, xyz: 867, xyz: 868, xyz: 869, xyz: 870, xyz: 871, xyz: 872, xyz: 873, xyz: 874, xyz: 875, xyz: 876, xyz: 877, xyz: 878, xyz: 879, xyz: 880, xyz: 881, xyz: 882, xyz: 883, xyz: 884, xyz: 885, xyz: 886, xyz: 887, xyz: 888, xyz: 889, xyz: 890, xyz: 891, xyz: 892, xyz: 893, xyz: 894, xyz: 895, xyz: 896, xyz: 897, xyz: 898, xyz: 899, xyz: 900, xyz: 901, xyz: 902, xyz: 903, xyz: 904, xyz: 905, xyz: 906, xyz: 907, xyz: 908, xyz: 909, xyz: 910, xyz: 911, xyz: 912, xyz: 913, xyz: 914, xyz: 915, xyz: 916, xyz: 917, xyz: 918, xyz: 919, xyz: 920, xyz: 921, xyz: 922, xyz: 923, xyz: 924, xyz: 925, xyz: 926, xyz: 927, xyz: 928, xyz: 929, xyz: 930, xyz: 931, xyz: 932, xyz: 933, xyz: 934, xyz: 935, xyz: 936, xyz: 937, xyz: 938, xyz: 939, xyz: 940, xyz: 941, xyz: 942, xyz: 943, xyz: 944, xyz: 945, xyz: 946, xyz: 947, xyz: 948, xyz: 949, xyz: 950, xyz: 951, xyz: 952, xyz: 953, xyz: 954, xyz: 955, xyz: 956, xyz: 957, xyz: 958, xyz: 959, xyz: 960, xyz: 961, xyz: 962, xyz: 963, xyz: 964, xyz: 965, xyz: 966, xyz: 967, xyz: 968, xyz: 969, xyz: 970, xyz: 971, xyz: 972, xyz: 973, xyz: 974, xyz: 975, xyz: 976, xyz: 977, xyz: 978, xyz: 979, xyz: 980, xyz: 981, xyz: 982, xyz: 983, xyz: 984, xyz: 985, xyz: 986, xyz: 987, xyz: 988, xyz: 989, xyz: 990, xyz: 991, xyz: 992, xyz: 993, xyz: 994, xyz: 995, xyz: 996, xyz: 997, xyz: 998, xyz: 999] -List is: [1, 2, 3, 4] -List is: [a, b, c, d] diff --git a/test/2000-virtual-list-structural/info.txt b/test/2000-virtual-list-structural/info.txt deleted file mode 100644 index 606c984f7a..0000000000 --- a/test/2000-virtual-list-structural/info.txt +++ /dev/null @@ -1,3 +0,0 @@ -Tests basic functions in the jvmti plugin. - -Tests that using the structural redefinition can add new virtual methods and fields. diff --git a/test/2000-virtual-list-structural/run b/test/2000-virtual-list-structural/run deleted file mode 100755 index 0d416328d4..0000000000 --- a/test/2000-virtual-list-structural/run +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -# -# Copyright 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. - -# TODO(b/144168550) This test uses access patterns that can be replaced by -# invoke-virtual-quick during dex2dex compilation. This breaks the test since the -# -quick opcode encodes the exact byte offset of vtable methods. Since this test -# changes the offset this causes problems. -./default-run "$@" --jvmti --runtime-option -Xopaque-jni-ids:true -Xcompiler-option --debuggable diff --git a/test/2000-virtual-list-structural/src-ex/java/util/AbstractCollection.java b/test/2000-virtual-list-structural/src-ex/java/util/AbstractCollection.java deleted file mode 120000 index a30fbdc6e0..0000000000 --- a/test/2000-virtual-list-structural/src-ex/java/util/AbstractCollection.java +++ /dev/null @@ -1 +0,0 @@ -../../../../../../libcore/ojluni/src/main/java/java/util/AbstractCollection.java
\ No newline at end of file diff --git a/test/2000-virtual-list-structural/src/Main.java b/test/2000-virtual-list-structural/src/Main.java deleted file mode 100644 index b2a42c2722..0000000000 --- a/test/2000-virtual-list-structural/src/Main.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import art.*; -import java.util.*; -import java.lang.invoke.*; -import java.io.*; -import java.util.zip.*; - -public class Main { - public static final String TEST_NAME = "2000-virtual-list-structural"; - public static final boolean PRINT_COUNT = false; - public static MethodHandles.Lookup lookup = MethodHandles.publicLookup(); - public static MethodHandle getcnt; - public static MethodHandle get_total_cnt; - public static void GetHandles() throws Throwable { - getcnt = lookup.findGetter(AbstractCollection.class, "cnt", Integer.TYPE); - get_total_cnt = lookup.findStaticGetter(AbstractCollection.class, "TOTAL_COUNT", Integer.TYPE); - } - - public static byte[] GetDexBytes() throws Throwable { - String jar_loc = System.getenv("DEX_LOCATION") + "/" + TEST_NAME + "-ex.jar"; - try (ZipFile zip = new ZipFile(new File(jar_loc))) { - ZipEntry entry = zip.getEntry("classes.dex"); - try (InputStream is = zip.getInputStream(entry)) { - byte[] res = new byte[(int)entry.getSize()]; - is.read(res); - return res; - } - } - } - public static void PrintListAndData(AbstractCollection<String> c) throws Throwable { - if (PRINT_COUNT) { - System.out.println("List is: " + c + " count = " + getcnt.invoke(c) + " TOTAL_COUNT = " + get_total_cnt.invoke()); - } else { - System.out.println("List is: " + c); - } - } - public static void main(String[] args) throws Throwable { - AbstractCollection<String> l1 = (AbstractCollection<String>)Arrays.asList("a", "b", "c", "d"); - AbstractCollection<String> l2 = new ArrayList<>(); - l2.add("1"); - l2.add("2"); - l2.add("3"); - l2.add("4"); - Redefinition.doCommonStructuralClassRedefinition(AbstractCollection.class, GetDexBytes()); - GetHandles(); - AbstractCollection<String> l3 = new HashSet<>(l2); - AbstractCollection<String> l4 = new LinkedList<>(l1); - PrintListAndData(l1); - PrintListAndData(l2); - for (int i = 0; i < 1000; i++) { - l2.add("xyz: " + i); - } - PrintListAndData(l2); - PrintListAndData(l3); - PrintListAndData(l4); - CheckLE(getcnt.invoke(l1), get_total_cnt.invoke()); - CheckLE(getcnt.invoke(l2), get_total_cnt.invoke()); - CheckLE(getcnt.invoke(l3), get_total_cnt.invoke()); - CheckLE(getcnt.invoke(l4), get_total_cnt.invoke()); - CheckEQ(getcnt.invoke(l1), 0); - CheckLE(getcnt.invoke(l2), 0); - CheckLE(getcnt.invoke(l1), getcnt.invoke(l2)); - CheckLE(getcnt.invoke(l1), getcnt.invoke(l3)); - CheckLE(getcnt.invoke(l1), getcnt.invoke(l4)); - CheckLE(getcnt.invoke(l2), getcnt.invoke(l3)); - CheckLE(getcnt.invoke(l2), getcnt.invoke(l4)); - CheckLE(getcnt.invoke(l3), getcnt.invoke(l4)); - } - public static void CheckEQ(Object a, int b) { - CheckEQ(((Integer)a).intValue(), b); - } - public static void CheckLE(Object a, Object b) { - CheckLE(((Integer)a).intValue(), ((Integer)b).intValue()); - } - public static void CheckEQ(int a, int b) { - if (a != b) { - throw new Error(a + " is not equal to " + b); - } - } - public static void CheckLE(int a, int b) { - if (!(a <= b)) { - throw new Error(a + " is not less than or equal to " + b); - } - } -} diff --git a/test/2000-virtual-list-structural/src/art/Redefinition.java b/test/2000-virtual-list-structural/src/art/Redefinition.java deleted file mode 120000 index 81eaf31bbb..0000000000 --- a/test/2000-virtual-list-structural/src/art/Redefinition.java +++ /dev/null @@ -1 +0,0 @@ -../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/2001-virtual-structural-multithread/expected.txt b/test/2001-virtual-structural-multithread/expected.txt deleted file mode 100644 index e69de29bb2..0000000000 --- a/test/2001-virtual-structural-multithread/expected.txt +++ /dev/null diff --git a/test/2001-virtual-structural-multithread/info.txt b/test/2001-virtual-structural-multithread/info.txt deleted file mode 100644 index 3e5291df87..0000000000 --- a/test/2001-virtual-structural-multithread/info.txt +++ /dev/null @@ -1,4 +0,0 @@ -Tests structural redefinition with multiple threads. - -Tests that using the structural redefinition while concurrently loading and using a subtype of -the class being redefined doesn't cause any unexpected problems. diff --git a/test/2001-virtual-structural-multithread/run b/test/2001-virtual-structural-multithread/run deleted file mode 100755 index 421f7b0bf2..0000000000 --- a/test/2001-virtual-structural-multithread/run +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -# -# Copyright 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. - -# TODO(b/144168550) This test uses access patterns that can be replaced by -# iget-object-quick during dex2dex compilation. This breaks the test since the -# -quick opcode encodes the exact byte offset of fields. Since this test changes -# the offset this causes problems. -./default-run "$@" --jvmti --runtime-option -Xopaque-jni-ids:true -Xcompiler-option --debuggable diff --git a/test/2001-virtual-structural-multithread/src-art/Main.java b/test/2001-virtual-structural-multithread/src-art/Main.java deleted file mode 100644 index 618cdcdf25..0000000000 --- a/test/2001-virtual-structural-multithread/src-art/Main.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -public class Main { - public static void main(String[] args) throws Exception { - art.Test2001.run(); - } -} diff --git a/test/2001-virtual-structural-multithread/src-art/art/Redefinition.java b/test/2001-virtual-structural-multithread/src-art/art/Redefinition.java deleted file mode 120000 index 81eaf31bbb..0000000000 --- a/test/2001-virtual-structural-multithread/src-art/art/Redefinition.java +++ /dev/null @@ -1 +0,0 @@ -../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/2001-virtual-structural-multithread/src-art/art/Test2001.java b/test/2001-virtual-structural-multithread/src-art/art/Test2001.java deleted file mode 100644 index e6ee0ceaec..0000000000 --- a/test/2001-virtual-structural-multithread/src-art/art/Test2001.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * 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. - */ - -package art; - -import dalvik.system.InMemoryDexClassLoader; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Base64; -import java.util.concurrent.CountDownLatch; -import java.util.function.Supplier; - -public class Test2001 { - private static final int NUM_THREADS = 20; - - public static class Transform { - public String greetingEnglish; - - public Transform() { - this.greetingEnglish = "Hello"; - } - - public String sayHi() { - return greetingEnglish + " from " + Thread.currentThread().getName(); - } - } - - /** - * base64 encoded class/dex file for - * public static class Transform { - * public String greetingEnglish; - * public String greetingFrench; - * public String greetingDanish; - * public String greetingJapanese; - * - * public Transform() { - * this.greetingEnglish = "Hello World"; - * this.greetingFrench = "Bonjour le Monde"; - * this.greetingDanish = "Hej Verden"; - * this.greetingJapanese = "こんにちは世界"; - * } - * public String sayHi() { - * return sayHiEnglish() + ", " + sayHiFrench() + ", " + sayHiDanish() + ", " + sayHiJapanese() + " from " + Thread.currentThread().getName(); - * } - * public String sayHiEnglish() { - * return greetingEnglish; - * } - * public String sayHiDanish() { - * return greetingDanish; - * } - * public String sayHiJapanese() { - * return greetingJapanese; - * } - * public String sayHiFrench() { - * return greetingFrench; - * } - * } - */ - private static final byte[] DEX_BYTES = - Base64.getDecoder() - .decode( - "ZGV4CjAzNQCnKPY06VRa4aM/zFW0MYLmRxT/NtXxD/H4BgAAcAAAAHhWNBIAAAAAAAAAADQGAAAl" - + "AAAAcAAAAAkAAAAEAQAABAAAACgBAAAEAAAAWAEAAAwAAAB4AQAAAQAAANgBAAAABQAA+AEAAEoD" - + "AABSAwAAVgMAAF4DAABwAwAAfAMAAIkDAACMAwAAkAMAAKoDAAC6AwAA3gMAAP4DAAASBAAAJgQA" - + "AEEEAABVBAAAZAQAAG8EAAByBAAAfwQAAIcEAACWBAAAnwQAAK8EAADABAAA0AQAAOIEAADoBAAA" - + "7wQAAPwEAAAKBQAAFwUAACYFAAAwBQAANwUAAMUFAAAIAAAACQAAAAoAAAALAAAADAAAAA0AAAAO" - + "AAAADwAAABIAAAAGAAAABQAAAAAAAAAHAAAABgAAAEQDAAAGAAAABwAAAAAAAAASAAAACAAAAAAA" - + "AAAAAAUAFwAAAAAABQAYAAAAAAAFABkAAAAAAAUAGgAAAAAAAwACAAAAAAAAABwAAAAAAAAAHQAA" - + "AAAAAAAeAAAAAAAAAB8AAAAAAAAAIAAAAAQAAwACAAAABgADAAIAAAAGAAEAFAAAAAYAAAAhAAAA" - + "BwACABUAAAAHAAAAFgAAAAAAAAABAAAABAAAAAAAAAAQAAAAJAYAAOsFAAAAAAAABwABAAIAAAAt" - + "AwAAQQAAAG4QAwAGAAwAbhAEAAYADAFuEAIABgAMAm4QBQAGAAwDcQAKAAAADARuEAsABAAMBCIF" - + "BgBwEAcABQBuIAgABQAaAAEAbiAIAAUAbiAIABUAbiAIAAUAbiAIACUAbiAIAAUAbiAIADUAGgAA" - + "AG4gCAAFAG4gCABFAG4QCQAFAAwAEQAAAAIAAQAAAAAAMQMAAAMAAABUEAAAEQAAAAIAAQAAAAAA" - + "NQMAAAMAAABUEAEAEQAAAAIAAQAAAAAAOQMAAAMAAABUEAIAEQAAAAIAAQAAAAAAPQMAAAMAAABU" - + "EAMAEQAAAAIAAQABAAAAJAMAABQAAABwEAYAAQAaAAUAWxABABoAAwBbEAIAGgAEAFsQAAAaACQA" - + "WxADAA4ACwAOPEtLS0sAEgAOABgADgAVAA4AHgAOABsADgAAAAABAAAABQAGIGZyb20gAAIsIAAG" - + "PGluaXQ+ABBCb25qb3VyIGxlIE1vbmRlAApIZWogVmVyZGVuAAtIZWxsbyBXb3JsZAABTAACTEwA" - + "GExhcnQvVGVzdDIwMDEkVHJhbnNmb3JtOwAOTGFydC9UZXN0MjAwMTsAIkxkYWx2aWsvYW5ub3Rh" - + "dGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwASTGph" - + "dmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAGUxqYXZhL2xhbmcvU3RyaW5nQnVp" - + "bGRlcjsAEkxqYXZhL2xhbmcvVGhyZWFkOwANVGVzdDIwMDEuamF2YQAJVHJhbnNmb3JtAAFWAAth" - + "Y2Nlc3NGbGFncwAGYXBwZW5kAA1jdXJyZW50VGhyZWFkAAdnZXROYW1lAA5ncmVldGluZ0Rhbmlz" - + "aAAPZ3JlZXRpbmdFbmdsaXNoAA5ncmVldGluZ0ZyZW5jaAAQZ3JlZXRpbmdKYXBhbmVzZQAEbmFt" - + "ZQAFc2F5SGkAC3NheUhpRGFuaXNoAAxzYXlIaUVuZ2xpc2gAC3NheUhpRnJlbmNoAA1zYXlIaUph" - + "cGFuZXNlAAh0b1N0cmluZwAFdmFsdWUAiwF+fkQ4eyJjb21waWxhdGlvbi1tb2RlIjoiZGVidWci" - + "LCJoYXMtY2hlY2tzdW1zIjpmYWxzZSwibWluLWFwaSI6MSwic2hhLTEiOiJmNjJiOGNlNmEwNTkw" - + "MDU0ZWYzNGExYWVkZTcwYjQ2NjY4ZThiNDlmIiwidmVyc2lvbiI6IjIuMC4xLWRldiJ9AAfjgZPj" - + "gpPjgavjgaHjga/kuJbnlYwAAgIBIhgBAgMCEwQJGxcRAAQBBQABAQEBAQEBAIGABOwFAQH4AwEB" - + "jAUBAaQFAQG8BQEB1AUAAAAAAAAAAgAAANwFAADiBQAAGAYAAAAAAAAAAAAAAAAAABAAAAAAAAAA" - + "AQAAAAAAAAABAAAAJQAAAHAAAAACAAAACQAAAAQBAAADAAAABAAAACgBAAAEAAAABAAAAFgBAAAF" - + "AAAADAAAAHgBAAAGAAAAAQAAANgBAAABIAAABgAAAPgBAAADIAAABgAAACQDAAABEAAAAQAAAEQD" - + "AAACIAAAJQAAAEoDAAAEIAAAAgAAANwFAAAAIAAAAQAAAOsFAAADEAAAAgAAABQGAAAGIAAAAQAA" - + "ACQGAAAAEAAAAQAAADQGAAA="); - - /* - * base64 encoded class/dex file for - package art; - import java.util.function.Supplier; - public class SubTransform extends art.Test2001.Transform implements Supplier<String> { - public SubTransform() { - super(); - } - public String get() { - return "from SUBCLASS: " + super.sayHi(); - } - } - */ - private static final byte[] SUB_DEX_BYTES = - Base64.getDecoder() - .decode( - "ZGV4CjAzNQBawzkIDf9khFw00md41U4vIqRuhqBTjM+0BAAAcAAAAHhWNBIAAAAAAAAAAPwDAAAV" - + "AAAAcAAAAAgAAADEAAAABAAAAOQAAAAAAAAAAAAAAAgAAAAUAQAAAQAAAFQBAABAAwAAdAEAAAIC" - + "AAAKAgAADgIAABECAAAVAgAAKQIAAEMCAABiAgAAdgIAAIoCAAClAgAAxAIAAOMCAAD2AgAA+QIA" - + "AAEDAAASAwAAFwMAAB4DAAAoAwAALwMAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAoAAAANAAAA" - + "AgAAAAMAAAAAAAAAAgAAAAQAAAAAAAAAAwAAAAUAAAD8AQAADQAAAAcAAAAAAAAAAAADAAAAAAAA" - + "AAAAEAAAAAAAAQAQAAAAAQADAAAAAAABAAEAEQAAAAUAAwAAAAAABQACAA4AAAAFAAEAEgAAAAAA" - + "AAABAAAAAQAAAPQBAAAMAAAA7AMAAMsDAAAAAAAAAgABAAEAAADpAQAABQAAAG4QAgABAAwAEQAA" - + "AAQAAQACAAAA7QEAABYAAABvEAQAAwAMACIBBQBwEAUAAQAaAg8AbiAGACEAbiAGAAEAbhAHAAEA" - + "DAARAAEAAQABAAAA5AEAAAQAAABwEAMAAAAOAAYADjwABAAOAAkADgAAAAABAAAABgAAAAEAAAAE" - + "AAY8aW5pdD4AAj47AAFMAAJMTAASTGFydC9TdWJUcmFuc2Zvcm07ABhMYXJ0L1Rlc3QyMDAxJFRy" - + "YW5zZm9ybTsAHUxkYWx2aWsvYW5ub3RhdGlvbi9TaWduYXR1cmU7ABJMamF2YS9sYW5nL09iamVj" - + "dDsAEkxqYXZhL2xhbmcvU3RyaW5nOwAZTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwAdTGphdmEv" - + "dXRpbC9mdW5jdGlvbi9TdXBwbGllcjsAHUxqYXZhL3V0aWwvZnVuY3Rpb24vU3VwcGxpZXI8ABFT" - + "dWJUcmFuc2Zvcm0uamF2YQABVgAGYXBwZW5kAA9mcm9tIFNVQkNMQVNTOiAAA2dldAAFc2F5SGkA" - + "CHRvU3RyaW5nAAV2YWx1ZQCLAX5+RDh7ImNvbXBpbGF0aW9uLW1vZGUiOiJkZWJ1ZyIsImhhcy1j" - + "aGVja3N1bXMiOmZhbHNlLCJtaW4tYXBpIjoxLCJzaGEtMSI6ImY2MmI4Y2U2YTA1OTAwNTRlZjM0" - + "YTFhZWRlNzBiNDY2NjhlOGI0OWYiLCJ2ZXJzaW9uIjoiMi4wLjEtZGV2In0AAgIBExwEFwUXCxcI" - + "FwEAAAECAIGABMwDAcEg9AIBAZADAAAAAAAAAQAAAL0DAADkAwAAAAAAAAAAAAAAAAAADwAAAAAA" - + "AAABAAAAAAAAAAEAAAAVAAAAcAAAAAIAAAAIAAAAxAAAAAMAAAAEAAAA5AAAAAUAAAAIAAAAFAEA" - + "AAYAAAABAAAAVAEAAAEgAAADAAAAdAEAAAMgAAADAAAA5AEAAAEQAAACAAAA9AEAAAIgAAAVAAAA" - + "AgIAAAQgAAABAAAAvQMAAAAgAAABAAAAywMAAAMQAAACAAAA4AMAAAYgAAABAAAA7AMAAAAQAAAB" - + "AAAA/AMAAA=="); - - public static void run() throws Exception { - Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE); - doTest(); - } - - public static Supplier<String> mkTransform() { - try { - return (Supplier<String>) - (new InMemoryDexClassLoader( - ByteBuffer.wrap(SUB_DEX_BYTES), Test2001.class.getClassLoader()) - .loadClass("art.SubTransform") - .newInstance()); - } catch (Exception e) { - return () -> { - return e.toString(); - }; - } - } - - public static final class MyThread extends Thread { - public MyThread(CountDownLatch delay, int id) { - super("Thread: " + id); - this.thr_id = id; - this.results = new ArrayList<>(1000); - this.finish = false; - this.delay = delay; - } - - public void run() { - delay.countDown(); - while (!finish) { - Supplier<String> t = mkTransform(); - results.add(t.get()); - } - } - - public void finish() throws Exception { - finish = true; - this.join(); - } - - public void Check() throws Exception { - for (String s : results) { - if (!s.equals("from SUBCLASS: Hello from " + getName()) - && !s.equals("from SUBCLASS: Hello, null, null, null from " + getName()) - && !s.equals( - "from SUBCLASS: Hello World, Bonjour le Monde, Hej Verden, こんにちは世界 from " - + getName())) { - System.out.println("FAIL " + thr_id + ": Unexpected result: " + s); - } - } - } - - public ArrayList<String> results; - public volatile boolean finish; - public int thr_id; - public CountDownLatch delay; - } - - public static MyThread[] startThreads(int num_threads) throws Exception { - CountDownLatch cdl = new CountDownLatch(num_threads); - MyThread[] res = new MyThread[num_threads]; - for (int i = 0; i < num_threads; i++) { - res[i] = new MyThread(cdl, i); - res[i].start(); - } - cdl.await(); - return res; - } - - public static void finishThreads(MyThread[] thrs) throws Exception { - for (MyThread t : thrs) { - t.finish(); - } - for (MyThread t : thrs) { - t.Check(); - } - } - - public static void doTest() throws Exception { - MyThread[] threads = startThreads(NUM_THREADS); - Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); - finishThreads(threads); - } -} diff --git a/test/2001-virtual-structural-multithread/src/Main.java b/test/2001-virtual-structural-multithread/src/Main.java deleted file mode 100644 index 89b8557970..0000000000 --- a/test/2001-virtual-structural-multithread/src/Main.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -public class Main { - public static void main(String[] args) throws Exception { - System.out.println("FAIL: Test is only for art!"); - } -} diff --git a/test/2002-virtual-structural-initializing/expected.txt b/test/2002-virtual-structural-initializing/expected.txt deleted file mode 100644 index c1c8a70a8b..0000000000 --- a/test/2002-virtual-structural-initializing/expected.txt +++ /dev/null @@ -1 +0,0 @@ -Initialized Static Hello diff --git a/test/2002-virtual-structural-initializing/info.txt b/test/2002-virtual-structural-initializing/info.txt deleted file mode 100644 index 3e5291df87..0000000000 --- a/test/2002-virtual-structural-initializing/info.txt +++ /dev/null @@ -1,4 +0,0 @@ -Tests structural redefinition with multiple threads. - -Tests that using the structural redefinition while concurrently loading and using a subtype of -the class being redefined doesn't cause any unexpected problems. diff --git a/test/2002-virtual-structural-initializing/run b/test/2002-virtual-structural-initializing/run deleted file mode 100755 index 421f7b0bf2..0000000000 --- a/test/2002-virtual-structural-initializing/run +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -# -# Copyright 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. - -# TODO(b/144168550) This test uses access patterns that can be replaced by -# iget-object-quick during dex2dex compilation. This breaks the test since the -# -quick opcode encodes the exact byte offset of fields. Since this test changes -# the offset this causes problems. -./default-run "$@" --jvmti --runtime-option -Xopaque-jni-ids:true -Xcompiler-option --debuggable diff --git a/test/2002-virtual-structural-initializing/src-art/Main.java b/test/2002-virtual-structural-initializing/src-art/Main.java deleted file mode 100644 index a0aab42c7f..0000000000 --- a/test/2002-virtual-structural-initializing/src-art/Main.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -public class Main { - public static void main(String[] args) throws Exception { - art.Test2002.run(); - } -} diff --git a/test/2002-virtual-structural-initializing/src-art/art/Redefinition.java b/test/2002-virtual-structural-initializing/src-art/art/Redefinition.java deleted file mode 120000 index 81eaf31bbb..0000000000 --- a/test/2002-virtual-structural-initializing/src-art/art/Redefinition.java +++ /dev/null @@ -1 +0,0 @@ -../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/2002-virtual-structural-initializing/src-art/art/Test2002.java b/test/2002-virtual-structural-initializing/src-art/art/Test2002.java deleted file mode 100644 index f91e3f7ec5..0000000000 --- a/test/2002-virtual-structural-initializing/src-art/art/Test2002.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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. - */ - -package art; - -import dalvik.system.InMemoryDexClassLoader; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Base64; -import java.util.concurrent.CountDownLatch; -import java.util.function.Supplier; - -public class Test2002 { - public static final CountDownLatch start_latch = new CountDownLatch(1); - public static final CountDownLatch finish_latch = new CountDownLatch(1); - public static class Transform { - public Transform() { } - - public String sayHi() { - return "Hi"; - } - } - - /** - * base64 encoded class/dex file for - * public static class Transform { - * public String greeting; - * - * public Transform() { - * greeting = "Hello"; - * } - * public String sayHi() { - * return greeting; - * } - * } - */ - private static final byte[] DEX_BYTES = - Base64.getDecoder() - .decode( -"ZGV4CjAzNQBlpDFxr5PhCBfCyN+GZYuYQvSqtTEESU3oAwAAcAAAAHhWNBIAAAAAAAAAADADAAAS" + -"AAAAcAAAAAcAAAC4AAAAAgAAANQAAAABAAAA7AAAAAMAAAD0AAAAAQAAAAwBAAC8AgAALAEAAHAB" + -"AAB4AQAAfwEAAIIBAACcAQAArAEAANABAADwAQAABAIAABgCAAAnAgAAMgIAADUCAABCAgAATAIA" + -"AFICAABZAgAAYAIAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAsAAAACAAAABQAAAAAAAAALAAAA" + -"BgAAAAAAAAAAAAUADQAAAAAAAQAAAAAAAAAAAA8AAAAEAAEAAAAAAAAAAAABAAAABAAAAAAAAAAJ" + -"AAAAIAMAAP0CAAAAAAAAAgABAAAAAABqAQAAAwAAAFQQAAARAAAAAgABAAEAAABkAQAACAAAAHAQ" + -"AgABABoAAQBbEAAADgAGAA48SwAKAA4AAAAGPGluaXQ+AAVIZWxsbwABTAAYTGFydC9UZXN0MjAw" + -"MiRUcmFuc2Zvcm07AA5MYXJ0L1Rlc3QyMDAyOwAiTGRhbHZpay9hbm5vdGF0aW9uL0VuY2xvc2lu" + -"Z0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xhc3M7ABJMamF2YS9sYW5nL09iamVj" + -"dDsAEkxqYXZhL2xhbmcvU3RyaW5nOwANVGVzdDIwMDIuamF2YQAJVHJhbnNmb3JtAAFWAAthY2Nl" + -"c3NGbGFncwAIZ3JlZXRpbmcABG5hbWUABXNheUhpAAV2YWx1ZQCLAX5+RDh7ImNvbXBpbGF0aW9u" + -"LW1vZGUiOiJkZWJ1ZyIsImhhcy1jaGVja3N1bXMiOmZhbHNlLCJtaW4tYXBpIjoxLCJzaGEtMSI6" + -"ImY2MmI4Y2U2YTA1OTAwNTRlZjM0YTFhZWRlNzBiNDY2NjhlOGI0OWYiLCJ2ZXJzaW9uIjoiMi4w" + -"LjEtZGV2In0AAgIBEBgBAgMCDAQJDhcKAAEBAQABAIGABMQCAQGsAgAAAAAAAAACAAAA7gIAAPQC" + -"AAAUAwAAAAAAAAAAAAAAAAAADwAAAAAAAAABAAAAAAAAAAEAAAASAAAAcAAAAAIAAAAHAAAAuAAA" + -"AAMAAAACAAAA1AAAAAQAAAABAAAA7AAAAAUAAAADAAAA9AAAAAYAAAABAAAADAEAAAEgAAACAAAA" + -"LAEAAAMgAAACAAAAZAEAAAIgAAASAAAAcAEAAAQgAAACAAAA7gIAAAAgAAABAAAA/QIAAAMQAAAC" + -"AAAAEAMAAAYgAAABAAAAIAMAAAAQAAABAAAAMAMAAA=="); - - /* - * base64 encoded class/dex file for - package art; - import java.util.function.Supplier; - import java.util.concurrent.CountDownLatch; - - public class SubTransform extends art.Test2002.Transform implements Supplier<String> { - public static final String staticId; - static { - String res = null; - try { - Test2002.start_latch.countDown(); - Test2002.finish_latch.await(); - res = "Initialized Static"; - } catch (Exception e) { - res = e.toString(); - } - staticId = res; - } - public SubTransform() { - super(); - } - public String get() { - return SubTransform.staticId + " " + sayHi(); - } - } - */ - private static final byte[] SUB_DEX_BYTES = - Base64.getDecoder() - .decode( -"ZGV4CjAzNQB0BhXQtGTKXAGE/UzeevPgeNK7UrQJRJkoBgAAcAAAAHhWNBIAAAAAAAAAAGQFAAAf" + -"AAAAcAAAAAsAAADsAAAABAAAABgBAAADAAAASAEAAAwAAABgAQAAAQAAAMABAABIBAAA4AEAAM4C" + -"AADRAgAA2wIAAOMCAADnAgAA+wIAAP4CAAACAwAAFgMAADADAABAAwAAXwMAAHYDAACKAwAAngMA" + -"ALkDAADgAwAA/wMAAB4EAAAxBAAANAQAADwEAABDBAAATgQAAFwEAABhBAAAaAQAAHUEAAB/BAAA" + -"iQQAAJAEAAAHAAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAAA8AAAAQAAAAEwAAAAUAAAAF" + -"AAAAAAAAAAUAAAAGAAAAAAAAAAYAAAAHAAAAyAIAABMAAAAKAAAAAAAAAAAABgAbAAAAAgAIABcA" + -"AAACAAgAGgAAAAAAAwABAAAAAAADAAIAAAAAAAAAGAAAAAAAAQAYAAAAAAABABkAAAABAAMAAgAA" + -"AAQAAQAcAAAABwADAAIAAAAHAAIAFAAAAAcAAQAcAAAACAADABUAAAAIAAMAFgAAAAAAAAABAAAA" + -"AQAAAMACAAASAAAAVAUAACwFAAAAAAAAAgABAAEAAAC1AgAABQAAAG4QAwABAAwAEQAAAAQAAQAC" + -"AAAAuQIAABsAAABiAAAAbhAEAAMADAEiAgcAcBAHAAIAbiAIAAIAGgAAAG4gCAACAG4gCAASAG4Q" + -"CQACAAwAEQAAAAEAAAABAAEApAIAABYAAAAAAGIAAgBuEAsAAABiAAEAbhAKAAAAGgAEACgGDQBu" + -"EAYAAAAMAGkAAAAOAAEAAAAMAAEAAQEEDgEAAQABAAAAsAIAAAQAAABwEAUAAAAOAAgADh9aWi8b" + -"HkwtABMADjwABQAOABYADgAAAAABAAAACQAAAAEAAAAGAAEgAAg8Y2xpbml0PgAGPGluaXQ+AAI+" + -"OwASSW5pdGlhbGl6ZWQgU3RhdGljAAFMAAJMTAASTGFydC9TdWJUcmFuc2Zvcm07ABhMYXJ0L1Rl" + -"c3QyMDAyJFRyYW5zZm9ybTsADkxhcnQvVGVzdDIwMDI7AB1MZGFsdmlrL2Fubm90YXRpb24vU2ln" + -"bmF0dXJlOwAVTGphdmEvbGFuZy9FeGNlcHRpb247ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZh" + -"L2xhbmcvU3RyaW5nOwAZTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwAlTGphdmEvdXRpbC9jb25j" + -"dXJyZW50L0NvdW50RG93bkxhdGNoOwAdTGphdmEvdXRpbC9mdW5jdGlvbi9TdXBwbGllcjsAHUxq" + -"YXZhL3V0aWwvZnVuY3Rpb24vU3VwcGxpZXI8ABFTdWJUcmFuc2Zvcm0uamF2YQABVgAGYXBwZW5k" + -"AAVhd2FpdAAJY291bnREb3duAAxmaW5pc2hfbGF0Y2gAA2dldAAFc2F5SGkAC3N0YXJ0X2xhdGNo" + -"AAhzdGF0aWNJZAAIdG9TdHJpbmcABXZhbHVlAIsBfn5EOHsiY29tcGlsYXRpb24tbW9kZSI6ImRl" + -"YnVnIiwiaGFzLWNoZWNrc3VtcyI6ZmFsc2UsIm1pbi1hcGkiOjEsInNoYS0xIjoiZjYyYjhjZTZh" + -"MDU5MDA1NGVmMzRhMWFlZGU3MGI0NjY2OGU4YjQ5ZiIsInZlcnNpb24iOiIyLjAuMS1kZXYifQAC" + -"AwEdHAQXCBcRFw0XAwEAAgIAGQCIgATEBAGBgASMBQLBIOADAQH8AwAAAAAAAQAAAB4FAABMBQAA" + -"AAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAAAAAAEAAAAfAAAAcAAAAAIAAAALAAAA7AAAAAMAAAAE" + -"AAAAGAEAAAQAAAADAAAASAEAAAUAAAAMAAAAYAEAAAYAAAABAAAAwAEAAAEgAAAEAAAA4AEAAAMg" + -"AAAEAAAApAIAAAEQAAACAAAAwAIAAAIgAAAfAAAAzgIAAAQgAAABAAAAHgUAAAAgAAABAAAALAUA" + -"AAMQAAACAAAASAUAAAYgAAABAAAAVAUAAAAQAAABAAAAZAUAAA=="); - - public static void run() throws Exception { - Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE); - doTest(); - } - - public static Supplier<String> mkTransform() { - try { - return (Supplier<String>) - (new InMemoryDexClassLoader( - ByteBuffer.wrap(SUB_DEX_BYTES), Test2002.class.getClassLoader()) - .loadClass("art.SubTransform") - .newInstance()); - } catch (Exception e) { - return () -> { - return e.toString(); - }; - } - } - - public static void doTest() throws Exception { - Thread t = new Thread(() -> { - Supplier<String> s = mkTransform(); - System.out.println(s.get()); - }); - t.start(); - start_latch.await(); - Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); - finish_latch.countDown(); - t.join(); - } -} diff --git a/test/2002-virtual-structural-initializing/src/Main.java b/test/2002-virtual-structural-initializing/src/Main.java deleted file mode 100644 index 89b8557970..0000000000 --- a/test/2002-virtual-structural-initializing/src/Main.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -public class Main { - public static void main(String[] args) throws Exception { - System.out.println("FAIL: Test is only for art!"); - } -} diff --git a/test/knownfailures.json b/test/knownfailures.json index c5115e9fab..8840de500f 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -1150,11 +1150,7 @@ "1995-final-virtual-structural-multithread", "1996-final-override-virtual-structural", "1997-structural-shadow-method", - "1998-structural-shadow-field", - "1999-virtual-structural", - "2000-virtual-list-structural", - "2001-virtual-structural-multithread", - "2002-virtual-structural-initializing" + "1998-structural-shadow-field" ], "variant": "jvm", "description": ["Doesn't run on RI."] |