Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/runtime/dex/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 82 kB image not shown  

Quelle  dex_file_annotations.cc

  Sprache: C
 

/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "dex_file_annotations.h"

#include <stdlib.h>

#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "art_field-inl.h"
#include "art_method-alloc-inl.h"
#include "base/sdk_version.h"
#include "class_linker-inl.h"
#include "class_root-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_types.h"
#include "dex/dex_instruction-inl.h"
#include "jni/jni_internal.h"
#include "jvalue-inl.h"
#include "mirror/array-alloc-inl.h"
#include "mirror/class-alloc-inl.h"
#include "mirror/field.h"
#include "mirror/method.h"
#include "mirror/object_array-alloc-inl.h"
#include "mirror/object_array-inl.h"
#include "oat/oat_file.h"
#include "obj_ptr-inl.h"
#include "reflection.h"
#include "thread.h"
#include "well_known_classes.h"

namespace art HIDDEN {

using android::base::StringPrintf;

using dex::AnnotationItem;
using dex::AnnotationSetItem;
using dex::AnnotationSetRefItem;
using dex::AnnotationSetRefList;
using dex::AnnotationsDirectoryItem;
using dex::FieldAnnotationsItem;
using dex::MethodAnnotationsItem;
using dex::ParameterAnnotationsItem;

struct DexFile::AnnotationValue {
  JValue value_;
  uint8_t type_;
};

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 dex::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 dex::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 dex::ClassDef* class_def_;

  DISALLOW_COPY_AND_ASSIGN(ClassData);
};

ObjPtr<mirror::Object> CreateAnnotationMember(const ClassData& klass,
                                              Handle<mirror::Class> annotation_class,
                                              const uint8_t** annotation)
    REQUIRES_SHARED(Locks::mutator_lock_);

bool IsVisibilityCompatible(DexFile::DexVisibility actual, DexFile::DexVisibility expected) {
  if (expected == DexFile::DexVisibility::kRuntime) {
    if (IsSdkVersionSetAndAtMost(Runtime::Current()->GetTargetSdkVersion(), SdkVersion::kM)) {
      return actual == DexFile::DexVisibility::kRuntime || actual == DexFile::DexVisibility::kBuild;
    }
  }
  return actual == expected;
}

static const AnnotationSetItem* FindAnnotationSetForField(const DexFile& dex_file,
                                                          const dex::ClassDef& class_def,
                                                          uint32_t field_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationsDirectoryItem* annotations_dir = dex_file.GetAnnotationsDirectory(class_def);
  if (annotations_dir == nullptr) {
    return nullptr;
  }
  const FieldAnnotationsItem* field_annotations = dex_file.GetFieldAnnotations(annotations_dir);
  if (field_annotations == nullptr) {
    return nullptr;
  }
  uint32_t field_count = annotations_dir->fields_size_;
  for (uint32_t i = 0; i < field_count; ++i) {
    if (field_annotations[i].field_idx_ == field_index) {
      return dex_file.GetFieldAnnotationSetItem(field_annotations[i]);
    }
  }
  return nullptr;
}

static const AnnotationSetItem* FindAnnotationSetForField(ArtField* field)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ObjPtr<mirror::Class> klass = field->GetDeclaringClass();
  const dex::ClassDef* class_def = klass->GetClassDef();
  if (class_def == nullptr) {
    DCHECK(klass->IsProxyClass());
    return nullptr;
  }
  return FindAnnotationSetForField(*field->GetDexFile(), *class_def, field->GetDexFieldIndex());
}

const AnnotationItem* SearchAnnotationSet(const DexFile& dex_file,
                                          const AnnotationSetItem* annotation_set,
                                          const char* descriptor,
                                          DexFile::DexVisibility visibility)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationItem* result = nullptr;
  for (uint32_t i = 0; i < annotation_set->size_; ++i) {
    const AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
    if (!IsVisibilityCompatible(static_cast<DexFile::DexVisibility>(annotation_item->visibility_),
                                visibility)) {
      continue;
    }
    const uint8_t* annotation = annotation_item->annotation_;
    uint32_t type_index = DecodeUnsignedLeb128(&annotation);

    if (strcmp(descriptor, dex_file.GetTypeDescriptor(dex::TypeIndex(type_index))) == 0{
      result = annotation_item;
      break;
    }
  }
  return result;
}

inline static void SkipEncodedValueHeaderByte(const uint8_t** annotation_ptr) {
  (*annotation_ptr)++;
}

bool SkipAnnotationValue(const DexFile& dex_file, const uint8_t** annotation_ptr)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const uint8_t* annotation = *annotation_ptr;
  uint8_t header_byte = *(annotation++);
  uint8_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask;
  uint8_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift;
  int32_t width = value_arg + 1;

  switch (value_type) {
    case DexFile::kDexAnnotationByte:
    case DexFile::kDexAnnotationShort:
    case DexFile::kDexAnnotationChar:
    case DexFile::kDexAnnotationInt:
    case DexFile::kDexAnnotationLong:
    case DexFile::kDexAnnotationFloat:
    case DexFile::kDexAnnotationDouble:
    case DexFile::kDexAnnotationMethodType:
    case DexFile::kDexAnnotationMethodHandle:
    case DexFile::kDexAnnotationString:
    case DexFile::kDexAnnotationType:
    case DexFile::kDexAnnotationMethod:
    case DexFile::kDexAnnotationField:
    case DexFile::kDexAnnotationEnum:
      break;
    case DexFile::kDexAnnotationArray:
    {
      uint32_t size = DecodeUnsignedLeb128(&annotation);
      for (; size != 0u; --size) {
        if (!SkipAnnotationValue(dex_file, &annotation)) {
          return false;
        }
      }
      width = 0;
      break;
    }
    case DexFile::kDexAnnotationAnnotation:
    {
      DecodeUnsignedLeb128(&annotation);  // unused type_index
      uint32_t size = DecodeUnsignedLeb128(&annotation);
      for (; size != 0u; --size) {
        DecodeUnsignedLeb128(&annotation);  // unused element_name_index
        if (!SkipAnnotationValue(dex_file, &annotation)) {
          return false;
        }
      }
      width = 0;
      break;
    }
    case DexFile::kDexAnnotationBoolean:
    case DexFile::kDexAnnotationNull:
      width = 0;
      break;
    default:
      LOG(FATAL) << StringPrintf("Bad annotation element value byte 0x%02x", value_type);
      UNREACHABLE();
  }

  annotation += width;
  *annotation_ptr = annotation;
  return true;
}

const uint8_t* SearchEncodedAnnotation(const DexFile& dex_file,
                                       const uint8_t* annotation,
                                       const char* name)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DecodeUnsignedLeb128(&annotation);  // unused type_index
  uint32_t size = DecodeUnsignedLeb128(&annotation);

  while (size != 0) {
    uint32_t element_name_index = DecodeUnsignedLeb128(&annotation);
    const char* element_name =
        dex_file.GetStringData(dex_file.GetStringId(dex::StringIndex(element_name_index)));
    if (strcmp(name, element_name) == 0) {
      return annotation;
    }
    SkipAnnotationValue(dex_file, &annotation);
    size--;
  }
  return nullptr;
}

static const AnnotationSetItem* FindAnnotationSetForMethod(const DexFile& dex_file,
                                                           const dex::ClassDef& class_def,
                                                           uint32_t method_index) {
  const AnnotationsDirectoryItem* annotations_dir = dex_file.GetAnnotationsDirectory(class_def);
  if (annotations_dir == nullptr) {
    return nullptr;
  }
  const MethodAnnotationsItem* method_annotations = dex_file.GetMethodAnnotations(annotations_dir);
  if (method_annotations == nullptr) {
    return nullptr;
  }
  uint32_t method_count = annotations_dir->methods_size_;
  for (uint32_t i = 0; i < method_count; ++i) {
    if (method_annotations[i].method_idx_ == method_index) {
      return dex_file.GetMethodAnnotationSetItem(method_annotations[i]);
    }
  }
  return nullptr;
}

inline const AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  if (method->IsProxyMethod()) {
    return nullptr;
  }
  return FindAnnotationSetForMethod(*method->GetDexFile(),
                                    method->GetClassDef(),
                                    method->GetDexMethodIndex());
}

const ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* method)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile* dex_file = method->GetDexFile();
  const AnnotationsDirectoryItem* annotations_dir =
      dex_file->GetAnnotationsDirectory(method->GetClassDef());
  if (annotations_dir == nullptr) {
    return nullptr;
  }
  const ParameterAnnotationsItem* parameter_annotations =
      dex_file->GetParameterAnnotations(annotations_dir);
  if (parameter_annotations == nullptr) {
    return nullptr;
  }
  uint32_t method_index = method->GetDexMethodIndex();
  uint32_t parameter_count = annotations_dir->parameters_size_;
  for (uint32_t i = 0; i < parameter_count; ++i) {
    if (parameter_annotations[i].method_idx_ == method_index) {
      return ¶meter_annotations[i];
    }
  }
  return nullptr;
}

static const AnnotationSetItem* FindAnnotationSetForClass(const ClassData& klass)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  const dex::ClassDef* class_def = klass.GetClassDef();
  if (class_def == nullptr) {
    DCHECK(klass.GetRealClass()->IsProxyClass());
    return nullptr;
  }
  const AnnotationsDirectoryItem* annotations_dir = dex_file.GetAnnotationsDirectory(*class_def);
  if (annotations_dir == nullptr) {
    return nullptr;
  }
  return dex_file.GetClassAnnotationSet(annotations_dir);
}

ObjPtr<mirror::Object> ProcessEncodedAnnotation(const ClassData& 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();
  StackHandleScope<4> hs(self);
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  Handle<mirror::Class> annotation_class(hs.NewHandle(
      class_linker->ResolveType(dex::TypeIndex(type_index),
                                hs.NewHandle(klass.GetDexCache()),
                                hs.NewHandle(klass.GetClassLoader()))));
  if (annotation_class == nullptr) {
    LOG(INFO) << "Unable to resolve " << klass.GetRealClass()->PrettyClass()
              << " annotation class " << type_index;
    DCHECK(Thread::Current()->IsExceptionPending());
    Thread::Current()->ClearException();
    return nullptr;
  }

  ObjPtr<mirror::Class> annotation_member_array_class =
      WellKnownClasses::ToClass(WellKnownClasses::libcore_reflect_AnnotationMember__array);
  if (annotation_member_array_class == nullptr) {
    return nullptr;
  }
  ObjPtr<mirror::ObjectArray<mirror::Object>> element_array = nullptr;
  if (size > 0) {
    element_array =
        mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_member_array_class, size);
    if (element_array == nullptr) {
      LOG(ERROR) << "Failed to allocate annotation member array (" << size << " elements)";
      return nullptr;
    }
  }

  Handle<mirror::ObjectArray<mirror::Object>> h_element_array(hs.NewHandle(element_array));
  for (uint32_t i = 0; i < size; ++i) {
    ObjPtr<mirror::Object> new_member = CreateAnnotationMember(klass, annotation_class, annotation);
    if (new_member == nullptr) {
      return nullptr;
    }
    h_element_array->SetWithoutChecks<false>(i, new_member);
  }

  ArtMethod* create_annotation_method =
      WellKnownClasses::libcore_reflect_AnnotationFactory_createAnnotation;
  ObjPtr<mirror::Object> result = create_annotation_method->InvokeStatic<'L''L''L'>(
      self, annotation_class.Get(), h_element_array.Get());
  if (self->IsExceptionPending()) {
    LOG(INFO) << "Exception in AnnotationFactory.createAnnotation";
    return nullptr;
  }

  return result;
}

template <bool kTransactionActive>
bool ProcessAnnotationValue(const ClassData& 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();
  Thread* self = Thread::Current();
  ObjPtr<mirror::Object> element_object = nullptr;
  bool set_object = false;
  Primitive::Type primitive_type = Primitive::kPrimVoid;
  const uint8_t* annotation = *annotation_ptr;
  uint8_t header_byte = *(annotation++);
  uint8_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask;
  uint8_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift;
  int32_t width = value_arg + 1;
  annotation_value->type_ = value_type;

  switch (value_type) {
    case DexFile::kDexAnnotationByte:
      annotation_value->value_.SetB(
          static_cast<int8_t>(DexFile::ReadSignedInt(annotation, value_arg)));
      primitive_type = Primitive::kPrimByte;
      break;
    case DexFile::kDexAnnotationShort:
      annotation_value->value_.SetS(
          static_cast<int16_t>(DexFile::ReadSignedInt(annotation, value_arg)));
      primitive_type = Primitive::kPrimShort;
      break;
    case DexFile::kDexAnnotationChar:
      annotation_value->value_.SetC(
          static_cast<uint16_t>(DexFile::ReadUnsignedInt(annotation, value_arg, false)));
      primitive_type = Primitive::kPrimChar;
      break;
    case DexFile::kDexAnnotationInt:
      annotation_value->value_.SetI(DexFile::ReadSignedInt(annotation, value_arg));
      primitive_type = Primitive::kPrimInt;
      break;
    case DexFile::kDexAnnotationLong:
      annotation_value->value_.SetJ(DexFile::ReadSignedLong(annotation, value_arg));
      primitive_type = Primitive::kPrimLong;
      break;
    case DexFile::kDexAnnotationFloat:
      annotation_value->value_.SetI(DexFile::ReadUnsignedInt(annotation, value_arg, true));
      primitive_type = Primitive::kPrimFloat;
      break;
    case DexFile::kDexAnnotationDouble:
      annotation_value->value_.SetJ(DexFile::ReadUnsignedLong(annotation, value_arg, true));
      primitive_type = Primitive::kPrimDouble;
      break;
    case DexFile::kDexAnnotationBoolean:
      annotation_value->value_.SetZ(value_arg != 0);
      primitive_type = Primitive::kPrimBoolean;
      width = 0;
      break;
    case DexFile::kDexAnnotationMethodType:
    case DexFile::kDexAnnotationMethodHandle:
      // These annotations are unexpected here. Don't process them.
      LOG(WARNING) << StringPrintf("Unexpected annotation of type 0x%02x", value_type);
      return false;
    case DexFile::kDexAnnotationString: {
      uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        StackHandleScope<1> hs(self);
        element_object = Runtime::Current()->GetClassLinker()->ResolveString(
            dex::StringIndex(index), hs.NewHandle(klass.GetDexCache()));
        set_object = true;
        if (element_object == nullptr) {
          return false;
        }
      }
      break;
    }
    case DexFile::kDexAnnotationType: {
      uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        dex::TypeIndex type_index(index);
        StackHandleScope<2> hs(self);
        element_object = Runtime::Current()->GetClassLinker()->ResolveType(
            type_index,
            hs.NewHandle(klass.GetDexCache()),
            hs.NewHandle(klass.GetClassLoader()));
        set_object = true;
        if (element_object == nullptr) {
          CHECK(self->IsExceptionPending());
          if (result_style == DexFile::kAllObjects) {
            const char* msg = dex_file.GetTypeDescriptor(type_index);
            self->ThrowNewWrappedException("Ljava/lang/TypeNotPresentException;", msg);
            element_object = self->GetException();
            self->ClearException();
          } else {
            return false;
          }
        }
      }
      break;
    }
    case DexFile::kDexAnnotationMethod: {
      uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
        StackHandleScope<2> hs(self);
        ArtMethod* method = class_linker->ResolveMethodId(
            index,
            hs.NewHandle(klass.GetDexCache()),
            hs.NewHandle(klass.GetClassLoader()));
        if (method == nullptr) {
          return false;
        }
        PointerSize pointer_size = class_linker->GetImagePointerSize();
        set_object = true;
        if (method->IsConstructor()) {
          element_object = (pointer_size == PointerSize::k64)
              ? mirror::Constructor::CreateFromArtMethod<PointerSize::k64>(self, method)
              : mirror::Constructor::CreateFromArtMethod<PointerSize::k32>(self, method);
        } else {
          element_object = (pointer_size == PointerSize::k64)
              ? mirror::Method::CreateFromArtMethod<PointerSize::k64>(self, method)
              : mirror::Method::CreateFromArtMethod<PointerSize::k32>(self, method);
        }
        if (element_object == nullptr) {
          return false;
        }
      }
      break;
    }
    case DexFile::kDexAnnotationField: {
      uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        StackHandleScope<2> hs(self);
        ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(
            index,
            hs.NewHandle(klass.GetDexCache()),
            hs.NewHandle(klass.GetClassLoader()));
        if (field == nullptr) {
          return false;
        }
        set_object = true;
        element_object = mirror::Field::CreateFromArtField(self, field, true);
        if (element_object == nullptr) {
          return false;
        }
      }
      break;
    }
    case DexFile::kDexAnnotationEnum: {
      uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        StackHandleScope<3> hs(self);
        ArtField* enum_field = Runtime::Current()->GetClassLinker()->ResolveField(
            index,
            hs.NewHandle(klass.GetDexCache()),
            hs.NewHandle(klass.GetClassLoader()),
            true);
        if (enum_field == nullptr) {
          return false;
        } else {
          Handle<mirror::Class> field_class(hs.NewHandle(enum_field->GetDeclaringClass()));
          Runtime::Current()->GetClassLinker()->EnsureInitialized(self, field_class, truetrue);
          element_object = enum_field->GetObject(field_class.Get());
          set_object = true;
        }
      }
      break;
    }
    case DexFile::kDexAnnotationArray:
      if (result_style == DexFile::kAllRaw || array_class == nullptr) {
        return false;
      } else {
        ScopedObjectAccessUnchecked soa(self);
        StackHandleScope<2> hs(self);
        uint32_t size = DecodeUnsignedLeb128(&annotation);
        Handle<mirror::Class> component_type(hs.NewHandle(array_class->GetComponentType()));
        Handle<mirror::Array> new_array(hs.NewHandle(mirror::Array::Alloc(
            self, array_class.Get(), size, array_class->GetComponentSizeShift(),
            Runtime::Current()->GetHeap()->GetCurrentAllocator())));
        if (new_array == nullptr) {
          LOG(ERROR) << "Annotation element array allocation failed with size " << size;
          return false;
        }
        DexFile::AnnotationValue new_annotation_value;
        for (uint32_t i = 0; i < size; ++i) {
          if (!ProcessAnnotationValue<kTransactionActive>(klass,
                                                          &annotation,
                                                          &new_annotation_value,
                                                          component_type,
                                                          DexFile::kPrimitivesOrObjects)) {
            return false;
          }
          if (!component_type->IsPrimitive()) {
            ObjPtr<mirror::Object> obj = new_annotation_value.value_.GetL();
            new_array->AsObjectArray<mirror::Object>()->
                SetWithoutChecks<kTransactionActive>(i, obj);
          } else {
            switch (new_annotation_value.type_) {
              case DexFile::kDexAnnotationByte:
                new_array->AsByteArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetB());
                break;
              case DexFile::kDexAnnotationShort:
                new_array->AsShortArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetS());
                break;
              case DexFile::kDexAnnotationChar:
                new_array->AsCharArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetC());
                break;
              case DexFile::kDexAnnotationInt:
                new_array->AsIntArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetI());
                break;
              case DexFile::kDexAnnotationLong:
                new_array->AsLongArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetJ());
                break;
              case DexFile::kDexAnnotationFloat:
                new_array->AsFloatArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetF());
                break;
              case DexFile::kDexAnnotationDouble:
                new_array->AsDoubleArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetD());
                break;
              case DexFile::kDexAnnotationBoolean:
                new_array->AsBooleanArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetZ());
                break;
              default:
                LOG(FATAL) << "Found invalid annotation value type while building annotation array";
                return false;
            }
          }
        }
        element_object = new_array.Get();
        set_object = true;
        width = 0;
      }
      break;
    case DexFile::kDexAnnotationAnnotation:
      if (result_style == DexFile::kAllRaw) {
        return false;
      }
      element_object = ProcessEncodedAnnotation(klass, &annotation);
      if (element_object == nullptr) {
        return false;
      }
      set_object = true;
      width = 0;
      break;
    case DexFile::kDexAnnotationNull:
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(0);
      } else {
        CHECK(element_object == nullptr);
        set_object = true;
      }
      width = 0;
      break;
    default:
      LOG(ERROR) << StringPrintf("Bad annotation element value type 0x%02x", value_type);
      return false;
  }

  annotation += width;
  *annotation_ptr = annotation;

  if (result_style == DexFile::kAllObjects && primitive_type != Primitive::kPrimVoid) {
    element_object = BoxPrimitive(primitive_type, annotation_value->value_);
    set_object = true;
  }

  if (set_object) {
    annotation_value->value_.SetL(element_object);
  }

  return true;
}

