in runtime/dex_file.cc [1836:2097]
bool DexFile::ProcessAnnotationValue(Handle<mirror::Class> klass, const uint8_t** annotation_ptr,
AnnotationValue* annotation_value, Handle<mirror::Class> array_class,
DexFile::AnnotationResultStyle result_style) const {
Thread* self = Thread::Current();
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 & kDexAnnotationValueTypeMask;
uint8_t value_arg = header_byte >> kDexAnnotationValueArgShift;
int32_t width = value_arg + 1;
annotation_value->type_ = value_type;
switch (value_type) {
case kDexAnnotationByte:
annotation_value->value_.SetB(static_cast<int8_t>(ReadSignedInt(annotation, value_arg)));
primitive_type = Primitive::kPrimByte;
break;
case kDexAnnotationShort:
annotation_value->value_.SetS(static_cast<int16_t>(ReadSignedInt(annotation, value_arg)));
primitive_type = Primitive::kPrimShort;
break;
case kDexAnnotationChar:
annotation_value->value_.SetC(static_cast<uint16_t>(ReadUnsignedInt(annotation, value_arg,
false)));
primitive_type = Primitive::kPrimChar;
break;
case kDexAnnotationInt:
annotation_value->value_.SetI(ReadSignedInt(annotation, value_arg));
primitive_type = Primitive::kPrimInt;
break;
case kDexAnnotationLong:
annotation_value->value_.SetJ(ReadSignedLong(annotation, value_arg));
primitive_type = Primitive::kPrimLong;
break;
case kDexAnnotationFloat:
annotation_value->value_.SetI(ReadUnsignedInt(annotation, value_arg, true));
primitive_type = Primitive::kPrimFloat;
break;
case kDexAnnotationDouble:
annotation_value->value_.SetJ(ReadUnsignedLong(annotation, value_arg, true));
primitive_type = Primitive::kPrimDouble;
break;
case kDexAnnotationBoolean:
annotation_value->value_.SetZ(value_arg != 0);
primitive_type = Primitive::kPrimBoolean;
width = 0;
break;
case kDexAnnotationString: {
uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
if (result_style == kAllRaw) {
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(), index, dex_cache);
set_object = true;
if (element_object == nullptr) {
return false;
}
}
break;
}
case kDexAnnotationType: {
uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
if (result_style == kAllRaw) {
annotation_value->value_.SetI(index);
} else {
element_object = Runtime::Current()->GetClassLinker()->ResolveType(
klass->GetDexFile(), index, klass.Get());
set_object = true;
if (element_object == nullptr) {
CHECK(self->IsExceptionPending());
if (result_style == kAllObjects) {
const char* msg = StringByTypeIdx(index);
self->ThrowNewWrappedException("Ljava/lang/TypeNotPresentException;", msg);
element_object = self->GetException();
self->ClearException();
} else {
return false;
}
}
}
break;
}
case kDexAnnotationMethod: {
uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
if (result_style == kAllRaw) {
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()));
ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType(
klass->GetDexFile(), index, dex_cache, class_loader);
if (method == nullptr) {
return false;
}
set_object = true;
if (method->IsConstructor()) {
element_object = mirror::Constructor::CreateFromArtMethod(self, method);
} else {
element_object = mirror::Method::CreateFromArtMethod(self, method);
}
if (element_object == nullptr) {
return false;
}
}
break;
}
case kDexAnnotationField: {
uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
if (result_style == kAllRaw) {
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, dex_cache, class_loader);
if (field == nullptr) {
return false;
}
set_object = true;
element_object = mirror::Field::CreateFromArtField(self, field, true);
if (element_object == nullptr) {
return false;
}
}
break;
}
case kDexAnnotationEnum: {
uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
if (result_style == kAllRaw) {
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, dex_cache, class_loader, 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, true, true);
element_object = enum_field->GetObject(field_class.Get());
set_object = true;
}
}
break;
}
case kDexAnnotationArray:
if (result_style == kAllRaw || array_class.Get() == 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<true>(
self, array_class.Get(), size, array_class->GetComponentSizeShift(),
Runtime::Current()->GetHeap()->GetCurrentAllocator())));
if (new_array.Get() == nullptr) {
LOG(ERROR) << "Annotation element array allocation failed with size " << size;
return false;
}
AnnotationValue new_annotation_value;
for (uint32_t i = 0; i < size; ++i) {
if (!ProcessAnnotationValue(klass, &annotation, &new_annotation_value, component_type,
kPrimitivesOrObjects)) {
return false;
}
if (!component_type->IsPrimitive()) {
mirror::Object* obj = new_annotation_value.value_.GetL();
new_array->AsObjectArray<mirror::Object>()->SetWithoutChecks<false>(i, obj);
} else {
switch (new_annotation_value.type_) {
case kDexAnnotationByte:
new_array->AsByteArray()->SetWithoutChecks<false>(
i, new_annotation_value.value_.GetB());
break;
case kDexAnnotationShort:
new_array->AsShortArray()->SetWithoutChecks<false>(
i, new_annotation_value.value_.GetS());
break;
case kDexAnnotationChar:
new_array->AsCharArray()->SetWithoutChecks<false>(
i, new_annotation_value.value_.GetC());
break;
case kDexAnnotationInt:
new_array->AsIntArray()->SetWithoutChecks<false>(
i, new_annotation_value.value_.GetI());
break;
case kDexAnnotationLong:
new_array->AsLongArray()->SetWithoutChecks<false>(
i, new_annotation_value.value_.GetJ());
break;
case kDexAnnotationFloat:
new_array->AsFloatArray()->SetWithoutChecks<false>(
i, new_annotation_value.value_.GetF());
break;
case kDexAnnotationDouble:
new_array->AsDoubleArray()->SetWithoutChecks<false>(
i, new_annotation_value.value_.GetD());
break;
case kDexAnnotationBoolean:
new_array->AsBooleanArray()->SetWithoutChecks<false>(
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 kDexAnnotationAnnotation:
if (result_style == kAllRaw) {
return false;
}
element_object = ProcessEncodedAnnotation(klass, &annotation);
if (element_object == nullptr) {
return false;
}
set_object = true;
width = 0;
break;
case kDexAnnotationNull:
if (result_style == 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 == 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;
}