diff options
| -rw-r--r-- | runtime/art_method-inl.h | 6 | ||||
| -rw-r--r-- | runtime/art_method.cc | 10 | ||||
| -rw-r--r-- | runtime/art_method.h | 2 | ||||
| -rw-r--r-- | runtime/dex_file_annotations.cc | 329 | ||||
| -rw-r--r-- | test/980-redefine-object/expected.txt | 55 | ||||
| -rw-r--r-- | test/980-redefine-object/info.txt | 23 | ||||
| -rw-r--r-- | test/980-redefine-object/redefine_object.cc | 54 | ||||
| -rwxr-xr-x | test/980-redefine-object/run | 17 | ||||
| -rw-r--r-- | test/980-redefine-object/src-ex/TestWatcher.java | 25 | ||||
| -rw-r--r-- | test/980-redefine-object/src/Main.java | 390 | ||||
| -rw-r--r-- | test/980-redefine-object/src/Transform.java | 17 | ||||
| -rw-r--r-- | test/Android.bp | 1 | ||||
| -rw-r--r-- | test/ti-agent/common_helper.cc | 7 | ||||
| -rw-r--r-- | test/ti-agent/common_helper.h | 1 |
14 files changed, 123 insertions, 814 deletions
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index b47f8f0fc2..685e26c78d 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -347,11 +347,7 @@ inline const char* ArtMethod::GetDeclaringClassSourceFile() { inline uint16_t ArtMethod::GetClassDefIndex() { DCHECK(!IsProxyMethod()); - if (LIKELY(!IsObsolete())) { - return GetDeclaringClass()->GetDexClassDefIndex(); - } else { - return FindObsoleteDexClassDefIndex(); - } + return GetDeclaringClass()->GetDexClassDefIndex(); } inline const DexFile::ClassDef& ArtMethod::GetClassDef() { diff --git a/runtime/art_method.cc b/runtime/art_method.cc index 80a877350b..9d74e7c92b 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -104,16 +104,6 @@ mirror::DexCache* ArtMethod::GetObsoleteDexCache() { UNREACHABLE(); } -uint16_t ArtMethod::FindObsoleteDexClassDefIndex() { - DCHECK(!Runtime::Current()->IsAotCompiler()) << PrettyMethod(); - DCHECK(IsObsolete()); - const DexFile* dex_file = GetDexFile(); - const dex::TypeIndex declaring_class_type = dex_file->GetMethodId(GetDexMethodIndex()).class_idx_; - const DexFile::ClassDef* class_def = dex_file->FindClassDef(declaring_class_type); - CHECK(class_def != nullptr); - return dex_file->GetIndexForClassDef(*class_def); -} - mirror::String* ArtMethod::GetNameAsString(Thread* self) { CHECK(!IsProxyMethod()); StackHandleScope<1> hs(self); diff --git a/runtime/art_method.h b/runtime/art_method.h index 2248c3bd9d..cd1950c0e2 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -700,8 +700,6 @@ class ArtMethod FINAL { } ptr_sized_fields_; private: - uint16_t FindObsoleteDexClassDefIndex() REQUIRES_SHARED(Locks::mutator_lock_); - bool IsAnnotatedWith(jclass klass, uint32_t visibility); static constexpr size_t PtrSizedFieldsOffset(PointerSize pointer_size) { diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc index 6b9654dc49..d39ea35a90 100644 --- a/runtime/dex_file_annotations.cc +++ b/runtime/dex_file_annotations.cc @@ -41,80 +41,7 @@ struct DexFile::AnnotationValue { }; namespace { - -// A helper class that contains all the data needed to do annotation lookup. -class ClassData { - public: - explicit ClassData(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) - : ClassData(ScopedNullHandle<mirror::Class>(), // klass - method, - *method->GetDexFile(), - &method->GetClassDef()) {} - - // Requires Scope to be able to create at least 1 handles. - template <typename Scope> - ClassData(Scope& hs, ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) - : ClassData(hs.NewHandle(field->GetDeclaringClass())) { } - - explicit ClassData(Handle<mirror::Class> klass) REQUIRES_SHARED(art::Locks::mutator_lock_) - : ClassData(klass, // klass - nullptr, // method - klass->GetDexFile(), - klass->GetClassDef()) {} - - const DexFile& GetDexFile() const REQUIRES_SHARED(Locks::mutator_lock_) { - return dex_file_; - } - - const DexFile::ClassDef* GetClassDef() const REQUIRES_SHARED(Locks::mutator_lock_) { - return class_def_; - } - - ObjPtr<mirror::DexCache> GetDexCache() const REQUIRES_SHARED(Locks::mutator_lock_) { - if (method_ != nullptr) { - return method_->GetDexCache(); - } else { - return real_klass_->GetDexCache(); - } - } - - ObjPtr<mirror::ClassLoader> GetClassLoader() const REQUIRES_SHARED(Locks::mutator_lock_) { - if (method_ != nullptr) { - return method_->GetDeclaringClass()->GetClassLoader(); - } else { - return real_klass_->GetClassLoader(); - } - } - - ObjPtr<mirror::Class> GetRealClass() const REQUIRES_SHARED(Locks::mutator_lock_) { - if (method_ != nullptr) { - return method_->GetDeclaringClass(); - } else { - return real_klass_.Get(); - } - } - - private: - ClassData(Handle<mirror::Class> klass, - ArtMethod* method, - const DexFile& dex_file, - const DexFile::ClassDef* class_def) REQUIRES_SHARED(Locks::mutator_lock_) - : real_klass_(klass), - method_(method), - dex_file_(dex_file), - class_def_(class_def) { - DCHECK((method_ == nullptr) || real_klass_.IsNull()); - } - - Handle<mirror::Class> real_klass_; - ArtMethod* method_; - const DexFile& dex_file_; - const DexFile::ClassDef* class_def_; - - DISALLOW_COPY_AND_ASSIGN(ClassData); -}; - -mirror::Object* CreateAnnotationMember(const ClassData& klass, +mirror::Object* CreateAnnotationMember(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class, const uint8_t** annotation) REQUIRES_SHARED(Locks::mutator_lock_); @@ -258,8 +185,9 @@ const uint8_t* SearchEncodedAnnotation(const DexFile& dex_file, const DexFile::AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) { const DexFile* dex_file = method->GetDexFile(); + mirror::Class* klass = method->GetDeclaringClass(); const DexFile::AnnotationsDirectoryItem* annotations_dir = - dex_file->GetAnnotationsDirectory(method->GetClassDef()); + dex_file->GetAnnotationsDirectory(*klass->GetClassDef()); if (annotations_dir == nullptr) { return nullptr; } @@ -281,8 +209,9 @@ const DexFile::AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method) const DexFile::ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) { const DexFile* dex_file = method->GetDexFile(); + mirror::Class* klass = method->GetDeclaringClass(); const DexFile::AnnotationsDirectoryItem* annotations_dir = - dex_file->GetAnnotationsDirectory(method->GetClassDef()); + dex_file->GetAnnotationsDirectory(*klass->GetClassDef()); if (annotations_dir == nullptr) { return nullptr; } @@ -301,34 +230,30 @@ const DexFile::ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* return nullptr; } -const DexFile::AnnotationSetItem* FindAnnotationSetForClass(const ClassData& klass) +const DexFile::AnnotationSetItem* FindAnnotationSetForClass(Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) { - const DexFile& dex_file = klass.GetDexFile(); + const DexFile& dex_file = klass->GetDexFile(); const DexFile::AnnotationsDirectoryItem* annotations_dir = - dex_file.GetAnnotationsDirectory(*klass.GetClassDef()); + dex_file.GetAnnotationsDirectory(*klass->GetClassDef()); if (annotations_dir == nullptr) { return nullptr; } return dex_file.GetClassAnnotationSet(annotations_dir); } -mirror::Object* ProcessEncodedAnnotation(const ClassData& klass, const uint8_t** annotation) +mirror::Object* ProcessEncodedAnnotation(Handle<mirror::Class> klass, const uint8_t** annotation) REQUIRES_SHARED(Locks::mutator_lock_) { uint32_t type_index = DecodeUnsignedLeb128(annotation); uint32_t size = DecodeUnsignedLeb128(annotation); Thread* self = Thread::Current(); ScopedObjectAccessUnchecked soa(self); - StackHandleScope<4> hs(self); + StackHandleScope<2> hs(self); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); Handle<mirror::Class> annotation_class(hs.NewHandle( - class_linker->ResolveType(klass.GetDexFile(), - dex::TypeIndex(type_index), - hs.NewHandle(klass.GetDexCache()), - hs.NewHandle(klass.GetClassLoader())))); + class_linker->ResolveType(klass->GetDexFile(), dex::TypeIndex(type_index), klass.Get()))); if (annotation_class == nullptr) { - LOG(INFO) << "Unable to resolve " << klass.GetRealClass()->PrettyClass() - << " annotation class " << type_index; + LOG(INFO) << "Unable to resolve " << klass->PrettyClass() << " annotation class " << type_index; DCHECK(Thread::Current()->IsExceptionPending()); Thread::Current()->ClearException(); return nullptr; @@ -375,13 +300,13 @@ mirror::Object* ProcessEncodedAnnotation(const ClassData& klass, const uint8_t** } template <bool kTransactionActive> -bool ProcessAnnotationValue(const ClassData& klass, +bool ProcessAnnotationValue(Handle<mirror::Class> klass, const uint8_t** annotation_ptr, DexFile::AnnotationValue* annotation_value, Handle<mirror::Class> array_class, DexFile::AnnotationResultStyle result_style) REQUIRES_SHARED(Locks::mutator_lock_) { - const DexFile& dex_file = klass.GetDexFile(); + const DexFile& dex_file = klass->GetDexFile(); Thread* self = Thread::Current(); ObjPtr<mirror::Object> element_object = nullptr; bool set_object = false; @@ -436,8 +361,9 @@ bool ProcessAnnotationValue(const ClassData& klass, annotation_value->value_.SetI(index); } else { StackHandleScope<1> hs(self); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); element_object = Runtime::Current()->GetClassLinker()->ResolveString( - klass.GetDexFile(), dex::StringIndex(index), hs.NewHandle(klass.GetDexCache())); + klass->GetDexFile(), dex::StringIndex(index), dex_cache); set_object = true; if (element_object == nullptr) { return false; @@ -451,12 +377,8 @@ bool ProcessAnnotationValue(const ClassData& klass, annotation_value->value_.SetI(index); } else { dex::TypeIndex type_index(index); - StackHandleScope<2> hs(self); element_object = Runtime::Current()->GetClassLinker()->ResolveType( - klass.GetDexFile(), - type_index, - hs.NewHandle(klass.GetDexCache()), - hs.NewHandle(klass.GetClassLoader())); + klass->GetDexFile(), type_index, klass.Get()); set_object = true; if (element_object == nullptr) { CHECK(self->IsExceptionPending()); @@ -477,13 +399,12 @@ bool ProcessAnnotationValue(const ClassData& klass, if (result_style == DexFile::kAllRaw) { annotation_value->value_.SetI(index); } else { - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); StackHandleScope<2> hs(self); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader())); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); ArtMethod* method = class_linker->ResolveMethodWithoutInvokeType( - klass.GetDexFile(), - index, - hs.NewHandle(klass.GetDexCache()), - hs.NewHandle(klass.GetClassLoader())); + klass->GetDexFile(), index, dex_cache, class_loader); if (method == nullptr) { return false; } @@ -518,11 +439,10 @@ bool ProcessAnnotationValue(const ClassData& klass, annotation_value->value_.SetI(index); } else { StackHandleScope<2> hs(self); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader())); ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS( - klass.GetDexFile(), - index, - hs.NewHandle(klass.GetDexCache()), - hs.NewHandle(klass.GetClassLoader())); + klass->GetDexFile(), index, dex_cache, class_loader); if (field == nullptr) { return false; } @@ -547,12 +467,10 @@ bool ProcessAnnotationValue(const ClassData& klass, annotation_value->value_.SetI(index); } else { StackHandleScope<3> hs(self); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader())); ArtField* enum_field = Runtime::Current()->GetClassLinker()->ResolveField( - klass.GetDexFile(), - index, - hs.NewHandle(klass.GetDexCache()), - hs.NewHandle(klass.GetClassLoader()), - true); + klass->GetDexFile(), index, dex_cache, class_loader, true); if (enum_field == nullptr) { return false; } else { @@ -677,10 +595,10 @@ bool ProcessAnnotationValue(const ClassData& klass, return true; } -mirror::Object* CreateAnnotationMember(const ClassData& klass, +mirror::Object* CreateAnnotationMember(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class, const uint8_t** annotation) { - const DexFile& dex_file = klass.GetDexFile(); + const DexFile& dex_file = klass->GetDexFile(); Thread* self = Thread::Current(); ScopedObjectAccessUnchecked soa(self); StackHandleScope<5> hs(self); @@ -748,12 +666,12 @@ mirror::Object* CreateAnnotationMember(const ClassData& klass, } const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet( - const ClassData& klass, + Handle<mirror::Class> klass, const DexFile::AnnotationSetItem* annotation_set, uint32_t visibility, Handle<mirror::Class> annotation_class) REQUIRES_SHARED(Locks::mutator_lock_) { - const DexFile& dex_file = klass.GetDexFile(); + const DexFile& dex_file = klass->GetDexFile(); for (uint32_t i = 0; i < annotation_set->size_; ++i) { const DexFile::AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i); if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) { @@ -761,16 +679,12 @@ const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet( } const uint8_t* annotation = annotation_item->annotation_; uint32_t type_index = DecodeUnsignedLeb128(&annotation); - StackHandleScope<2> hs(Thread::Current()); mirror::Class* resolved_class = Runtime::Current()->GetClassLinker()->ResolveType( - klass.GetDexFile(), - dex::TypeIndex(type_index), - hs.NewHandle(klass.GetDexCache()), - hs.NewHandle(klass.GetClassLoader())); + klass->GetDexFile(), dex::TypeIndex(type_index), klass.Get()); if (resolved_class == nullptr) { std::string temp; LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d", - klass.GetRealClass()->GetDescriptor(&temp), type_index); + klass->GetDescriptor(&temp), type_index); CHECK(Thread::Current()->IsExceptionPending()); Thread::Current()->ClearException(); continue; @@ -784,7 +698,7 @@ const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet( } mirror::Object* GetAnnotationObjectFromAnnotationSet( - const ClassData& klass, + Handle<mirror::Class> klass, const DexFile::AnnotationSetItem* annotation_set, uint32_t visibility, Handle<mirror::Class> annotation_class) @@ -798,13 +712,13 @@ mirror::Object* GetAnnotationObjectFromAnnotationSet( return ProcessEncodedAnnotation(klass, &annotation); } -mirror::Object* GetAnnotationValue(const ClassData& klass, +mirror::Object* GetAnnotationValue(Handle<mirror::Class> klass, const DexFile::AnnotationItem* annotation_item, const char* annotation_name, Handle<mirror::Class> array_class, uint32_t expected_type) REQUIRES_SHARED(Locks::mutator_lock_) { - const DexFile& dex_file = klass.GetDexFile(); + const DexFile& dex_file = klass->GetDexFile(); const uint8_t* annotation = SearchEncodedAnnotation(dex_file, annotation_item->annotation_, annotation_name); if (annotation == nullptr) { @@ -831,10 +745,10 @@ mirror::Object* GetAnnotationValue(const ClassData& klass, return annotation_value.value_.GetL(); } -mirror::ObjectArray<mirror::String>* GetSignatureValue(const ClassData& klass, +mirror::ObjectArray<mirror::String>* GetSignatureValue(Handle<mirror::Class> klass, const DexFile::AnnotationSetItem* annotation_set) REQUIRES_SHARED(Locks::mutator_lock_) { - const DexFile& dex_file = klass.GetDexFile(); + const DexFile& dex_file = klass->GetDexFile(); StackHandleScope<1> hs(Thread::Current()); const DexFile::AnnotationItem* annotation_item = SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/Signature;", @@ -857,10 +771,10 @@ mirror::ObjectArray<mirror::String>* GetSignatureValue(const ClassData& klass, return obj->AsObjectArray<mirror::String>(); } -mirror::ObjectArray<mirror::Class>* GetThrowsValue(const ClassData& klass, +mirror::ObjectArray<mirror::Class>* GetThrowsValue(Handle<mirror::Class> klass, const DexFile::AnnotationSetItem* annotation_set) REQUIRES_SHARED(Locks::mutator_lock_) { - const DexFile& dex_file = klass.GetDexFile(); + const DexFile& dex_file = klass->GetDexFile(); StackHandleScope<1> hs(Thread::Current()); const DexFile::AnnotationItem* annotation_item = SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/Throws;", @@ -884,11 +798,11 @@ mirror::ObjectArray<mirror::Class>* GetThrowsValue(const ClassData& klass, } mirror::ObjectArray<mirror::Object>* ProcessAnnotationSet( - const ClassData& klass, + Handle<mirror::Class> klass, const DexFile::AnnotationSetItem* annotation_set, uint32_t visibility) REQUIRES_SHARED(Locks::mutator_lock_) { - const DexFile& dex_file = klass.GetDexFile(); + const DexFile& dex_file = klass->GetDexFile(); Thread* self = Thread::Current(); ScopedObjectAccessUnchecked soa(self); StackHandleScope<2> hs(self); @@ -942,11 +856,11 @@ mirror::ObjectArray<mirror::Object>* ProcessAnnotationSet( } mirror::ObjectArray<mirror::Object>* ProcessAnnotationSetRefList( - const ClassData& klass, + Handle<mirror::Class> klass, const DexFile::AnnotationSetRefList* set_ref_list, uint32_t size) REQUIRES_SHARED(Locks::mutator_lock_) { - const DexFile& dex_file = klass.GetDexFile(); + const DexFile& dex_file = klass->GetDexFile(); Thread* self = Thread::Current(); ScopedObjectAccessUnchecked soa(self); StackHandleScope<1> hs(self); @@ -985,17 +899,15 @@ mirror::Object* GetAnnotationForField(ArtField* field, Handle<mirror::Class> ann return nullptr; } StackHandleScope<1> hs(Thread::Current()); - const ClassData field_class(hs, field); - return GetAnnotationObjectFromAnnotationSet(field_class, - annotation_set, - DexFile::kDexVisibilityRuntime, - annotation_class); + Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass())); + return GetAnnotationObjectFromAnnotationSet(field_class, annotation_set, + DexFile::kDexVisibilityRuntime, annotation_class); } mirror::ObjectArray<mirror::Object>* GetAnnotationsForField(ArtField* field) { const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); StackHandleScope<1> hs(Thread::Current()); - const ClassData field_class(hs, field); + Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass())); return ProcessAnnotationSet(field_class, annotation_set, DexFile::kDexVisibilityRuntime); } @@ -1005,7 +917,7 @@ mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForField(ArtField* fi return nullptr; } StackHandleScope<1> hs(Thread::Current()); - const ClassData field_class(hs, field); + Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass())); return GetSignatureValue(field_class, annotation_set); } @@ -1015,17 +927,17 @@ bool IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_ return false; } StackHandleScope<1> hs(Thread::Current()); - const ClassData field_class(hs, field); + Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass())); const DexFile::AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet( field_class, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class); return annotation_item != nullptr; } mirror::Object* GetAnnotationDefaultValue(ArtMethod* method) { - const ClassData klass(method); - const DexFile* dex_file = &klass.GetDexFile(); + const DexFile* dex_file = method->GetDexFile(); + mirror::Class* klass = method->GetDeclaringClass(); const DexFile::AnnotationsDirectoryItem* annotations_dir = - dex_file->GetAnnotationsDirectory(*klass.GetClassDef()); + dex_file->GetAnnotationsDirectory(*klass->GetClassDef()); if (annotations_dir == nullptr) { return nullptr; } @@ -1053,9 +965,10 @@ mirror::Object* GetAnnotationDefaultValue(ArtMethod* method) { return nullptr; } DexFile::AnnotationValue annotation_value; - StackHandleScope<1> hs(Thread::Current()); + StackHandleScope<2> hs(Thread::Current()); + Handle<mirror::Class> h_klass(hs.NewHandle(klass)); Handle<mirror::Class> return_type(hs.NewHandle(method->GetReturnType(true /* resolve */))); - if (!ProcessAnnotationValue<false>(klass, + if (!ProcessAnnotationValue<false>(h_klass, &annotation, &annotation_value, return_type, @@ -1070,15 +983,17 @@ mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle<mirror::Class> if (annotation_set == nullptr) { return nullptr; } - return GetAnnotationObjectFromAnnotationSet(ClassData(method), annotation_set, + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + return GetAnnotationObjectFromAnnotationSet(method_class, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class); } mirror::ObjectArray<mirror::Object>* GetAnnotationsForMethod(ArtMethod* method) { const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); - return ProcessAnnotationSet(ClassData(method), - annotation_set, - DexFile::kDexVisibilityRuntime); + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + return ProcessAnnotationSet(method_class, annotation_set, DexFile::kDexVisibilityRuntime); } mirror::ObjectArray<mirror::Class>* GetExceptionTypesForMethod(ArtMethod* method) { @@ -1086,7 +1001,9 @@ mirror::ObjectArray<mirror::Class>* GetExceptionTypesForMethod(ArtMethod* method if (annotation_set == nullptr) { return nullptr; } - return GetThrowsValue(ClassData(method), annotation_set); + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + return GetThrowsValue(method_class, annotation_set); } mirror::ObjectArray<mirror::Object>* GetParameterAnnotations(ArtMethod* method) { @@ -1102,7 +1019,9 @@ mirror::ObjectArray<mirror::Object>* GetParameterAnnotations(ArtMethod* method) return nullptr; } uint32_t size = set_ref_list->size_; - return ProcessAnnotationSetRefList(ClassData(method), set_ref_list, size); + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + return ProcessAnnotationSetRefList(method_class, set_ref_list, size); } mirror::Object* GetAnnotationForMethodParameter(ArtMethod* method, @@ -1126,7 +1045,9 @@ mirror::Object* GetAnnotationForMethodParameter(ArtMethod* method, const DexFile::AnnotationSetItem* annotation_set = dex_file->GetSetRefItemItem(annotation_set_ref); - return GetAnnotationObjectFromAnnotationSet(ClassData(method), + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + return GetAnnotationObjectFromAnnotationSet(method_class, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class); @@ -1151,7 +1072,7 @@ bool GetParametersMetadataForMethod(ArtMethod* method, return false; } - StackHandleScope<4> hs(Thread::Current()); + StackHandleScope<5> hs(Thread::Current()); // Extract the parameters' names String[]. ObjPtr<mirror::Class> string_class = mirror::String::GetJavaLangString(); @@ -1161,9 +1082,9 @@ bool GetParametersMetadataForMethod(ArtMethod* method, return false; } - ClassData data(method); + Handle<mirror::Class> klass = hs.NewHandle(method->GetDeclaringClass()); Handle<mirror::Object> names_obj = - hs.NewHandle(GetAnnotationValue(data, + hs.NewHandle(GetAnnotationValue(klass, annotation_item, "names", string_array_class, @@ -1178,7 +1099,7 @@ bool GetParametersMetadataForMethod(ArtMethod* method, return false; } Handle<mirror::Object> access_flags_obj = - hs.NewHandle(GetAnnotationValue(data, + hs.NewHandle(GetAnnotationValue(klass, annotation_item, "accessFlags", int_array_class, @@ -1197,7 +1118,9 @@ mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* if (annotation_set == nullptr) { return nullptr; } - return GetSignatureValue(ClassData(method), annotation_set); + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + return GetSignatureValue(method_class, annotation_set); } bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class, @@ -1206,39 +1129,37 @@ bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotati if (annotation_set == nullptr) { return false; } + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); const DexFile::AnnotationItem* annotation_item = - GetAnnotationItemFromAnnotationSet(ClassData(method), - annotation_set, visibility, annotation_class); + GetAnnotationItemFromAnnotationSet(method_class, annotation_set, visibility, + annotation_class); return annotation_item != nullptr; } mirror::Object* GetAnnotationForClass(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) { - ClassData data(klass); - const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); if (annotation_set == nullptr) { return nullptr; } - return GetAnnotationObjectFromAnnotationSet(data, - annotation_set, - DexFile::kDexVisibilityRuntime, + return GetAnnotationObjectFromAnnotationSet(klass, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class); } mirror::ObjectArray<mirror::Object>* GetAnnotationsForClass(Handle<mirror::Class> klass) { - ClassData data(klass); - const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); - return ProcessAnnotationSet(data, annotation_set, DexFile::kDexVisibilityRuntime); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + return ProcessAnnotationSet(klass, annotation_set, DexFile::kDexVisibilityRuntime); } mirror::ObjectArray<mirror::Class>* GetDeclaredClasses(Handle<mirror::Class> klass) { - ClassData data(klass); - const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); if (annotation_set == nullptr) { return nullptr; } const DexFile::AnnotationItem* annotation_item = - SearchAnnotationSet(data.GetDexFile(), annotation_set, "Ldalvik/annotation/MemberClasses;", + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/MemberClasses;", DexFile::kDexVisibilitySystem); if (annotation_item == nullptr) { return nullptr; @@ -1251,7 +1172,7 @@ mirror::ObjectArray<mirror::Class>* GetDeclaredClasses(Handle<mirror::Class> kla return nullptr; } mirror::Object* obj = - GetAnnotationValue(data, annotation_item, "value", class_array_class, + GetAnnotationValue(klass, annotation_item, "value", class_array_class, DexFile::kDexAnnotationArray); if (obj == nullptr) { return nullptr; @@ -1260,18 +1181,18 @@ mirror::ObjectArray<mirror::Class>* GetDeclaredClasses(Handle<mirror::Class> kla } mirror::Class* GetDeclaringClass(Handle<mirror::Class> klass) { - ClassData data(klass); - const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); if (annotation_set == nullptr) { return nullptr; } const DexFile::AnnotationItem* annotation_item = - SearchAnnotationSet(data.GetDexFile(), annotation_set, "Ldalvik/annotation/EnclosingClass;", + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/EnclosingClass;", DexFile::kDexVisibilitySystem); if (annotation_item == nullptr) { return nullptr; } - mirror::Object* obj = GetAnnotationValue(data, annotation_item, "value", + mirror::Object* obj = GetAnnotationValue(klass, annotation_item, "value", ScopedNullHandle<mirror::Class>(), DexFile::kDexAnnotationType); if (obj == nullptr) { @@ -1281,30 +1202,28 @@ mirror::Class* GetDeclaringClass(Handle<mirror::Class> klass) { } mirror::Class* GetEnclosingClass(Handle<mirror::Class> klass) { + const DexFile& dex_file = klass->GetDexFile(); mirror::Class* declaring_class = GetDeclaringClass(klass); if (declaring_class != nullptr) { return declaring_class; } - ClassData data(klass); - const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); if (annotation_set == nullptr) { return nullptr; } const DexFile::AnnotationItem* annotation_item = - SearchAnnotationSet(data.GetDexFile(), - annotation_set, - "Ldalvik/annotation/EnclosingMethod;", + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/EnclosingMethod;", DexFile::kDexVisibilitySystem); if (annotation_item == nullptr) { return nullptr; } const uint8_t* annotation = - SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "value"); + SearchEncodedAnnotation(dex_file, annotation_item->annotation_, "value"); if (annotation == nullptr) { return nullptr; } DexFile::AnnotationValue annotation_value; - if (!ProcessAnnotationValue<false>(data, + if (!ProcessAnnotationValue<false>(klass, &annotation, &annotation_value, ScopedNullHandle<mirror::Class>(), @@ -1315,11 +1234,10 @@ mirror::Class* GetEnclosingClass(Handle<mirror::Class> klass) { return nullptr; } StackHandleScope<2> hs(Thread::Current()); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader())); ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType( - data.GetDexFile(), - annotation_value.value_.GetI(), - hs.NewHandle(data.GetDexCache()), - hs.NewHandle(data.GetClassLoader())); + klass->GetDexFile(), annotation_value.value_.GetI(), dex_cache, class_loader); if (method == nullptr) { return nullptr; } @@ -1327,44 +1245,39 @@ mirror::Class* GetEnclosingClass(Handle<mirror::Class> klass) { } mirror::Object* GetEnclosingMethod(Handle<mirror::Class> klass) { - ClassData data(klass); - const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); if (annotation_set == nullptr) { return nullptr; } const DexFile::AnnotationItem* annotation_item = - SearchAnnotationSet(data.GetDexFile(), - annotation_set, - "Ldalvik/annotation/EnclosingMethod;", + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/EnclosingMethod;", DexFile::kDexVisibilitySystem); if (annotation_item == nullptr) { return nullptr; } - return GetAnnotationValue(data, annotation_item, "value", ScopedNullHandle<mirror::Class>(), + return GetAnnotationValue(klass, annotation_item, "value", ScopedNullHandle<mirror::Class>(), DexFile::kDexAnnotationMethod); } bool GetInnerClass(Handle<mirror::Class> klass, mirror::String** name) { - ClassData data(klass); - const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); if (annotation_set == nullptr) { return false; } const DexFile::AnnotationItem* annotation_item = SearchAnnotationSet( - data.GetDexFile(), - annotation_set, - "Ldalvik/annotation/InnerClass;", - DexFile::kDexVisibilitySystem); + dex_file, annotation_set, "Ldalvik/annotation/InnerClass;", DexFile::kDexVisibilitySystem); if (annotation_item == nullptr) { return false; } const uint8_t* annotation = - SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "name"); + SearchEncodedAnnotation(dex_file, annotation_item->annotation_, "name"); if (annotation == nullptr) { return false; } DexFile::AnnotationValue annotation_value; - if (!ProcessAnnotationValue<false>(data, + if (!ProcessAnnotationValue<false>(klass, &annotation, &annotation_value, ScopedNullHandle<mirror::Class>(), @@ -1380,24 +1293,24 @@ bool GetInnerClass(Handle<mirror::Class> klass, mirror::String** name) { } bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) { - ClassData data(klass); - const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); if (annotation_set == nullptr) { return false; } const DexFile::AnnotationItem* annotation_item = - SearchAnnotationSet(data.GetDexFile(), annotation_set, "Ldalvik/annotation/InnerClass;", + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/InnerClass;", DexFile::kDexVisibilitySystem); if (annotation_item == nullptr) { return false; } const uint8_t* annotation = - SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "accessFlags"); + SearchEncodedAnnotation(dex_file, annotation_item->annotation_, "accessFlags"); if (annotation == nullptr) { return false; } DexFile::AnnotationValue annotation_value; - if (!ProcessAnnotationValue<false>(data, + if (!ProcessAnnotationValue<false>(klass, &annotation, &annotation_value, ScopedNullHandle<mirror::Class>(), @@ -1412,22 +1325,20 @@ bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) { } mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass) { - ClassData data(klass); - const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); if (annotation_set == nullptr) { return nullptr; } - return GetSignatureValue(data, annotation_set); + return GetSignatureValue(klass, annotation_set); } bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) { - ClassData data(klass); - const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); if (annotation_set == nullptr) { return false; } const DexFile::AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet( - data, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class); + klass, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class); return annotation_item != nullptr; } diff --git a/test/980-redefine-object/expected.txt b/test/980-redefine-object/expected.txt deleted file mode 100644 index 86753292de..0000000000 --- a/test/980-redefine-object/expected.txt +++ /dev/null @@ -1,55 +0,0 @@ - Initializing and loading the TestWatcher class that will (eventually) be notified of object allocations - Allocating an j.l.Object before redefining Object class - Allocating a Transform before redefining Object class - Redefining the Object class to add a hook into the <init> method -Object allocated of type 'Ljava/lang/StringBuilder;' -Object allocated of type 'Ljava/nio/HeapCharBuffer;' - Allocating an j.l.Object after redefining Object class -Object allocated of type 'Ljava/lang/Object;' -Object allocated of type 'Ljava/lang/StringBuilder;' -Object allocated of type 'Ljava/nio/HeapCharBuffer;' - Allocating a Transform after redefining Object class -Object allocated of type 'LTransform;' -Object allocated of type 'Ljava/lang/StringBuilder;' -Object allocated of type 'Ljava/nio/HeapCharBuffer;' - Allocating an int[] after redefining Object class -Object allocated of type 'Ljava/lang/StringBuilder;' -Object allocated of type 'Ljava/nio/HeapCharBuffer;' - Allocating an array list -Object allocated of type 'Ljava/util/ArrayList;' -Object allocated of type 'Ljava/lang/StringBuilder;' -Object allocated of type 'Ljava/nio/HeapCharBuffer;' - Adding a bunch of stuff to the array list -Object allocated of type 'Ljava/lang/Object;' -Object allocated of type 'Ljava/lang/Object;' -Object allocated of type 'LTransform;' -Object allocated of type 'Ljava/lang/StringBuilder;' -Object allocated of type 'Ljava/nio/HeapCharBuffer;' - Allocating a linked list -Object allocated of type 'Ljava/util/LinkedList;' -Object allocated of type 'Ljava/lang/StringBuilder;' -Object allocated of type 'Ljava/nio/HeapCharBuffer;' - Adding a bunch of stuff to the linked list -Object allocated of type 'Ljava/lang/Object;' -Object allocated of type 'Ljava/util/LinkedList$Node;' -Object allocated of type 'Ljava/lang/Object;' -Object allocated of type 'Ljava/util/LinkedList$Node;' -Object allocated of type 'Ljava/util/LinkedList$Node;' -Object allocated of type 'Ljava/util/LinkedList$Node;' -Object allocated of type 'Ljava/util/LinkedList$Node;' -Object allocated of type 'Ljava/util/LinkedList$Node;' -Object allocated of type 'LTransform;' -Object allocated of type 'Ljava/util/LinkedList$Node;' -Object allocated of type 'Ljava/lang/StringBuilder;' -Object allocated of type 'Ljava/nio/HeapCharBuffer;' - Throwing from down 4 stack frames -Object allocated of type 'Ljava/lang/Exception;' -Object allocated of type 'Ljava/lang/StringBuilder;' -Object allocated of type 'Ljava/nio/HeapCharBuffer;' - Exception caught. -Object allocated of type 'Ljava/lang/StringBuilder;' -Object allocated of type 'Ljava/nio/HeapCharBuffer;' - Finishing test! -Object allocated of type 'Ljava/lang/InterruptedException;' -Object allocated of type 'Ljava/lang/InterruptedException;' -Object allocated of type 'Ljava/lang/InterruptedException;' diff --git a/test/980-redefine-object/info.txt b/test/980-redefine-object/info.txt deleted file mode 100644 index f3e01b596d..0000000000 --- a/test/980-redefine-object/info.txt +++ /dev/null @@ -1,23 +0,0 @@ -Tests basic functions in the jvmti plugin. - -This tests that we are able to redefine methods/constructors on the -java.lang.Object class at runtime. - -This also (indirectly) tests that we correctly handle reading annotations on -obsolete methods. This is something that is not normally done since there is no -way to get a reference to an obsolete method outside of the runtime but some -annotations on the Object class are read by the runtime directly. - -NB This test cannot be run on the RI at the moment. - -If this test starts failing during the doCommonClassRedefinition call it is -possible that the definition of Object contained in the base64 DEX_BYTES array -has become stale and will need to be recreated. The only difference from the -normal Object dex bytes is that (a) it contains only the bytes of the Object -class itself, and (b) it adds an -'invoke-static {p0}, Ljava/lang/Object;->NotifyConstructed(Ljava/lang/Object;)V' -to the <init> function. - -It is also possible it could fail due to the pattern of allocations caused by -doing string concatenation or printing changing. In this case you should simply -update the expected.txt file. diff --git a/test/980-redefine-object/redefine_object.cc b/test/980-redefine-object/redefine_object.cc deleted file mode 100644 index ff450ddd35..0000000000 --- a/test/980-redefine-object/redefine_object.cc +++ /dev/null @@ -1,54 +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. - */ - -#include <inttypes.h> -#include <iostream> - -#include "android-base/stringprintf.h" -#include "base/logging.h" -#include "base/macros.h" -#include "jni.h" -#include "openjdkjvmti/jvmti.h" -#include "ScopedUtfChars.h" - -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" - -namespace art { -namespace Test980RedefineObjects { - -extern "C" JNIEXPORT void JNICALL Java_Main_bindFunctionsForClass( - JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jclass target) { - BindFunctionsOnClass(jvmti_env, env, target); -} - -extern "C" JNIEXPORT void JNICALL Java_art_test_TestWatcher_NotifyConstructed( - JNIEnv* env, jclass TestWatcherClass ATTRIBUTE_UNUSED, jobject constructed) { - char* sig = nullptr; - char* generic_sig = nullptr; - if (JvmtiErrorToException(env, jvmti_env->GetClassSignature(env->GetObjectClass(constructed), - &sig, - &generic_sig))) { - // Exception. - return; - } - std::cout << "Object allocated of type '" << sig << "'" << std::endl; - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(sig)); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(generic_sig)); -} - -} // namespace Test980RedefineObjects -} // namespace art diff --git a/test/980-redefine-object/run b/test/980-redefine-object/run deleted file mode 100755 index c6e62ae6cd..0000000000 --- a/test/980-redefine-object/run +++ /dev/null @@ -1,17 +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. - -./default-run "$@" --jvmti diff --git a/test/980-redefine-object/src-ex/TestWatcher.java b/test/980-redefine-object/src-ex/TestWatcher.java deleted file mode 100644 index d15e68871c..0000000000 --- a/test/980-redefine-object/src-ex/TestWatcher.java +++ /dev/null @@ -1,25 +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. - */ - -package art.test; - -public class TestWatcher { - // NB This function is native since it is called in the Object.<init> method and so cannot cause - // any java allocations at all. The normal System.out.print* functions will cause allocations to - // occur so we cannot use them. This means the easiest way to report the object as being created - // is to go into native code and do it there. - public static native void NotifyConstructed(Object o); -} diff --git a/test/980-redefine-object/src/Main.java b/test/980-redefine-object/src/Main.java deleted file mode 100644 index 348951c4ba..0000000000 --- a/test/980-redefine-object/src/Main.java +++ /dev/null @@ -1,390 +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 java.util.ArrayList; -import java.util.Base64; -import java.util.LinkedList; - -public class Main { - - // TODO We should make this run on the RI. - /** - * This test cannot be run on the RI. - */ - private static final byte[] CLASS_BYTES = new byte[0]; - - // TODO It might be a good idea to replace this hard-coded Object definition with a - // retransformation based test. - /** - * Base64 encoding of the following smali file. - * - * .class public Ljava/lang/Object; - * .source "Object.java" - * # instance fields - * .field private transient shadow$_klass_:Ljava/lang/Class; - * .annotation system Ldalvik/annotation/Signature; - * value = { - * "Ljava/lang/Class", - * "<*>;" - * } - * .end annotation - * .end field - * - * .field private transient shadow$_monitor_:I - * # direct methods - * .method public constructor <init>()V - * .registers 1 - * .prologue - * invoke-static {p0}, Lart/test/TestWatcher;->NotifyConstructed(Ljava/lang/Object;)V - * return-void - * .end method - * - * .method static identityHashCode(Ljava/lang/Object;)I - * .registers 7 - * .prologue - * iget v0, p0, Ljava/lang/Object;->shadow$_monitor_:I - * const/high16 v3, -0x40000000 # -2.0f - * const/high16 v2, -0x80000000 - * const v1, 0xfffffff - * const/high16 v4, -0x40000000 # -2.0f - * and-int/2addr v4, v0 - * const/high16 v5, -0x80000000 - * if-ne v4, v5, :cond_15 - * const v4, 0xfffffff - * and-int/2addr v4, v0 - * return v4 - * :cond_15 - * invoke-static {p0}, Ljava/lang/Object;->identityHashCodeNative(Ljava/lang/Object;)I - * move-result v4 - * return v4 - * .end method - * - * .method private static native identityHashCodeNative(Ljava/lang/Object;)I - * .annotation build Ldalvik/annotation/optimization/FastNative; - * .end annotation - * .end method - * - * .method private native internalClone()Ljava/lang/Object; - * .annotation build Ldalvik/annotation/optimization/FastNative; - * .end annotation - * .end method - * - * - * # virtual methods - * .method protected clone()Ljava/lang/Object; - * .registers 4 - * .annotation system Ldalvik/annotation/Throws; - * value = { - * Ljava/lang/CloneNotSupportedException; - * } - * .end annotation - * - * .prologue - * instance-of v0, p0, Ljava/lang/Cloneable; - * if-nez v0, :cond_2d - * new-instance v0, Ljava/lang/CloneNotSupportedException; - * new-instance v1, Ljava/lang/StringBuilder; - * invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V - * const-string/jumbo v2, "Class " - * invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; - * move-result-object v1 - * invoke-virtual {p0}, Ljava/lang/Object;->getClass()Ljava/lang/Class; - * move-result-object v2 - * invoke-virtual {v2}, Ljava/lang/Class;->getName()Ljava/lang/String; - * move-result-object v2 - * invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; - * move-result-object v1 - * const-string/jumbo v2, " doesn\'t implement Cloneable" - * invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; - * move-result-object v1 - * invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; - * move-result-object v1 - * invoke-direct {v0, v1}, Ljava/lang/CloneNotSupportedException;-><init>(Ljava/lang/String;)V - * throw v0 - * :cond_2d - * invoke-direct {p0}, Ljava/lang/Object;->internalClone()Ljava/lang/Object; - * move-result-object v0 - * return-object v0 - * .end method - * - * .method public equals(Ljava/lang/Object;)Z - * .registers 3 - * .prologue - * if-ne p0, p1, :cond_4 - * const/4 v0, 0x1 - * :goto_3 - * return v0 - * :cond_4 - * const/4 v0, 0x0 - * goto :goto_3 - * .end method - * - * .method protected finalize()V - * .registers 1 - * .annotation system Ldalvik/annotation/Throws; - * value = { - * Ljava/lang/Throwable; - * } - * .end annotation - * .prologue - * return-void - * .end method - * - * .method public final getClass()Ljava/lang/Class; - * .registers 2 - * .annotation system Ldalvik/annotation/Signature; - * value = { - * "()", - * "Ljava/lang/Class", - * "<*>;" - * } - * .end annotation - * .prologue - * iget-object v0, p0, Ljava/lang/Object;->shadow$_klass_:Ljava/lang/Class; - * return-object v0 - * .end method - * - * .method public hashCode()I - * .registers 2 - * .prologue - * invoke-static {p0}, Ljava/lang/Object;->identityHashCode(Ljava/lang/Object;)I - * move-result v0 - * return v0 - * .end method - * - * .method public final native notify()V - * .annotation build Ldalvik/annotation/optimization/FastNative; - * .end annotation - * .end method - * - * .method public final native notifyAll()V - * .annotation build Ldalvik/annotation/optimization/FastNative; - * .end annotation - * .end method - * - * .method public toString()Ljava/lang/String; - * .registers 3 - * .prologue - * new-instance v0, Ljava/lang/StringBuilder; - * invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V - * invoke-virtual {p0}, Ljava/lang/Object;->getClass()Ljava/lang/Class; - * move-result-object v1 - * invoke-virtual {v1}, Ljava/lang/Class;->getName()Ljava/lang/String; - * move-result-object v1 - * invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; - * move-result-object v0 - * const-string/jumbo v1, "@" - * invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; - * move-result-object v0 - * invoke-virtual {p0}, Ljava/lang/Object;->hashCode()I - * move-result v1 - * invoke-static {v1}, Ljava/lang/Integer;->toHexString(I)Ljava/lang/String; - * move-result-object v1 - * invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; - * move-result-object v0 - * invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; - * move-result-object v0 - * return-object v0 - * .end method - * - * .method public final native wait()V - * .annotation system Ldalvik/annotation/Throws; - * value = { - * Ljava/lang/InterruptedException; - * } - * .end annotation - * - * .annotation build Ldalvik/annotation/optimization/FastNative; - * .end annotation - * .end method - * - * .method public final wait(J)V - * .registers 4 - * .annotation system Ldalvik/annotation/Throws; - * value = { - * Ljava/lang/InterruptedException; - * } - * .end annotation - * .prologue - * const/4 v0, 0x0 - * invoke-virtual {p0, p1, p2, v0}, Ljava/lang/Object;->wait(JI)V - * return-void - * .end method - * - * .method public final native wait(JI)V - * .annotation system Ldalvik/annotation/Throws; - * value = { - * Ljava/lang/InterruptedException; - * } - * .end annotation - * - * .annotation build Ldalvik/annotation/optimization/FastNative; - * .end annotation - * .end method - */ - private static final byte[] DEX_BYTES = Base64.getDecoder().decode( - "ZGV4CjAzNQDUlMR9j03MYuOKekKs2p7zJzu2IfDb7RlMCgAAcAAAAHhWNBIAAAAAAAAAAIgJAAA6" + - "AAAAcAAAABEAAABYAQAADQAAAJwBAAACAAAAOAIAABYAAABIAgAAAQAAAPgCAAA0BwAAGAMAABgD" + - "AAA2AwAAOgMAAEADAABIAwAASwMAAFMDAABWAwAAWgMAAF0DAABgAwAAZAMAAGgDAACAAwAAnwMA" + - "ALsDAADoAwAA+gMAAA0EAAA1BAAATAQAAGEEAACDBAAAlwQAAKsEAADGBAAA3QQAAPAEAAD9BAAA" + - "AAUAAAQFAAAJBQAADQUAABAFAAAUBQAAHAUAACMFAAArBQAANQUAAD8FAABIBQAAUgUAAGQFAAB8" + - "BQAAiwUAAJUFAACnBQAAugUAAM0FAADVBQAA3QUAAOgFAADtBQAA/QUAAA8GAAAcBgAAJgYAAC0G" + - "AAAGAAAACAAAAAwAAAANAAAADgAAAA8AAAARAAAAEgAAABMAAAAUAAAAFQAAABYAAAAXAAAAGAAA" + - "ABkAAAAcAAAAIAAAAAYAAAAAAAAAAAAAAAcAAAAAAAAAPAYAAAkAAAAGAAAAAAAAAAkAAAALAAAA" + - "AAAAAAkAAAAMAAAAAAAAAAoAAAAMAAAARAYAAAsAAAANAAAAVAYAABwAAAAPAAAAAAAAAB0AAAAP" + - "AAAATAYAAB4AAAAPAAAANAYAAB8AAAAPAAAAPAYAAB8AAAAPAAAAVAYAACEAAAAQAAAAPAYAAAsA" + - "BgA0AAAACwAAADUAAAACAAoAGgAAAAYABAAnAAAABwALAAMAAAAJAAUANgAAAAsABwADAAAACwAD" + - "ACMAAAALAAwAJAAAAAsABwAlAAAACwACACYAAAALAAAAKAAAAAsAAQApAAAACwABACoAAAALAAMA" + - "KwAAAAsABwAxAAAACwAHADIAAAALAAQANwAAAAsABwA5AAAACwAIADkAAAALAAkAOQAAAA0ABwAD" + - "AAAADQAGACIAAAANAAQANwAAAAsAAAABAAAA/////wAAAAAbAAAA0AYAAD4JAAAAAAAAHCBkb2Vz" + - "bid0IGltcGxlbWVudCBDbG9uZWFibGUAAigpAAQ8Kj47AAY8aW5pdD4AAUAABkNsYXNzIAABSQAC" + - "SUwAAUoAAUwAAkxJAAJMTAAWTGFydC90ZXN0L1Rlc3RXYXRjaGVyOwAdTGRhbHZpay9hbm5vdGF0" + - "aW9uL1NpZ25hdHVyZTsAGkxkYWx2aWsvYW5ub3RhdGlvbi9UaHJvd3M7ACtMZGFsdmlrL2Fubm90" + - "YXRpb24vb3B0aW1pemF0aW9uL0Zhc3ROYXRpdmU7ABBMamF2YS9sYW5nL0NsYXNzABFMamF2YS9s" + - "YW5nL0NsYXNzOwAmTGphdmEvbGFuZy9DbG9uZU5vdFN1cHBvcnRlZEV4Y2VwdGlvbjsAFUxqYXZh" + - "L2xhbmcvQ2xvbmVhYmxlOwATTGphdmEvbGFuZy9JbnRlZ2VyOwAgTGphdmEvbGFuZy9JbnRlcnJ1" + - "cHRlZEV4Y2VwdGlvbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABlM" + - "amF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7ABVMamF2YS9sYW5nL1Rocm93YWJsZTsAEU5vdGlmeUNv" + - "bnN0cnVjdGVkAAtPYmplY3QuamF2YQABVgACVkoAA1ZKSQACVkwAAVoAAlpMAAZhcHBlbmQABWNs" + - "b25lAAZlcXVhbHMACGZpbmFsaXplAAhnZXRDbGFzcwAHZ2V0TmFtZQAIaGFzaENvZGUAEGlkZW50" + - "aXR5SGFzaENvZGUAFmlkZW50aXR5SGFzaENvZGVOYXRpdmUADWludGVybmFsQ2xvbmUACGxvY2tX" + - "b3JkABBsb2NrV29yZEhhc2hNYXNrABFsb2NrV29yZFN0YXRlSGFzaAARbG9ja1dvcmRTdGF0ZU1h" + - "c2sABm1pbGxpcwAGbm90aWZ5AAlub3RpZnlBbGwAA29iagAOc2hhZG93JF9rbGFzc18AEHNoYWRv" + - "dyRfbW9uaXRvcl8AC3RvSGV4U3RyaW5nAAh0b1N0cmluZwAFdmFsdWUABHdhaXQAAAIAAAABAAAA" + - "AQAAAAsAAAABAAAAAAAAAAEAAAABAAAAAQAAAAwAAgQBOBwBGAcCBAE4HAEYCgIDATgcAhcQFwIC" + - "BAE4HAEYDgAFAAIDATgcAxcBFxAXAgAAAAAAAAAAAAEAAABaBgAAAgAAAGIGAAB8BgAAAQAAAGIG" + - "AAABAAAAagYAAAEAAAB0BgAAAQAAAHwGAAABAAAAfwYAAAAAAAABAAAACgAAAAAAAAAAAAAAsAYA" + - "AAUAAACUBgAABwAAALgGAAAIAAAAyAYAAAsAAADABgAADAAAAMAGAAANAAAAwAYAAA4AAADABgAA" + - "EAAAAJwGAAARAAAAqAYAABIAAACcBgAAKAAHDgBwATQHDi0DAC0BLQMDMAEtAwIvATwDAS4BeFsA" + - "7AEABw5LARoPOsYArAEBNAcOAMUEAAcOAEEABw4AaAAHDgCRAgAHDgCmAwExBw5LAAAAAQABAAEA" + - "AAA4BwAABAAAAHEQAAAAAA4ABwABAAEAAAA9BwAAGgAAAFJgAQAVAwDAFQIAgBQB////DxUEAMC1" + - "BBUFAIAzVAcAFAT///8PtQQPBHEQCwAGAAoEDwQEAAEAAgAAAFkHAAAyAAAAIDAIADkAKwAiAAcA" + - "IgENAHAQEwABABsCBQAAAG4gFAAhAAwBbhAIAAMADAJuEAEAAgAMAm4gFAAhAAwBGwIAAAAAbiAU" + - "ACEADAFuEBUAAQAMAXAgAgAQACcAcBAMAAMADAARAAMAAgAAAAAAZQcAAAYAAAAzIQQAEhAPABIA" + - "KP4BAAEAAAAAAGwHAAABAAAADgAAAAIAAQAAAAAAcgcAAAMAAABUEAAAEQAAAAIAAQABAAAAdwcA" + - "AAUAAABxEAoAAQAKAA8AAAADAAEAAgAAAHwHAAApAAAAIgANAHAQEwAAAG4QCAACAAwBbhABAAEA" + - "DAFuIBQAEAAMABsBBAAAAG4gFAAQAAwAbhAJAAIACgFxEAMAAQAMAW4gFAAQAAwAbhAVAAAADAAR" + - "AAAABAADAAQAAACCBwAABQAAABIAbkASACEDDgAAAgQLAIIBAYIBBIGABIwPBgikDwGKAgABggIA" + - "BQToDwEB3BABBPgQARGMEQEBpBEEkQIAAZECAAEBwBEBkQIAARGkEgGRAgAAABAAAAAAAAAAAQAA" + - "AAAAAAABAAAAOgAAAHAAAAACAAAAEQAAAFgBAAADAAAADQAAAJwBAAAEAAAAAgAAADgCAAAFAAAA" + - "FgAAAEgCAAAGAAAAAQAAAPgCAAACIAAAOgAAABgDAAABEAAABQAAADQGAAAEIAAABgAAAFoGAAAD" + - "EAAACQAAAIwGAAAGIAAAAQAAANAGAAADIAAACQAAADgHAAABIAAACQAAAIwHAAAAIAAAAQAAAD4J" + - "AAAAEAAAAQAAAIgJAAA="); - - private static final String LISTENER_LOCATION = - System.getenv("DEX_LOCATION") + "/980-redefine-object-ex.jar"; - - public static void main(String[] args) { - doTest(); - } - - private static void ensureTestWatcherInitialized() { - try { - // Make sure the TestWatcher class can be found from the Object <init> function. - addToBootClassLoader(LISTENER_LOCATION); - // Load TestWatcher from the bootclassloader and make sure it is initialized. - Class<?> testwatcher_class = Class.forName("art.test.TestWatcher", true, null); - // Bind the native functions of testwatcher_class. - bindFunctionsForClass(testwatcher_class); - } catch (Exception e) { - throw new Error("Exception while making testwatcher", e); - } - } - - // NB This function will cause 2 objects of type "Ljava/nio/HeapCharBuffer;" and - // "Ljava/nio/HeapCharBuffer;" to be allocated each time it is called. - private static void safePrintln(Object o) { - System.out.flush(); - System.out.print("\t" + o + "\n"); - System.out.flush(); - } - - private static void throwFrom(int depth) throws Exception { - if (depth <= 0) { - throw new Exception("Throwing the exception"); - } else { - throwFrom(depth - 1); - } - } - - public static void doTest() { - safePrintln("Initializing and loading the TestWatcher class that will (eventually) be " + - "notified of object allocations"); - // Make sure the TestWatcher class is initialized before we do anything else. - ensureTestWatcherInitialized(); - safePrintln("Allocating an j.l.Object before redefining Object class"); - // Make sure these aren't shown. - Object o = new Object(); - safePrintln("Allocating a Transform before redefining Object class"); - Transform t = new Transform(); - - // Redefine the Object Class. - safePrintln("Redefining the Object class to add a hook into the <init> method"); - doCommonClassRedefinition(Object.class, CLASS_BYTES, DEX_BYTES); - - safePrintln("Allocating an j.l.Object after redefining Object class"); - Object o2 = new Object(); - safePrintln("Allocating a Transform after redefining Object class"); - Transform t2 = new Transform(); - - // This shouldn't cause the Object constructor to be run. - safePrintln("Allocating an int[] after redefining Object class"); - int[] abc = new int[12]; - - // Try adding stuff to an array list. - safePrintln("Allocating an array list"); - ArrayList<Object> al = new ArrayList<>(); - safePrintln("Adding a bunch of stuff to the array list"); - al.add(new Object()); - al.add(new Object()); - al.add(o2); - al.add(o); - al.add(t); - al.add(t2); - al.add(new Transform()); - - // Try adding stuff to a LinkedList - safePrintln("Allocating a linked list"); - LinkedList<Object> ll = new LinkedList<>(); - safePrintln("Adding a bunch of stuff to the linked list"); - ll.add(new Object()); - ll.add(new Object()); - ll.add(o2); - ll.add(o); - ll.add(t); - ll.add(t2); - ll.add(new Transform()); - - // Try making an exception. - safePrintln("Throwing from down 4 stack frames"); - try { - throwFrom(4); - } catch (Exception e) { - safePrintln("Exception caught."); - } - - safePrintln("Finishing test!"); - } - - private static native void addToBootClassLoader(String s); - - private static native void bindFunctionsForClass(Class<?> target); - - // Transforms the class - private static native void doCommonClassRedefinition(Class<?> target, - byte[] class_file, - byte[] dex_file); -} diff --git a/test/980-redefine-object/src/Transform.java b/test/980-redefine-object/src/Transform.java deleted file mode 100644 index 23f67d96c7..0000000000 --- a/test/980-redefine-object/src/Transform.java +++ /dev/null @@ -1,17 +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. - */ - -class Transform { } diff --git a/test/Android.bp b/test/Android.bp index 3bb3ef8de7..594cce2a6e 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -275,7 +275,6 @@ art_cc_defaults { "936-search-onload/search_onload.cc", "944-transform-classloaders/classloader.cc", "945-obsolete-native/obsolete_native.cc", - "980-redefine-object/redefine_object.cc", ], shared_libs: [ "libbase", diff --git a/test/ti-agent/common_helper.cc b/test/ti-agent/common_helper.cc index 6316a9c368..4ddd0aafb0 100644 --- a/test/ti-agent/common_helper.cc +++ b/test/ti-agent/common_helper.cc @@ -520,14 +520,11 @@ void BindFunctions(jvmtiEnv* jenv, JNIEnv* env, const char* class_name) { LOG(FATAL) << "Could not load " << class_name; } } - BindFunctionsOnClass(jenv, env, klass.get()); -} -void BindFunctionsOnClass(jvmtiEnv* jenv, JNIEnv* env, jclass klass) { // Use JVMTI to get the methods. jint method_count; jmethodID* methods; - jvmtiError methods_result = jenv->GetClassMethods(klass, &method_count, &methods); + jvmtiError methods_result = jenv->GetClassMethods(klass.get(), &method_count, &methods); if (methods_result != JVMTI_ERROR_NONE) { LOG(FATAL) << "Could not get methods"; } @@ -541,7 +538,7 @@ void BindFunctionsOnClass(jvmtiEnv* jenv, JNIEnv* env, jclass klass) { } constexpr jint kNative = static_cast<jint>(kAccNative); if ((modifiers & kNative) != 0) { - BindMethod(jenv, env, klass, methods[i]); + BindMethod(jenv, env, klass.get(), methods[i]); } } diff --git a/test/ti-agent/common_helper.h b/test/ti-agent/common_helper.h index f10356dcbb..0a316edc7b 100644 --- a/test/ti-agent/common_helper.h +++ b/test/ti-agent/common_helper.h @@ -81,7 +81,6 @@ bool JvmtiErrorToException(JNIEnv* env, jvmtiError error); // // This will abort on failure. void BindFunctions(jvmtiEnv* jvmti_env, JNIEnv* env, const char* class_name); -void BindFunctionsOnClass(jvmtiEnv* jvmti_env, JNIEnv* env, jclass klass); } // namespace art |