ObjPtr<mirror::Object> CreateAnnotationMember(const ClassData& klass,
                                              Handle<mirror::Class> annotation_class,
                                              const uint8_t** annotation) {
  const DexFile& dex_file = klass.GetDexFile();
  Thread* self = Thread::Current();
  ScopedObjectAccessUnchecked soa(self);
  StackHandleScope<5> hs(self);
  uint32_t element_name_index = DecodeUnsignedLeb128(annotation);
  const char* name = dex_file.GetStringData(dex::StringIndex(element_name_index));

  PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
  ArtMethod* annotation_method =
      annotation_class->FindDeclaredVirtualMethodByName(name, pointer_size);
  if (annotation_method == nullptr) {
    return nullptr;
  }

  Handle<mirror::String> string_name =
      hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, name));
  if (UNLIKELY(string_name == nullptr)) {
    LOG(ERROR) << "Failed to allocate name for annotation member";
    return nullptr;
  }

  Handle<mirror::Class> method_return = hs.NewHandle(annotation_method->ResolveReturnType());
  if (UNLIKELY(method_return == nullptr)) {
    LOG(ERROR) << "Failed to resolve method return type for annotation member";
    return nullptr;
  }

  DexFile::AnnotationValue annotation_value;
  if (!ProcessAnnotationValue<false>(klass,
                                     annotation,
                                     &annotation_value,
                                     method_return,
                                     DexFile::kAllObjects)) {
    // TODO: Logging the error breaks run-test 005-annotations.
    // LOG(ERROR) << "Failed to process annotation value for annotation member";
    return nullptr;
  }
  Handle<mirror::Object> value_object = hs.NewHandle(annotation_value.value_.GetL());

  Handle<mirror::Method> method_object = hs.NewHandle((pointer_size == PointerSize::k64)
      ? mirror::Method::CreateFromArtMethod<PointerSize::k64>(self, annotation_method)
      : mirror::Method::CreateFromArtMethod<PointerSize::k32>(self, annotation_method));
  if (UNLIKELY(method_object == nullptr)) {
    LOG(ERROR) << "Failed to create method object for annotation member";
    return nullptr;
  }

  Handle<mirror::Object> new_member =
      WellKnownClasses::libcore_reflect_AnnotationMember_init->NewObject<'L''L''L''L'>(
          hs, self, string_name, value_object, method_return, method_object);
  if (new_member == nullptr) {
    DCHECK(self->IsExceptionPending());
    LOG(ERROR) << "Failed to create annotation member";
    return nullptr;
  }

  return new_member.Get();
}

const AnnotationItem* GetAnnotationItemFromAnnotationSet(const ClassData& klass,
                                                         const AnnotationSetItem* annotation_set,
                                                         DexFile::DexVisibility visibility,
                                                         Handle<mirror::Class> annotation_class)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  for (uint32_t i = 0; i < annotation_set->size_; ++i) {
    const AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
    if (!IsVisibilityCompatible(static_cast<DexFile::DexVisibility>(annotation_item->visibility_),
                                visibility)) {
      continue;
    }
    const uint8_t* annotation = annotation_item->annotation_;
    uint32_t type_index = DecodeUnsignedLeb128(&annotation);
    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    Thread* self = Thread::Current();
    StackHandleScope<2> hs(self);
    ObjPtr<mirror::Class> resolved_class = class_linker->ResolveType(
        dex::TypeIndex(type_index),
        hs.NewHandle(klass.GetDexCache()),
        hs.NewHandle(klass.GetClassLoader()));
    if (resolved_class == nullptr) {
      std::string temp;
      LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d",
                                   klass.GetRealClass()->GetDescriptor(&temp), type_index);
      CHECK(self->IsExceptionPending());
      self->ClearException();
      continue;
    }
    if (resolved_class == annotation_class.Get()) {
      return annotation_item;
    }
  }

  return nullptr;
}

ObjPtr<mirror::Object> GetAnnotationObjectFromAnnotationSet(const ClassData& klass,
                                                            const AnnotationSetItem* annotation_set,
                                                            DexFile::DexVisibility visibility,
                                                            Handle<mirror::Class> annotation_class)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
      klass, annotation_set, visibility, annotation_class);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  const uint8_t* annotation = annotation_item->annotation_;
  return ProcessEncodedAnnotation(klass, &annotation);
}

ObjPtr<mirror::Object> GetAnnotationValue(const ClassData& klass,
                                          const 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 uint8_t* annotation =
      SearchEncodedAnnotation(dex_file, annotation_item->annotation_, annotation_name);
  if (annotation == nullptr) {
    return nullptr;
  }
  DexFile::AnnotationValue annotation_value;
  bool result = Runtime::Current()->IsActiveTransaction()
      ? ProcessAnnotationValue<true>(klass,
                                     &annotation,
                                     &annotation_value,
                                     array_class,
                                     DexFile::kAllObjects)
      : ProcessAnnotationValue<false>(klass,
                                      &annotation,
                                      &annotation_value,
                                      array_class,
                                      DexFile::kAllObjects);
  if (!result) {
    return nullptr;
  }
  if (annotation_value.type_ != expected_type) {
    return nullptr;
  }
  return annotation_value.value_.GetL();
}

template<typename T>
static inline ObjPtr<mirror::ObjectArray<T>> GetAnnotationArrayValue(
                                     Handle<mirror::Class> klass,
                                     const char* annotation_name,
                                     const char* value_name)
            REQUIRES_SHARED(Locks::mutator_lock_) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(
      data.GetDexFile(), annotation_set, annotation_name, DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  StackHandleScope<1> hs(Thread::Current());
  Handle<mirror::Class> class_array_class =
      hs.NewHandle(GetClassRoot<mirror::ObjectArray<T>>());
  DCHECK(class_array_class != nullptr);
  ObjPtr<mirror::Object> obj = GetAnnotationValue(data,
                                                  annotation_item,
                                                  value_name,
                                                  class_array_class,
                                                  DexFile::kDexAnnotationArray);
  if (obj == nullptr) {
    return nullptr;
  }
  return obj->AsObjectArray<T>();
}

static ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureValue(
    const ClassData& klass,
    const AnnotationSetItem* annotation_set)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  StackHandleScope<1> hs(Thread::Current());
  const AnnotationItem* annotation_item = SearchAnnotationSet(
      dex_file, annotation_set, "Ldalvik/annotation/Signature;", DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  Handle<mirror::Class> string_array_class =
      hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::String>>());
  DCHECK(string_array_class != nullptr);
  ObjPtr<mirror::Object> obj =
      GetAnnotationValue(klass, annotation_item, "value", string_array_class,
                         DexFile::kDexAnnotationArray);
  if (obj == nullptr) {
    return nullptr;
  }
  return obj->AsObjectArray<mirror::String>();
}

ObjPtr<mirror::ObjectArray<mirror::Class>> GetThrowsValue(const ClassData& klass,
                                                          const AnnotationSetItem* annotation_set)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  const AnnotationItem* annotation_item = SearchAnnotationSet(
      dex_file, annotation_set, "Ldalvik/annotation/Throws;", DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  StackHandleScope<1> hs(Thread::Current());
  Handle<mirror::Class> class_array_class =
      hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::Class>>());
  DCHECK(class_array_class != nullptr);
  ObjPtr<mirror::Object> obj =
      GetAnnotationValue(klass, annotation_item, "value", class_array_class,
                         DexFile::kDexAnnotationArray);
  if (obj == nullptr) {
    return nullptr;
  }
  return obj->AsObjectArray<mirror::Class>();
}

ObjPtr<mirror::ObjectArray<mirror::Object>> ProcessAnnotationSet(
    const ClassData& klass,
    const AnnotationSetItem* annotation_set,
    DexFile::DexVisibility visibility)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  Thread* self = Thread::Current();
  StackHandleScope<2> hs(self);
  Handle<mirror::Class> annotation_array_class(hs.NewHandle(
      WellKnownClasses::ToClass(WellKnownClasses::java_lang_annotation_Annotation__array)));
  if (annotation_set == nullptr) {
    return mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get()0);
  }

  uint32_t size = annotation_set->size_;
  Handle<mirror::ObjectArray<mirror::Object>> result(hs.NewHandle(
      mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), size)));
  if (result == nullptr) {
    return nullptr;
  }

  uint32_t dest_index = 0;
  for (uint32_t i = 0; i < size; ++i) {
    const AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
    // Note that we do not use IsVisibilityCompatible here because older code
    // was correct for this case.
    if (static_cast<DexFile::DexVisibility>(annotation_item->visibility_) != visibility) {
      continue;
    }
    const uint8_t* annotation = annotation_item->annotation_;
    ObjPtr<mirror::Object> annotation_obj = ProcessEncodedAnnotation(klass, &annotation);
    if (annotation_obj != nullptr) {
      result->SetWithoutChecks<false>(dest_index, annotation_obj);
      ++dest_index;
    } else if (self->IsExceptionPending()) {
      return nullptr;
    }
  }

  if (dest_index == size) {
    return result.Get();
  }

  ObjPtr<mirror::ObjectArray<mirror::Object>> trimmed_result =
      mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), dest_index);
  if (trimmed_result == nullptr) {
    return nullptr;
  }

  for (uint32_t i = 0; i < dest_index; ++i) {
    ObjPtr<mirror::Object> obj = result->GetWithoutChecks(i);
    trimmed_result->SetWithoutChecks<false>(i, obj);
  }

  return trimmed_result;
}

ObjPtr<mirror::ObjectArray<mirror::Object>> ProcessAnnotationSetRefList(
    const ClassData& klass,
    const AnnotationSetRefList* set_ref_list,
    uint32_t size)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  Thread* self = Thread::Current();
  StackHandleScope<1> hs(self);
  ObjPtr<mirror::Class> annotation_array_class =
      WellKnownClasses::ToClass(WellKnownClasses::java_lang_annotation_Annotation__array);
  ObjPtr<mirror::Class> annotation_array_array_class =
      Runtime::Current()->GetClassLinker()->FindArrayClass(self, annotation_array_class);
  if (annotation_array_array_class == nullptr) {
    return nullptr;
  }
  Handle<mirror::ObjectArray<mirror::Object>> annotation_array_array(hs.NewHandle(
      mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_array_class, size)));
  if (annotation_array_array == nullptr) {
    LOG(ERROR) << "Annotation set ref array allocation failed";
    return nullptr;
  }
  for (uint32_t index = 0; index < size; ++index) {
    const AnnotationSetRefItem* set_ref_item = &set_ref_list->list_[index];
    const AnnotationSetItem* set_item = dex_file.GetSetRefItemItem(set_ref_item);
    ObjPtr<mirror::Object> annotation_set =
        ProcessAnnotationSet(klass, set_item, DexFile::DexVisibility::kRuntime);
    if (annotation_set == nullptr) {
      return nullptr;
    }
    annotation_array_array->SetWithoutChecks<false>(index, annotation_set);
  }
  return annotation_array_array.Get();
}
}  // namespace

namespace annotations {

ObjPtr<mirror::Object> GetAnnotationForField(ArtField* field,
                                             Handle<mirror::Class> annotation_class) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  StackHandleScope<1> hs(Thread::Current());
  const ClassData field_class(hs, field);
  return GetAnnotationObjectFromAnnotationSet(
      field_class, annotation_set, DexFile::DexVisibility::kRuntime, annotation_class);
}

ObjPtr<mirror::ObjectArray<mirror::Object>> GetAnnotationsForField(ArtField* field) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
  StackHandleScope<1> hs(Thread::Current());
  const ClassData field_class(hs, field);
  return ProcessAnnotationSet(field_class, annotation_set, DexFile::DexVisibility::kRuntime);
}

ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForField(ArtField* field) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  StackHandleScope<1> hs(Thread::Current());
  const ClassData field_class(hs, field);
  return GetSignatureValue(field_class, annotation_set);
}

bool IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
  if (annotation_set == nullptr) {
    return false;
  }
  StackHandleScope<1> hs(Thread::Current());
  const ClassData field_class(hs, field);
  const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
      field_class, annotation_set, DexFile::DexVisibility::kRuntime, annotation_class);
  return annotation_item != nullptr;
}

ObjPtr<mirror::Object> GetAnnotationDefaultValue(ArtMethod* method) {
  const ClassData klass(method);
  const DexFile* dex_file = &klass.GetDexFile();
  const AnnotationsDirectoryItem* annotations_dir =
      dex_file->GetAnnotationsDirectory(*klass.GetClassDef());
  if (annotations_dir == nullptr) {
    return nullptr;
  }
  const AnnotationSetItem* annotation_set =
      dex_file->GetClassAnnotationSet(annotations_dir);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(*dex_file,
                          annotation_set,
                          "Ldalvik/annotation/AnnotationDefault;",
                          DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  const uint8_t* annotation =
      SearchEncodedAnnotation(*dex_file, annotation_item->annotation_, "value");
  if (annotation == nullptr) {
    return nullptr;
  }
  uint8_t header_byte = *(annotation++);
  if ((header_byte & DexFile::kDexAnnotationValueTypeMask) != DexFile::kDexAnnotationAnnotation) {
    return nullptr;
  }
  annotation = SearchEncodedAnnotation(*dex_file, annotation, method->GetName());
  if (annotation == nullptr) {
    return nullptr;
  }
  DexFile::AnnotationValue annotation_value;
  StackHandleScope<1> hs(Thread::Current());
  Handle<mirror::Class> return_type(hs.NewHandle(method->ResolveReturnType()));
  if (!ProcessAnnotationValue<false>(klass,
                                     &annotation,
                                     &annotation_value,
                                     return_type,
                                     DexFile::kAllObjects)) {
    return nullptr;
  }
  return annotation_value.value_.GetL();
}

ObjPtr<mirror::Object> GetAnnotationForMethod(ArtMethod* method,
                                              Handle<mirror::Class> annotation_class) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetAnnotationObjectFromAnnotationSet(
      ClassData(method), annotation_set, DexFile::DexVisibility::kRuntime, annotation_class);
}

ObjPtr<mirror::ObjectArray<mirror::Object>> GetAnnotationsForMethod(ArtMethod* method) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
  return ProcessAnnotationSet(ClassData(method), annotation_set, DexFile::DexVisibility::kRuntime);
}

ObjPtr<mirror::ObjectArray<mirror::Class>> GetExceptionTypesForMethod(ArtMethod* method) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetThrowsValue(ClassData(method), annotation_set);
}

ObjPtr<mirror::ObjectArray<mirror::Object>> GetParameterAnnotations(ArtMethod* method) {
  const DexFile* dex_file = method->GetDexFile();
  const ParameterAnnotationsItem* parameter_annotations =
      FindAnnotationsItemForMethod(method);
  if (parameter_annotations == nullptr) {
    return nullptr;
  }
  const AnnotationSetRefList* set_ref_list =
      dex_file->GetParameterAnnotationSetRefList(parameter_annotations);
  if (set_ref_list == nullptr) {
    return nullptr;
  }
  uint32_t size = set_ref_list->size_;
  return ProcessAnnotationSetRefList(ClassData(method), set_ref_list, size);
}

uint32_t GetNumberOfAnnotatedMethodParameters(ArtMethod* method) {
  const DexFile* dex_file = method->GetDexFile();
  const ParameterAnnotationsItem* parameter_annotations =
      FindAnnotationsItemForMethod(method);
  if (parameter_annotations == nullptr) {
    return 0u;
  }
  const AnnotationSetRefList* set_ref_list =
      dex_file->GetParameterAnnotationSetRefList(parameter_annotations);
  if (set_ref_list == nullptr) {
    return 0u;
  }
  return set_ref_list->size_;
}

ObjPtr<mirror::Object> GetAnnotationForMethodParameter(ArtMethod* method,
                                                       uint32_t parameter_idx,
                                                       Handle<mirror::Class> annotation_class) {
  const DexFile* dex_file = method->GetDexFile();
  const ParameterAnnotationsItem* parameter_annotations = FindAnnotationsItemForMethod(method);
  if (parameter_annotations == nullptr) {
    return nullptr;
  }
  const AnnotationSetRefList* set_ref_list =
      dex_file->GetParameterAnnotationSetRefList(parameter_annotations);
  if (set_ref_list == nullptr) {
    return nullptr;
  }
  if (parameter_idx >= set_ref_list->size_) {
    return nullptr;
  }
  const AnnotationSetRefItem* annotation_set_ref = &set_ref_list->list_[parameter_idx];
  const AnnotationSetItem* annotation_set =
     dex_file->GetSetRefItemItem(annotation_set_ref);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetAnnotationObjectFromAnnotationSet(
      ClassData(method), annotation_set, DexFile::DexVisibility::kRuntime, annotation_class);
}

bool GetParametersMetadataForMethod(
    ArtMethod* method,
    /*out*/ MutableHandle<mirror::ObjectArray<mirror::String>>* names,
    /*out*/ MutableHandle<mirror::IntArray>* access_flags) {
  const AnnotationSetItem* annotation_set =
      FindAnnotationSetForMethod(method);
  if (annotation_set == nullptr) {
    return false;
  }

  const DexFile* dex_file = method->GetDexFile();
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(*dex_file,
                          annotation_set,
                          "Ldalvik/annotation/MethodParameters;",
                          DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return false;
  }

  StackHandleScope<4> hs(Thread::Current());

  // Extract the parameters' names String[].
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  Handle<mirror::Class> string_array_class =
      hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::String>>(class_linker));
  DCHECK(string_array_class != nullptr);

  ClassData data(method);
  Handle<mirror::Object> names_obj =
      hs.NewHandle(GetAnnotationValue(data,
                                      annotation_item,
                                      "names",
                                      string_array_class,
                                      DexFile::kDexAnnotationArray));
  if (names_obj == nullptr) {
    return false;
  }

  // Extract the parameters' access flags int[].
  Handle<mirror::Class> int_array_class(hs.NewHandle(GetClassRoot<mirror::IntArray>(class_linker)));
  DCHECK(int_array_class != nullptr);
  Handle<mirror::Object> access_flags_obj =
      hs.NewHandle(GetAnnotationValue(data,
                                      annotation_item,
                                      "accessFlags",
                                      int_array_class,
                                      DexFile::kDexAnnotationArray));
  if (access_flags_obj == nullptr) {
    return false;
  }

  names->Assign(names_obj->AsObjectArray<mirror::String>());
  access_flags->Assign(access_flags_obj->AsIntArray());
  return true;
}

ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForMethod(ArtMethod* method) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetSignatureValue(ClassData(method), annotation_set);
}

bool IsMethodAnnotationPresent(
    ArtMethod* method,
    Handle<mirror::Class> annotation_class,
    DexFile::DexVisibility visibility /* = DexFile::DexVisibility::kRuntime */) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
      ClassData(method), annotation_set, visibility, annotation_class);
  return annotation_item != nullptr;
}

static void DCheckNativeAnnotation(const char* descriptor, jclass cls) {
  if (kIsDebugBuild) {
    ScopedObjectAccess soa(Thread::Current());
    ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
    ClassLinker* linker = Runtime::Current()->GetClassLinker();
    // WellKnownClasses may not be initialized yet, so `klass` may be null.
    if (klass != nullptr) {
      // Lookup using the boot class path loader should yield the annotation class.
      CHECK_EQ(klass, linker->LookupClass(soa.Self(), descriptor, /* class_loader= */ nullptr));
    }
  }
}

// Check whether a method from the `dex_file` with the given `annotation_set`
// is annotated with `annotation_descriptor` with build visibility.
static bool IsMethodBuildAnnotationPresent(const DexFile& dex_file,
                                           const AnnotationSetItem& annotation_set,
                                           const char* annotation_descriptor,
                                           jclass annotation_class) {
  for (uint32_t i = 0; i < annotation_set.size_; ++i) {
    const AnnotationItem* annotation_item = dex_file.GetAnnotationItem(&annotation_set, i);
    if (!IsVisibilityCompatible(static_cast<DexFile::DexVisibility>(annotation_item->visibility_),
                                DexFile::DexVisibility::kBuild)) {
      continue;
    }
    const uint8_t* annotation = annotation_item->annotation_;
    uint32_t type_index = DecodeUnsignedLeb128(&annotation);
    const char* descriptor = dex_file.GetTypeDescriptor(dex::TypeIndex(type_index));
    if (strcmp(descriptor, annotation_descriptor) == 0) {
      DCheckNativeAnnotation(descriptor, annotation_class);
      return true;
    }
  }
  return false;
}

static uint32_t GetNativeMethodAnnotationAccessFlags(const DexFile& dex_file,
                                                     const dex::AnnotationSetItem& annotation_set) {
  uint32_t access_flags = 0u;
  if (IsMethodBuildAnnotationPresent(
          dex_file,
          annotation_set,
          "Ldalvik/annotation/optimization/FastNative;",
          WellKnownClasses::dalvik_annotation_optimization_FastNative)) {
    access_flags |= kAccFastNative;
  }
  if (IsMethodBuildAnnotationPresent(
          dex_file,
          annotation_set,
          "Ldalvik/annotation/optimization/CriticalNative;",
          WellKnownClasses::dalvik_annotation_optimization_CriticalNative)) {
    access_flags |= kAccCriticalNative;
  }
  CHECK_NE(access_flags, kAccFastNative | kAccCriticalNative);
  return access_flags;
}

uint32_t GetNativeMethodAnnotationAccessFlags(const DexFile& dex_file,
                                              const dex::ClassDef& class_def,
                                              uint32_t method_index) {
  const dex::AnnotationSetItem* annotation_set =
      FindAnnotationSetForMethod(dex_file, class_def, method_index);
  if (annotation_set == nullptr) {
    return 0u;
  }
  return GetNativeMethodAnnotationAccessFlags(dex_file, *annotation_set);
}

uint32_t GetNativeMethodAnnotationAccessFlags(const DexFile& dex_file,
                                              const dex::MethodAnnotationsItem& method_annotations) {
  return GetNativeMethodAnnotationAccessFlags(
      dex_file, *dex_file.GetMethodAnnotationSetItem(method_annotations));
}

static bool MethodIsNeverCompile(const DexFile& dex_file,
                                 const dex::AnnotationSetItem& annotation_set) {
  return IsMethodBuildAnnotationPresent(
      dex_file,
      annotation_set,
      "Ldalvik/annotation/optimization/NeverCompile;",
      WellKnownClasses::dalvik_annotation_optimization_NeverCompile);
}

bool MethodIsNeverCompile(const DexFile& dex_file,
                          const dex::ClassDef& class_def,
                          uint32_t method_index) {
  const dex::AnnotationSetItem* annotation_set =
      FindAnnotationSetForMethod(dex_file, class_def, method_index);
  if (annotation_set == nullptr) {
    return false;
  }
  return MethodIsNeverCompile(dex_file, *annotation_set);
}

bool MethodIsNeverCompile(const DexFile& dex_file,
                          const dex::MethodAnnotationsItem& method_annotations) {
  return MethodIsNeverCompile(dex_file, *dex_file.GetMethodAnnotationSetItem(method_annotations));
}

bool MethodIsNeverInline(const DexFile& dex_file,
                         const dex::ClassDef& class_def,
                         uint32_t method_index) {
  const dex::AnnotationSetItem* annotation_set =
      FindAnnotationSetForMethod(dex_file, class_def, method_index);
  if (annotation_set == nullptr) {
    return false;
  }
  return IsMethodBuildAnnotationPresent(
      dex_file,
      *annotation_set,
      "Ldalvik/annotation/optimization/NeverInline;",
      WellKnownClasses::dalvik_annotation_optimization_NeverInline);
}

bool FieldIsReachabilitySensitive(const DexFile& dex_file,
                                  const dex::ClassDef& class_def,
                                  uint32_t field_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationSetItem* annotation_set =
      FindAnnotationSetForField(dex_file, class_def, field_index);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(dex_file,
                          annotation_set,
                          "Ldalvik/annotation/optimization/ReachabilitySensitive;",
                          DexFile::DexVisibility::kRuntime);
  // TODO: We're missing the equivalent of DCheckNativeAnnotation (not a DCHECK). Does it matter?
  return annotation_item != nullptr;
}

bool MethodIsReachabilitySensitive(const DexFile& dex_file,
                                   const dex::ClassDef& class_def,
                                   uint32_t method_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationSetItem* annotation_set =
      FindAnnotationSetForMethod(dex_file, class_def, method_index);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(dex_file,
                          annotation_set,
                          "Ldalvik/annotation/optimization/ReachabilitySensitive;",
                          DexFile::DexVisibility::kRuntime);
  return annotation_item != nullptr;
}

static bool MethodIsReachabilitySensitive(const DexFile& dex_file,
                                               uint32_t method_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK(method_index < dex_file.NumMethodIds());
  const dex::MethodId& method_id = dex_file.GetMethodId(method_index);
  dex::TypeIndex class_index = method_id.class_idx_;
  const dex::ClassDef * class_def = dex_file.FindClassDef(class_index);
  return class_def != nullptr
         && MethodIsReachabilitySensitive(dex_file, *class_def, method_index);
}

bool MethodContainsRSensitiveAccess(const DexFile& dex_file,
                                    const dex::ClassDef& class_def,
                                    uint32_t method_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  // TODO: This is too slow to run very regularly. Currently this is only invoked in the
  // presence of @DeadReferenceSafe, which will be rare. In the long run, we need to quickly
  // check once whether a class has any @ReachabilitySensitive annotations. If not, we can
  // immediately return false here for any method in that class.
  uint32_t code_item_offset = dex_file.FindCodeItemOffset(class_def, method_index);
  const dex::CodeItem* code_item = dex_file.GetCodeItem(code_item_offset);
  CodeItemInstructionAccessor accessor(dex_file, code_item);
  if (!accessor.HasCodeItem()) {
    return false;
  }
  for (DexInstructionIterator iter = accessor.begin(); iter != accessor.end(); ++iter) {
    switch (iter->Opcode()) {
      case Instruction::IGET:
      case Instruction::IGET_WIDE:
      case Instruction::IGET_OBJECT:
      case Instruction::IGET_BOOLEAN:
      case Instruction::IGET_BYTE:
      case Instruction::IGET_CHAR:
      case Instruction::IGET_SHORT:
      case Instruction::IPUT:
      case Instruction::IPUT_WIDE:
      case Instruction::IPUT_OBJECT:
      case Instruction::IPUT_BOOLEAN:
      case Instruction::IPUT_BYTE:
      case Instruction::IPUT_CHAR:
      case Instruction::IPUT_SHORT:
        {
          uint32_t field_index = iter->VRegC_22c();
          DCHECK(field_index < dex_file.NumFieldIds());
          // We only guarantee to pay attention to the annotation if it's in the same class,
          // or a containing class, but it's OK to do so in other cases.
          const dex::FieldId& field_id = dex_file.GetFieldId(field_index);
          dex::TypeIndex class_index = field_id.class_idx_;
          const dex::ClassDef * field_class_def = dex_file.FindClassDef(class_index);
          // We do not handle the case in which the field is declared in a superclass, and
          // don't claim to do so. The annotated field should normally be private.
          if (field_class_def != nullptr
              && FieldIsReachabilitySensitive(dex_file, *field_class_def, field_index)) {
            return true;
          }
        }
        break;
      case Instruction::INVOKE_SUPER:
        // Cannot call method in same class. TODO: Try an explicit superclass lookup for
        // better "best effort"?
        break;
      case Instruction::INVOKE_INTERFACE:
        // We handle an interface call just like a virtual call. We will find annotations
        // on interface methods/fields visible to us, but not of the annotation is in a
        // super-interface. Again, we could just ignore it.
      case Instruction::INVOKE_VIRTUAL:
      case Instruction::INVOKE_DIRECT:
        {
          uint32_t called_method_index = iter->VRegB_35c();
          if (MethodIsReachabilitySensitive(dex_file, called_method_index)) {
            return true;
          }
        }
        break;
      case Instruction::INVOKE_INTERFACE_RANGE:
      case Instruction::INVOKE_VIRTUAL_RANGE:
      case Instruction::INVOKE_DIRECT_RANGE:
        {
          uint32_t called_method_index = iter->VRegB_3rc();
          if (MethodIsReachabilitySensitive(dex_file, called_method_index)) {
            return true;
          }
        }
        break;
        // We explicitly do not handle indirect ReachabilitySensitive accesses through VarHandles,
        // etc. Thus we ignore INVOKE_CUSTOM / INVOKE_CUSTOM_RANGE / INVOKE_POLYMORPHIC /
        // INVOKE_POLYMORPHIC_RANGE.
      default:
        // There is no way to add an annotation to array elements, and so far we've encountered no
        // need for that, so we ignore AGET and APUT.
        // It's impractical or impossible to garbage collect a class while one of its methods is
        // on the call stack. We allow ReachabilitySensitive annotations on static methods and
        // fields, but they can be safely ignored.
        break;
    }
  }
  return false;
}

bool HasDeadReferenceSafeAnnotation(const DexFile& dex_file,
                                    const dex::ClassDef& class_def)
  // TODO: This should check outer classes as well.
  // It's conservatively correct not to do so.
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationsDirectoryItem* annotations_dir =
      dex_file.GetAnnotationsDirectory(class_def);
  if (annotations_dir == nullptr) {
    return false;
  }
  const AnnotationSetItem* annotation_set = dex_file.GetClassAnnotationSet(annotations_dir);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(dex_file,
                          annotation_set,
                          "Ldalvik/annotation/optimization/DeadReferenceSafe;",
                          DexFile::DexVisibility::kRuntime);
  return annotation_item != nullptr;
}

ObjPtr<mirror::Object> GetAnnotationForClass(Handle<mirror::Class> klass,
                                             Handle<mirror::Class> annotation_class) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetAnnotationObjectFromAnnotationSet(
      data, annotation_set, DexFile::DexVisibility::kRuntime, annotation_class);
}

ObjPtr<mirror::ObjectArray<mirror::Object>> GetAnnotationsForClass(Handle<mirror::Class> klass) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  return ProcessAnnotationSet(data, annotation_set, DexFile::DexVisibility::kRuntime);
}

ObjPtr<mirror::ObjectArray<mirror::Class>> GetDeclaredClasses(Handle<mirror::Class> klass) {
  return GetAnnotationArrayValue<mirror::Class>(klass,
                                                "Ldalvik/annotation/MemberClasses;",
                                                "value");
}

ObjPtr<mirror::Class> GetDeclaringClass(Handle<mirror::Class> klass) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(data.GetDexFile(),
                                                              annotation_set,
                                                              "Ldalvik/annotation/EnclosingClass;",
                                                              DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  ObjPtr<mirror::Object> obj = GetAnnotationValue(data,
                                                  annotation_item,
                                                  "value",
                                                  ScopedNullHandle<mirror::Class>(),
                                                  DexFile::kDexAnnotationType);
  if (obj == nullptr) {
    return nullptr;
  }
  if (!obj->IsClass()) {
    // TypeNotPresentException, throw the NoClassDefFoundError.
    Thread::Current()->SetException(obj->AsThrowable()->GetCause());
    return nullptr;
  }
  return obj->AsClass();
}

ObjPtr<mirror::Class> GetEnclosingClass(Handle<mirror::Class> klass) {
  ObjPtr<mirror::Class> declaring_class = GetDeclaringClass(klass);
  if (declaring_class != nullptr || Thread::Current()->IsExceptionPending()) {
    return declaring_class;
  }
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(data.GetDexFile(),
                                                              annotation_set,
                                                              "Ldalvik/annotation/EnclosingMethod;",
                                                              DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  const uint8_t* annotation =
      SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "value");
  if (annotation == nullptr) {
    return nullptr;
  }
  DexFile::AnnotationValue annotation_value;
  if (!ProcessAnnotationValue<false>(data,
                                     &annotation,
                                     &annotation_value,
                                     ScopedNullHandle<mirror::Class>(),
                                     DexFile::kAllRaw)) {
    return nullptr;
  }
  if (annotation_value.type_ != DexFile::kDexAnnotationMethod) {
    return nullptr;
  }
  StackHandleScope<2> hs(Thread::Current());
  ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodId(
      annotation_value.value_.GetI(),
      hs.NewHandle(data.GetDexCache()),
      hs.NewHandle(data.GetClassLoader()));
  if (method == nullptr) {
    return nullptr;
  }
  return method->GetDeclaringClass();
}

ObjPtr<mirror::Object> GetEnclosingMethod(Handle<mirror::Class> klass) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(data.GetDexFile(),
                                                              annotation_set,
                                                              "Ldalvik/annotation/EnclosingMethod;",
                                                              DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  return GetAnnotationValue(data, annotation_item, "value", ScopedNullHandle<mirror::Class>(),
      DexFile::kDexAnnotationMethod);
}

bool GetInnerClass(Handle<mirror::Class> klass, /*out*/ ObjPtr<mirror::String>* name) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(data.GetDexFile(),
                                                              annotation_set,
                                                              "Ldalvik/annotation/InnerClass;",
                                                              DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return false;
  }
  const uint8_t* annotation =
      SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "name");
  if (annotation == nullptr) {
    return false;
  }
  DexFile::AnnotationValue annotation_value;
  if (!ProcessAnnotationValue<false>(data,
                                     &annotation,
                                     &annotation_value,
                                     ScopedNullHandle<mirror::Class>(),
                                     DexFile::kAllObjects)) {
    return false;
  }
  if (annotation_value.type_ != DexFile::kDexAnnotationNull &&
      annotation_value.type_ != DexFile::kDexAnnotationString) {
    return false;
  }
  *name = down_cast<mirror::String*>(annotation_value.value_.GetL());
  return true;
}

bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(data.GetDexFile(),
                                                              annotation_set,
                                                              "Ldalvik/annotation/InnerClass;",
                                                              DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return false;
  }
  const uint8_t* annotation =
      SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "accessFlags");
  if (annotation == nullptr) {
    return false;
  }
  DexFile::AnnotationValue annotation_value;
  if (!ProcessAnnotationValue<false>(data,
                                     &annotation,
                                     &annotation_value,
                                     ScopedNullHandle<mirror::Class>(),
                                     DexFile::kAllRaw)) {
    return false;
  }
  if (annotation_value.type_ != DexFile::kDexAnnotationInt) {
    return false;
  }
  *flags = annotation_value.value_.GetI();
  return true;
}

ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForClass(
    Handle<mirror::Class> klass) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetSignatureValue(data, annotation_set);
}

const char* GetSourceDebugExtension(Handle<mirror::Class> klass) {
  // Before instantiating ClassData, check that klass has a DexCache
  // assigned.  The ClassData constructor indirectly dereferences it
  // when calling klass->GetDexFile().
  if (klass->GetDexCache() == nullptr) {
    DCHECK(klass->IsPrimitive() || klass->IsArrayClass());
    return nullptr;
  }

  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }

  const AnnotationItem* annotation_item =
      SearchAnnotationSet(data.GetDexFile(),
                          annotation_set,
                          "Ldalvik/annotation/SourceDebugExtension;",
                          DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }

  const uint8_t* annotation =
      SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "value");
  if (annotation == nullptr) {
    return nullptr;
  }
  DexFile::AnnotationValue annotation_value;
  if (!ProcessAnnotationValue<false>(data,
                                     &annotation,
                                     &annotation_value,
                                     ScopedNullHandle<mirror::Class>(),
                                     DexFile::kAllRaw)) {
    return nullptr;
  }
  if (annotation_value.type_ != DexFile::kDexAnnotationString) {
    return nullptr;
  }
  dex::StringIndex index(static_cast<uint32_t>(annotation_value.value_.GetI()));
  return data.GetDexFile().GetStringData(index);
}

ObjPtr<mirror::Class> GetNestHost(Handle<mirror::Class> klass) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(data.GetDexFile(),
                                                              annotation_set,
                                                              "Ldalvik/annotation/NestHost;",
                                                              DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  ObjPtr<mirror::Object> obj = GetAnnotationValue(data,
                                                  annotation_item,
                                                  "host",
                                                  ScopedNullHandle<mirror::Class>(),
                                                  DexFile::kDexAnnotationType);
  if (obj == nullptr) {
    return nullptr;
  }
  if (!obj->IsClass()) {
    // TypeNotPresentException, throw the NoClassDefFoundError.
    Thread::Current()->SetException(obj->AsThrowable()->GetCause());
    return nullptr;
  }
  return obj->AsClass();
}

ObjPtr<mirror::ObjectArray<mirror::Class>> GetNestMembers(Handle<mirror::Class> klass) {
  return GetAnnotationArrayValue<mirror::Class>(klass,
                                                "Ldalvik/annotation/NestMembers;",
                                                "classes");
}

ObjPtr<mirror::ObjectArray<mirror::Class>> GetPermittedSubclasses(Handle<mirror::Classklass) {
  return GetAnnotationArrayValue<mirror::Class>(klass,
                                                "Ldalvik/annotation/PermittedSubclasses;",
                                                "value");
}

ObjPtr<mirror::Object> getRecordAnnotationElement(Handle<mirror::Class> klass,
                                                  Handle<mirror::Class> array_class,
                                                  const char* element_name) {
  ClassData data(klass);
  const DexFile& dex_file = klass->GetDexFile();
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(
      dex_file, annotation_set, "Ldalvik/annotation/Record;", DexFile::DexVisibility::kSystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  const uint8_t* annotation =
      SearchEncodedAnnotation(dex_file, annotation_item->annotation_, element_name);
  if (annotation == nullptr) {
    return nullptr;
  }
  DexFile::AnnotationValue annotation_value;
  bool result = Runtime::Current()->IsActiveTransaction()
      ? ProcessAnnotationValue<true>(data,
                                     &annotation,
                                     &annotation_value,
                                     array_class,
                                     DexFile::kPrimitivesOrObjects)
      : ProcessAnnotationValue<false>(data,
                                      &annotation,
                                      &annotation_value,
                                      array_class,
                                      DexFile::kPrimitivesOrObjects);
  if (!result) {
    return nullptr;
  }
  return annotation_value.value_.GetL();
}

bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
      data, annotation_set, DexFile::DexVisibility::kRuntime, annotation_class);
  return annotation_item != nullptr;
}

int32_t GetLineNumFromPC(const DexFile* dex_file, ArtMethod* method, uint32_t rel_pc) {
  // For native method, lineno should be -2 to indicate it is native. Note that
  // "line number == -2" is how libcore tells from StackTraceElement.
  if (!method->HasCodeItem()) {
    return -2;
  }

  CodeItemDebugInfoAccessor accessor(method->DexInstructionDebugInfo());
  DCHECK(accessor.HasCodeItem()) << method->PrettyMethod() << " " << dex_file->GetLocation();

  // A method with no line number info should return -1
  uint32_t line_num = -1;
  accessor.GetLineNumForPc(rel_pc, &line_num);
  return line_num;
}

template<bool kTransactionActive>
void RuntimeEncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const {
  DCHECK(dex_cache_ != nullptr);
  switch (type_) {
    case kBoolean: field->SetBoolean<kTransactionActive>(field->GetDeclaringClass(), jval_.z);
        break;
    case kByte:    field->SetByte<kTransactionActive>(field->GetDeclaringClass(), jval_.b); break;
    case kShort:   field->SetShort<kTransactionActive>(field->GetDeclaringClass(), jval_.s); break;
    case kChar:    field->SetChar<kTransactionActive>(field->GetDeclaringClass(), jval_.c); break;
    case kInt:     field->SetInt<kTransactionActive>(field->GetDeclaringClass(), jval_.i); break;
    case kLong:    field->SetLong<kTransactionActive>(field->GetDeclaringClass(), jval_.j); break;
    case kFloat:   field->SetFloat<kTransactionActive>(field->GetDeclaringClass(), jval_.f); break;
    case kDouble:  field->SetDouble<kTransactionActive>(field->GetDeclaringClass(), jval_.d)break;
    case kNull:    field->SetObject<kTransactionActive>(field->GetDeclaringClass(), nullptr); break;
    case kString: {
      ObjPtr<mirror::String> resolved = linker_->ResolveString(dex::StringIndex(jval_.i),
                                                               dex_cache_);
      field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
      break;
    }
    case kType: {
      ObjPtr<mirror::Class> resolved = linker_->ResolveType(dex::TypeIndex(jval_.i),
                                                            dex_cache_,
                                                            class_loader_);
      field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
      break;
    }
    default: UNIMPLEMENTED(FATAL) << ": type " << type_;
  }
}
template
void RuntimeEncodedStaticFieldValueIterator::ReadValueToField<true>(ArtField* field) const;
template
void RuntimeEncodedStaticFieldValueIterator::ReadValueToField<false>(ArtField* fieldconst;

inline static VisitorStatus VisitElement(AnnotationVisitor* visitor,
                                         const char* element_name,
                                         uint8_t depth,
                                         uint32_t element_index,
                                         const DexFile::AnnotationValue& annotation_value)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  if (depth == 0) {
    return visitor->VisitAnnotationElement(
        element_name, annotation_value.type_, annotation_value.value_);
  } else {
    return visitor->VisitArrayElement(
        depth - 1, element_index, annotation_value.type_, annotation_value.value_);
  }
}

static VisitorStatus VisitEncodedValue(const ClassData& klass,
                                       const DexFile& dex_file,
                                       const uint8_t** annotation_ptr,
                                       AnnotationVisitor* visitor,
                                       const char* element_name,
                                       uint8_t depth,
                                       uint32_t element_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DexFile::AnnotationValue annotation_value;
  // kTransactionActive is safe because the result_style is kAllRaw.
  bool is_consumed = ProcessAnnotationValue<false>(klass,
                                                   annotation_ptr,
                                                   &annotation_value,
                                                   ScopedNullHandle<mirror::Class>(),
                                                   DexFile::kAllRaw);

  VisitorStatus status =
      VisitElement(visitor, element_name, depth, element_index, annotation_value);
  if (UNLIKELY(visitor->HasError())) {
    // Stop visiting since we won't verify the class anyway.
    return annotations::VisitorStatus::kVisitBreak;
  }

  switch (annotation_value.type_) {
    case DexFile::kDexAnnotationArray: {
      DCHECK(!is_consumed) << " unexpected consumption of array-typed element '" << element_name
                           << "' annotating the class " << klass.GetRealClass()->PrettyClass();
      SkipEncodedValueHeaderByte(annotation_ptr);
      uint32_t array_size = DecodeUnsignedLeb128(annotation_ptr);
      uint8_t next_depth = depth + 1;
      VisitorStatus element_status = (status == VisitorStatus::kVisitInner) ?
                                         VisitorStatus::kVisitNext :
                                         VisitorStatus::kVisitBreak;
      uint32_t i = 0;
      for (; i < array_size && element_status != VisitorStatus::kVisitBreak; ++i) {
        element_status = VisitEncodedValue(
            klass, dex_file, annotation_ptr, visitor, element_name, next_depth, i);
        if (UNLIKELY(visitor->HasError())) {
          // Stop visiting since we won't verify the class anyway.
          return annotations::VisitorStatus::kVisitBreak;
        }
      }
      for (; i < array_size; ++i) {
        SkipAnnotationValue(dex_file, annotation_ptr);
      }
      break;
    }
    case DexFile::kDexAnnotationAnnotation: {
      DCHECK(!is_consumed) << " unexpected consumption of annotation-typed element '"
                           << element_name << "' annotating the class "
                           << klass.GetRealClass()->PrettyClass();
      SkipEncodedValueHeaderByte(annotation_ptr);
      DecodeUnsignedLeb128(annotation_ptr);  // unused type_index
      uint32_t size = DecodeUnsignedLeb128(annotation_ptr);
      for (; size != 0u; --size) {
        DecodeUnsignedLeb128(annotation_ptr);  // unused element_name_index
        SkipAnnotationValue(dex_file, annotation_ptr);
      }
      break;
    }
    case DexFile::kDexAnnotationMethodType:
    case DexFile::kDexAnnotationMethodHandle:
      // kDexAnnotationMethodType and kDexAnnotationMethodHandle return false in order to not
      // crash the process but they are unexpected here.
      visitor->SetErrorMsg(StringPrintf(
          "Encountered unexpected annotation element type 0x%02x of %s for the class %s",
          annotation_value.type_,
          element_name,
          klass.GetRealClass()->PrettyClass().c_str()));
      // Stop visiting since we won't verify the class anyway.
      return annotations::VisitorStatus::kVisitBreak;
    default: {
      // kDexAnnotationArray and kDexAnnotationAnnotation are the only 2 known value_types causing
      // ProcessAnnotationValue return false. For other value_types, we shouldn't need to iterate
      // over annotation_ptr and skip the value here.
      DCHECK(is_consumed) << StringPrintf(
          "consumed annotation element type 0x%02x of %s for the class %s",
          annotation_value.type_,
          element_name,
          klass.GetRealClass()->PrettyClass().c_str());
      if (UNLIKELY(!is_consumed)) {
        SkipAnnotationValue(dex_file, annotation_ptr);
      }
      break;
    }
  }

  return status;
}

void VisitClassAnnotations(Handle<mirror::Class> klass, AnnotationVisitor* visitor) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return;
  }

  const DexFile& dex_file = data.GetDexFile();
  for (uint32_t i = 0; i < annotation_set->size_; ++i) {
    const AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
    DexFile::DexVisibility visibility =
        static_cast<DexFile::DexVisibility>(annotation_item->visibility_);
    const uint8_t* annotation = annotation_item->annotation_;
    uint32_t type_index = DecodeUnsignedLeb128(&annotation);
    const char* annotation_descriptor = dex_file.GetTypeDescriptor(dex::TypeIndex(type_index));
    VisitorStatus status = visitor->VisitAnnotation(annotation_descriptor, visibility);
    switch (status) {
      case VisitorStatus::kVisitBreak:
        return;
      case VisitorStatus::kVisitNext:
        continue;
      case VisitorStatus::kVisitInner:
        // Visit the annotation elements
        break;
    }

    uint32_t size = DecodeUnsignedLeb128(&annotation);
    while (size != 0) {
      uint32_t element_name_index = DecodeUnsignedLeb128(&annotation);
      const char* element_name =
          dex_file.GetStringData(dex_file.GetStringId(dex::StringIndex(element_name_index)));

      status = VisitEncodedValue(
          data, dex_file, &annotation, visitor, element_name, /*depth=*/0, /*ignored*/ 0);
      if (UNLIKELY(visitor->HasError())) {
        // Encountered an error, bail out since we won't verify the class anyway.
        return;
      }
      if (status == VisitorStatus::kVisitBreak) {
        break;
      }
      size--;
    }
  }
}

}  // namespace annotations

}  // namespace art

Messung V0.5 in Prozent
C=91 H=97 G=93

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.