2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 * We're not expecting to make much use of runtime annotations, so speed vs.
20 * space choices are weighted heavily toward small size.
22 * It would have been nice to treat "system" annotations in the same way
23 * we do "real" annotations, but that doesn't work. The chief difficulty
24 * is that some of them have member types that are not legal in annotations,
25 * such as Method and Annotation. Another source of pain comes from the
26 * AnnotationDefault annotation, which by virtue of being an annotation
27 * could itself have default values, requiring some additional checks to
30 * It's simpler, and more efficient, to handle the system annotations
31 * entirely inside the VM. There are empty classes defined for the system
32 * annotation types, but their only purpose is to allow the system
33 * annotations to share name space with standard annotations.
38 static Object* processEncodedAnnotation(const ClassObject* clazz,\
40 static bool skipEncodedAnnotation(const ClassObject* clazz, const u1** pPtr);
43 * System annotation descriptors.
45 static const char* kDescrAnnotationDefault
46 = "Ldalvik/annotation/AnnotationDefault;";
47 static const char* kDescrEnclosingClass
48 = "Ldalvik/annotation/EnclosingClass;";
49 static const char* kDescrEnclosingMethod
50 = "Ldalvik/annotation/EnclosingMethod;";
51 static const char* kDescrInnerClass = "Ldalvik/annotation/InnerClass;";
52 static const char* kDescrMemberClasses
53 = "Ldalvik/annotation/MemberClasses;";
54 static const char* kDescrSignature = "Ldalvik/annotation/Signature;";
55 static const char* kDescrThrows = "Ldalvik/annotation/Throws;";
58 * Read an unsigned LEB128 value from a buffer. Advances "pBuf".
60 static u4 readUleb128(const u1** pBuf)
64 const u1* buf = *pBuf;
69 * Worst-case on bad data is we read too much data and return a bogus
70 * result. Safe to assume that we will encounter a byte with its
71 * high bit clear before the end of the mapped file.
76 result |= (val & 0x7f) << shift;
78 } while ((val & 0x80) != 0);
85 * Get the annotations directory item.
87 static const DexAnnotationsDirectoryItem* getAnnoDirectory(DexFile* pDexFile,
88 const ClassObject* clazz)
90 const DexClassDef* pClassDef;
93 * Find the class def in the DEX file. For better performance we should
94 * stash this in the ClassObject.
96 pClassDef = dexFindClass(pDexFile, clazz->descriptor);
97 assert(pClassDef != NULL);
98 return dexGetAnnotationsDirectoryItem(pDexFile, pClassDef);
102 * Return a zero-length array of Annotation objects.
104 * TODO: this currently allocates a new array each time, but I think we
105 * can get away with returning a canonical copy.
107 * Caller must call dvmReleaseTrackedAlloc().
109 static ArrayObject* emptyAnnoArray()
111 return dvmAllocArrayByClass(
112 gDvm.classJavaLangAnnotationAnnotationArray, 0, ALLOC_DEFAULT);
116 * Return an array of empty arrays of Annotation objects.
118 * Caller must call dvmReleaseTrackedAlloc().
120 static ArrayObject* emptyAnnoArrayArray(int numElements)
122 Thread* self = dvmThreadSelf();
126 arr = dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArrayArray,
127 numElements, ALLOC_DEFAULT);
129 ArrayObject** elems = (ArrayObject**)(void*)arr->contents;
130 for (i = 0; i < numElements; i++) {
131 elems[i] = emptyAnnoArray();
132 dvmReleaseTrackedAlloc((Object*)elems[i], self);
140 * Read a signed integer. "zwidth" is the zero-based byte count.
142 static s4 readSignedInt(const u1* ptr, int zwidth)
147 for (i = zwidth; i >= 0; --i)
148 val = ((u4)val >> 8) | (((s4)*ptr++) << 24);
149 val >>= (3 - zwidth) * 8;
155 * Read an unsigned integer. "zwidth" is the zero-based byte count,
156 * "fillOnRight" indicates which side we want to zero-fill from.
158 static u4 readUnsignedInt(const u1* ptr, int zwidth, bool fillOnRight)
164 for (i = zwidth; i >= 0; --i)
165 val = (val >> 8) | (((u4)*ptr++) << 24);
166 val >>= (3 - zwidth) * 8;
168 for (i = zwidth; i >= 0; --i)
169 val = (val >> 8) | (((u4)*ptr++) << 24);
175 * Read a signed long. "zwidth" is the zero-based byte count.
177 static s8 readSignedLong(const u1* ptr, int zwidth)
182 for (i = zwidth; i >= 0; --i)
183 val = ((u8)val >> 8) | (((s8)*ptr++) << 56);
184 val >>= (7 - zwidth) * 8;
190 * Read an unsigned long. "zwidth" is the zero-based byte count,
191 * "fillOnRight" indicates which side we want to zero-fill from.
193 static u8 readUnsignedLong(const u1* ptr, int zwidth, bool fillOnRight)
199 for (i = zwidth; i >= 0; --i)
200 val = (val >> 8) | (((u8)*ptr++) << 56);
201 val >>= (7 - zwidth) * 8;
203 for (i = zwidth; i >= 0; --i)
204 val = (val >> 8) | (((u8)*ptr++) << 56);
211 * ===========================================================================
213 * ===========================================================================
217 * An annotation in "clazz" refers to a method by index. This just gives
218 * us the name of the class and the name and signature of the method. We
219 * need to find the method's class, and then find the method within that
220 * class. If the method has been resolved before, we can just use the
221 * results of the previous lookup.
223 * Normally we do this as part of method invocation in the interpreter, which
224 * provides us with a bit of context: is it virtual or direct, do we need
225 * to initialize the class because it's a static method, etc. We don't have
226 * that information here, so we have to do a bit of searching.
228 * Returns NULL if the method was not found (exception may be pending).
230 static Method* resolveAmbiguousMethod(const ClassObject* referrer, u4 methodIdx)
233 ClassObject* resClass;
235 const DexMethodId* pMethodId;
238 /* if we've already resolved this method, return it */
239 resMethod = dvmDexGetResolvedMethod(referrer->pDvmDex, methodIdx);
240 if (resMethod != NULL)
243 pDexFile = referrer->pDvmDex->pDexFile;
244 pMethodId = dexGetMethodId(pDexFile, methodIdx);
245 resClass = dvmResolveClass(referrer, pMethodId->classIdx, true);
246 if (resClass == NULL) {
247 /* note exception will be pending */
248 ALOGD("resolveAmbiguousMethod: unable to find class %d", methodIdx);
251 if (dvmIsInterfaceClass(resClass)) {
252 /* method is part of an interface -- not expecting that */
253 ALOGD("resolveAmbiguousMethod: method in interface?");
257 // TODO - consider a method access flag that indicates direct vs. virtual
258 name = dexStringById(pDexFile, pMethodId->nameIdx);
261 dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
263 if (name[0] == '<') {
265 * Constructor or class initializer. Only need to examine the
266 * "direct" list, and don't need to look up the class hierarchy.
268 resMethod = dvmFindDirectMethod(resClass, name, &proto);
271 * Do a hierarchical scan for direct and virtual methods.
273 * This uses the search order from the VM spec (v2 5.4.3.3), which
274 * seems appropriate here.
276 resMethod = dvmFindMethodHier(resClass, name, &proto);
283 * constants for processAnnotationValue indicating what style of
286 enum AnnotationResultStyle {
287 kAllObjects, /* return everything as an object */
288 kAllRaw, /* return everything as a raw value or index */
289 kPrimitivesOrObjects /* return primitives as-is but the rest as objects */
293 * Recursively process an annotation value.
295 * "clazz" is the class on which the annotations are defined. It may be
296 * NULL when "resultStyle" is "kAllRaw".
298 * If "resultStyle" is "kAllObjects", the result will always be an Object of an
299 * appropriate type (in pValue->value.l). For primitive types, the usual
300 * wrapper objects will be created.
302 * If "resultStyle" is "kAllRaw", numeric constants are stored directly into
303 * "pValue", and indexed values like String and Method are returned as
304 * indexes. Complex values like annotations and arrays are not handled.
306 * If "resultStyle" is "kPrimitivesOrObjects", numeric constants are stored
307 * directly into "pValue", and everything else is constructed as an Object
308 * of appropriate type (in pValue->value.l).
310 * The caller must call dvmReleaseTrackedAlloc on returned objects, when
311 * using "kAllObjects" or "kPrimitivesOrObjects".
313 * Returns "true" on success, "false" if the value could not be processed
314 * or an object could not be allocated. On allocation failure an exception
317 static bool processAnnotationValue(const ClassObject* clazz,
318 const u1** pPtr, AnnotationValue* pValue,
319 AnnotationResultStyle resultStyle)
321 Thread* self = dvmThreadSelf();
322 Object* elemObj = NULL;
323 bool setObject = false;
324 const u1* ptr = *pPtr;
325 u1 valueType, valueArg;
330 valueArg = valueType >> kDexAnnotationValueArgShift;
331 width = valueArg + 1; /* assume, correct later */
333 ALOGV("----- type is 0x%02x %d, ptr=%p [0x%06x]",
334 valueType & kDexAnnotationValueTypeMask, valueArg, ptr-1,
335 (ptr-1) - (u1*)clazz->pDvmDex->pDexFile->baseAddr);
337 pValue->type = valueType & kDexAnnotationValueTypeMask;
339 switch (valueType & kDexAnnotationValueTypeMask) {
340 case kDexAnnotationByte:
341 pValue->value.i = (s1) readSignedInt(ptr, valueArg);
342 if (resultStyle == kAllObjects) {
343 elemObj = (Object*) dvmBoxPrimitive(pValue->value,
344 dvmFindPrimitiveClass('B'));
348 case kDexAnnotationShort:
349 pValue->value.i = (s2) readSignedInt(ptr, valueArg);
350 if (resultStyle == kAllObjects) {
351 elemObj = (Object*) dvmBoxPrimitive(pValue->value,
352 dvmFindPrimitiveClass('S'));
356 case kDexAnnotationChar:
357 pValue->value.i = (u2) readUnsignedInt(ptr, valueArg, false);
358 if (resultStyle == kAllObjects) {
359 elemObj = (Object*) dvmBoxPrimitive(pValue->value,
360 dvmFindPrimitiveClass('C'));
364 case kDexAnnotationInt:
365 pValue->value.i = readSignedInt(ptr, valueArg);
366 if (resultStyle == kAllObjects) {
367 elemObj = (Object*) dvmBoxPrimitive(pValue->value,
368 dvmFindPrimitiveClass('I'));
372 case kDexAnnotationLong:
373 pValue->value.j = readSignedLong(ptr, valueArg);
374 if (resultStyle == kAllObjects) {
375 elemObj = (Object*) dvmBoxPrimitive(pValue->value,
376 dvmFindPrimitiveClass('J'));
380 case kDexAnnotationFloat:
381 pValue->value.i = readUnsignedInt(ptr, valueArg, true);
382 if (resultStyle == kAllObjects) {
383 elemObj = (Object*) dvmBoxPrimitive(pValue->value,
384 dvmFindPrimitiveClass('F'));
388 case kDexAnnotationDouble:
389 pValue->value.j = readUnsignedLong(ptr, valueArg, true);
390 if (resultStyle == kAllObjects) {
391 elemObj = (Object*) dvmBoxPrimitive(pValue->value,
392 dvmFindPrimitiveClass('D'));
396 case kDexAnnotationBoolean:
397 pValue->value.i = (valueArg != 0);
398 if (resultStyle == kAllObjects) {
399 elemObj = (Object*) dvmBoxPrimitive(pValue->value,
400 dvmFindPrimitiveClass('Z'));
406 case kDexAnnotationString:
407 idx = readUnsignedInt(ptr, valueArg, false);
408 if (resultStyle == kAllRaw) {
409 pValue->value.i = idx;
411 elemObj = (Object*) dvmResolveString(clazz, idx);
415 dvmAddTrackedAlloc(elemObj, self); // balance the Release
418 case kDexAnnotationType:
419 idx = readUnsignedInt(ptr, valueArg, false);
420 if (resultStyle == kAllRaw) {
421 pValue->value.i = idx;
423 elemObj = (Object*) dvmResolveClass(clazz, idx, true);
425 if (elemObj == NULL) {
426 /* we're expected to throw a TypeNotPresentException here */
427 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
428 const char* desc = dexStringByTypeIdx(pDexFile, idx);
429 dvmClearException(self);
430 dvmThrowTypeNotPresentException(desc);
433 dvmAddTrackedAlloc(elemObj, self); // balance the Release
437 case kDexAnnotationMethod:
438 idx = readUnsignedInt(ptr, valueArg, false);
439 if (resultStyle == kAllRaw) {
440 pValue->value.i = idx;
442 Method* meth = resolveAmbiguousMethod(clazz, idx);
445 elemObj = dvmCreateReflectObjForMethod(clazz, meth);
451 case kDexAnnotationField:
452 idx = readUnsignedInt(ptr, valueArg, false);
453 assert(false); // TODO
455 case kDexAnnotationEnum:
456 /* enum values are the contents of a static field */
457 idx = readUnsignedInt(ptr, valueArg, false);
458 if (resultStyle == kAllRaw) {
459 pValue->value.i = idx;
463 sfield = dvmResolveStaticField(clazz, idx);
464 if (sfield == NULL) {
467 assert(sfield->clazz->descriptor[0] == 'L');
468 elemObj = sfield->value.l;
470 dvmAddTrackedAlloc(elemObj, self); // balance the Release
474 case kDexAnnotationArray:
476 * encoded_array format, which is a size followed by a stream
477 * of annotation_value.
479 * We create an array of Object, populate it, and return it.
481 if (resultStyle == kAllRaw) {
484 ArrayObject* newArray;
487 size = readUleb128(&ptr);
488 LOGVV("--- annotation array, size is %u at %p", size, ptr);
489 newArray = dvmAllocArrayByClass(gDvm.classJavaLangObjectArray,
490 size, ALLOC_DEFAULT);
491 if (newArray == NULL) {
492 ALOGE("annotation element array alloc failed (%d)", size);
496 AnnotationValue avalue;
497 for (count = 0; count < size; count++) {
498 if (!processAnnotationValue(clazz, &ptr, &avalue,
500 dvmReleaseTrackedAlloc((Object*)newArray, self);
503 Object* obj = (Object*)avalue.value.l;
504 dvmSetObjectArrayElement(newArray, count, obj);
505 dvmReleaseTrackedAlloc(obj, self);
508 elemObj = (Object*) newArray;
513 case kDexAnnotationAnnotation:
514 /* encoded_annotation format */
515 if (resultStyle == kAllRaw)
517 elemObj = processEncodedAnnotation(clazz, &ptr);
521 dvmAddTrackedAlloc(elemObj, self); // balance the Release
524 case kDexAnnotationNull:
525 if (resultStyle == kAllRaw) {
528 assert(elemObj == NULL);
534 ALOGE("Bad annotation element value byte 0x%02x (0x%02x)",
535 valueType, valueType & kDexAnnotationValueTypeMask);
544 pValue->value.l = elemObj;
550 * For most object types, we have nothing to do here, and we just return
553 * For an array annotation, the type of the extracted object will always
554 * be java.lang.Object[], but we want it to match the type that the
555 * annotation member is expected to return. In some cases this may
556 * involve un-boxing primitive values.
558 * We allocate a second array with the correct type, then copy the data
559 * over. This releases the tracked allocation on "valueObj" and returns
560 * a new, tracked object.
562 * On failure, this releases the tracking on "valueObj" and returns NULL
563 * (allowing the call to say "foo = convertReturnType(foo, ..)").
565 static Object* convertReturnType(Object* valueObj, ClassObject* methodReturn)
567 if (valueObj == NULL ||
568 !dvmIsArray((ArrayObject*)valueObj) || !dvmIsArrayClass(methodReturn))
573 Thread* self = dvmThreadSelf();
574 ClassObject* srcElemClass;
575 ClassObject* dstElemClass;
578 * We always extract kDexAnnotationArray into Object[], so we expect to
579 * find that here. This means we can skip the FindClass on
580 * (valueObj->clazz->descriptor+1, valueObj->clazz->classLoader).
582 if (strcmp(valueObj->clazz->descriptor, "[Ljava/lang/Object;") != 0) {
583 ALOGE("Unexpected src type class (%s)", valueObj->clazz->descriptor);
586 srcElemClass = gDvm.classJavaLangObject;
589 * Skip past the '[' to get element class name. Note this is not always
590 * the same as methodReturn->elementClass.
592 char firstChar = methodReturn->descriptor[1];
593 if (firstChar == 'L' || firstChar == '[') {
594 dstElemClass = dvmFindClass(methodReturn->descriptor+1,
595 methodReturn->classLoader);
597 dstElemClass = dvmFindPrimitiveClass(firstChar);
599 ALOGV("HEY: converting valueObj from [%s to [%s",
600 srcElemClass->descriptor, dstElemClass->descriptor);
602 ArrayObject* srcArray = (ArrayObject*) valueObj;
603 u4 length = srcArray->length;
604 ArrayObject* newArray;
606 newArray = dvmAllocArrayByClass(methodReturn, length, ALLOC_DEFAULT);
607 if (newArray == NULL) {
608 ALOGE("Failed creating duplicate annotation class (%s %d)",
609 methodReturn->descriptor, length);
614 if (dstElemClass->primitiveType == PRIM_NOT) {
615 success = dvmCopyObjectArray(newArray, srcArray, dstElemClass);
617 success = dvmUnboxObjectArray(newArray, srcArray, dstElemClass);
620 ALOGE("Annotation array copy failed");
621 dvmReleaseTrackedAlloc((Object*)newArray, self);
627 /* replace old, return new */
628 dvmReleaseTrackedAlloc(valueObj, self);
629 return (Object*) newArray;
633 * Create a new AnnotationMember.
635 * "clazz" is the class on which the annotations are defined. "pPtr"
636 * points to a pointer into the annotation data. "annoClass" is the
637 * annotation's class.
639 * We extract the annotation's value, create a new AnnotationMember object,
642 * Returns NULL on failure; an exception may or may not be raised.
644 static Object* createAnnotationMember(const ClassObject* clazz,
645 const ClassObject* annoClass, const u1** pPtr)
647 Thread* self = dvmThreadSelf();
648 const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
649 StringObject* nameObj = NULL;
650 Object* valueObj = NULL;
651 Object* newMember = NULL;
652 Object* methodObj = NULL;
653 ClassObject* methodReturn = NULL;
656 AnnotationValue avalue;
660 elementNameIdx = readUleb128(pPtr);
662 if (!processAnnotationValue(clazz, pPtr, &avalue, kAllObjects)) {
663 ALOGW("Failed processing annotation value");
666 valueObj = (Object*)avalue.value.l;
668 /* new member to hold the element */
670 dvmAllocObject(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember,
672 name = dexStringById(pDexFile, elementNameIdx);
673 nameObj = dvmCreateStringFromCstr(name);
675 /* find the method in the annotation class, given only the name */
677 Method* annoMeth = dvmFindVirtualMethodByName(annoClass, name);
678 if (annoMeth == NULL) {
679 ALOGW("WARNING: could not find annotation member %s in %s",
680 name, annoClass->descriptor);
682 methodObj = dvmCreateReflectObjForMethod(annoClass, annoMeth);
683 methodReturn = dvmGetBoxedReturnType(annoMeth);
686 if (newMember == NULL || nameObj == NULL || methodObj == NULL ||
687 methodReturn == NULL)
689 ALOGE("Failed creating annotation element (m=%p n=%p a=%p r=%p)",
690 newMember, nameObj, methodObj, methodReturn);
694 /* convert the return type, if necessary */
695 valueObj = convertReturnType(valueObj, methodReturn);
696 if (valueObj == NULL)
699 /* call 4-argument constructor */
700 dvmCallMethod(self, gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init,
701 newMember, &unused, nameObj, valueObj, methodReturn, methodObj);
702 if (dvmCheckException(self)) {
703 ALOGD("Failed constructing annotation element");
710 /* release tracked allocations */
711 dvmReleaseTrackedAlloc(newMember, self);
712 dvmReleaseTrackedAlloc((Object*)nameObj, self);
713 dvmReleaseTrackedAlloc(valueObj, self);
714 dvmReleaseTrackedAlloc(methodObj, self);
722 * Create a new Annotation object from what we find in the annotation item.
724 * "clazz" is the class on which the annotations are defined. "pPtr"
725 * points to a pointer into the annotation data.
727 * We use the AnnotationFactory class to create the annotation for us. The
730 * public static Annotation createAnnotation(
731 * Class<? extends Annotation> annotationType,
732 * AnnotationMember[] elements)
734 * Returns a new Annotation, which will NOT be in the local ref table and
735 * not referenced elsewhere, so store it away soon. On failure, returns NULL
736 * with an exception raised.
738 static Object* processEncodedAnnotation(const ClassObject* clazz,
741 Thread* self = dvmThreadSelf();
742 Object* newAnno = NULL;
743 ArrayObject* elementArray = NULL;
744 const ClassObject* annoClass;
746 u4 typeIdx, size, count;
749 typeIdx = readUleb128(&ptr);
750 size = readUleb128(&ptr);
752 LOGVV("----- processEnc ptr=%p type=%d size=%d", ptr, typeIdx, size);
754 annoClass = dvmDexGetResolvedClass(clazz->pDvmDex, typeIdx);
755 if (annoClass == NULL) {
756 annoClass = dvmResolveClass(clazz, typeIdx, true);
757 if (annoClass == NULL) {
758 ALOGE("Unable to resolve %s annotation class %d",
759 clazz->descriptor, typeIdx);
760 assert(dvmCheckException(self));
765 ALOGV("----- processEnc ptr=%p [0x%06x] typeIdx=%d size=%d class=%s",
766 *pPtr, *pPtr - (u1*) clazz->pDvmDex->pDexFile->baseAddr,
767 typeIdx, size, annoClass->descriptor);
770 * Elements are parsed out and stored in an array. The Harmony
771 * constructor wants an array with just the declared elements --
772 * default values get merged in later.
777 elementArray = dvmAllocArrayByClass(
778 gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray,
779 size, ALLOC_DEFAULT);
780 if (elementArray == NULL) {
781 ALOGE("failed to allocate annotation member array (%d elements)",
788 * "ptr" points to a byte stream with "size" occurrences of
789 * annotation_element.
791 for (count = 0; count < size; count++) {
792 Object* newMember = createAnnotationMember(clazz, annoClass, &ptr);
793 if (newMember == NULL)
796 /* add it to the array */
797 dvmSetObjectArrayElement(elementArray, count, newMember);
801 gDvm.methOrgApacheHarmonyLangAnnotationAnnotationFactory_createAnnotation,
802 NULL, &result, annoClass, elementArray);
803 if (dvmCheckException(self)) {
804 ALOGD("Failed creating an annotation");
805 //dvmLogExceptionStackTrace();
809 newAnno = (Object*)result.l;
812 dvmReleaseTrackedAlloc((Object*) elementArray, NULL);
814 if (newAnno == NULL && !dvmCheckException(self)) {
815 /* make sure an exception is raised */
816 dvmThrowRuntimeException("failure in processEncodedAnnotation");
822 * Run through an annotation set and convert each entry into an Annotation
825 * Returns an array of Annotation objects, or NULL with an exception raised
828 static ArrayObject* processAnnotationSet(const ClassObject* clazz,
829 const DexAnnotationSetItem* pAnnoSet, int visibility)
831 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
832 const DexAnnotationItem* pAnnoItem;
833 ArrayObject* annoArray;
837 /* we need these later; make sure they're initialized */
838 if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory))
839 dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory);
840 if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember))
841 dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember);
843 /* count up the number of visible elements */
844 for (i = count = 0; i < (int) pAnnoSet->size; i++) {
845 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
846 if (pAnnoItem->visibility == visibility)
851 dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArray,
852 count, ALLOC_DEFAULT);
853 if (annoArray == NULL)
857 * Generate Annotation objects. We must put them into the array
858 * immediately (or add them to the tracked ref table).
861 for (i = 0; i < (int) pAnnoSet->size; i++) {
862 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
863 if (pAnnoItem->visibility != visibility)
865 const u1* ptr = pAnnoItem->annotation;
866 Object *anno = processEncodedAnnotation(clazz, &ptr);
868 dvmReleaseTrackedAlloc((Object*) annoArray, NULL);
871 dvmSetObjectArrayElement(annoArray, dstIndex, anno);
879 * Return the annotation item of the specified type in the annotation set, or
880 * NULL if the set contains no annotation of that type.
882 static const DexAnnotationItem* getAnnotationItemFromAnnotationSet(
883 const ClassObject* clazz, const DexAnnotationSetItem* pAnnoSet,
884 int visibility, const ClassObject* annotationClazz)
886 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
887 const DexAnnotationItem* pAnnoItem;
889 const ClassObject* annoClass;
893 /* we need these later; make sure they're initialized */
894 if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory))
895 dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory);
896 if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember))
897 dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember);
899 for (i = 0; i < (int) pAnnoSet->size; i++) {
900 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
901 if (pAnnoItem->visibility != visibility)
904 ptr = pAnnoItem->annotation;
905 typeIdx = readUleb128(&ptr);
907 annoClass = dvmDexGetResolvedClass(clazz->pDvmDex, typeIdx);
908 if (annoClass == NULL) {
909 annoClass = dvmResolveClass(clazz, typeIdx, true);
910 if (annoClass == NULL) {
911 return NULL; // an exception is pending
915 if (annoClass == annotationClazz) {
924 * Return the Annotation object of the specified type in the annotation set, or
925 * NULL if the set contains no annotation of that type.
927 static Object* getAnnotationObjectFromAnnotationSet(const ClassObject* clazz,
928 const DexAnnotationSetItem* pAnnoSet, int visibility,
929 const ClassObject* annotationClazz)
931 const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet(
932 clazz, pAnnoSet, visibility, annotationClazz);
933 if (pAnnoItem == NULL) {
936 const u1* ptr = pAnnoItem->annotation;
937 return processEncodedAnnotation(clazz, &ptr);
941 * ===========================================================================
942 * Skipping and scanning
943 * ===========================================================================
947 * Skip past an annotation value.
949 * "clazz" is the class on which the annotations are defined.
951 * Returns "true" on success, "false" on parsing failure.
953 static bool skipAnnotationValue(const ClassObject* clazz, const u1** pPtr)
955 const u1* ptr = *pPtr;
956 u1 valueType, valueArg;
960 valueArg = valueType >> kDexAnnotationValueArgShift;
961 width = valueArg + 1; /* assume */
963 ALOGV("----- type is 0x%02x %d, ptr=%p [0x%06x]",
964 valueType & kDexAnnotationValueTypeMask, valueArg, ptr-1,
965 (ptr-1) - (u1*)clazz->pDvmDex->pDexFile->baseAddr);
967 switch (valueType & kDexAnnotationValueTypeMask) {
968 case kDexAnnotationByte: break;
969 case kDexAnnotationShort: break;
970 case kDexAnnotationChar: break;
971 case kDexAnnotationInt: break;
972 case kDexAnnotationLong: break;
973 case kDexAnnotationFloat: break;
974 case kDexAnnotationDouble: break;
975 case kDexAnnotationString: break;
976 case kDexAnnotationType: break;
977 case kDexAnnotationMethod: break;
978 case kDexAnnotationField: break;
979 case kDexAnnotationEnum: break;
981 case kDexAnnotationArray:
982 /* encoded_array format */
984 u4 size = readUleb128(&ptr);
986 if (!skipAnnotationValue(clazz, &ptr))
992 case kDexAnnotationAnnotation:
993 /* encoded_annotation format */
994 if (!skipEncodedAnnotation(clazz, &ptr))
998 case kDexAnnotationBoolean:
999 case kDexAnnotationNull:
1003 ALOGE("Bad annotation element value byte 0x%02x", valueType);
1015 * Skip past an encoded annotation. Mainly useful for annotations embedded
1016 * in other annotations.
1018 static bool skipEncodedAnnotation(const ClassObject* clazz, const u1** pPtr)
1024 (void) readUleb128(&ptr);
1025 size = readUleb128(&ptr);
1028 * "ptr" points to a byte stream with "size" occurrences of
1029 * annotation_element.
1032 (void) readUleb128(&ptr);
1034 if (!skipAnnotationValue(clazz, &ptr))
1044 * Compare the name of the class in the DEX file to the supplied descriptor.
1045 * Return value is equivalent to strcmp.
1047 static int compareClassDescriptor(DexFile* pDexFile, u4 typeIdx,
1048 const char* descriptor)
1050 const char* str = dexStringByTypeIdx(pDexFile, typeIdx);
1052 return strcmp(str, descriptor);
1056 * Search through the annotation set for an annotation with a matching
1059 * Comparing the string descriptor is slower than comparing an integer class
1060 * index. If annotation lists are expected to be long, we could look up
1061 * the class' index by name from the DEX file, rather than doing a class
1062 * lookup and string compare on each entry. (Note the index will be
1063 * different for each DEX file, so we can't cache annotation class indices
1066 static const DexAnnotationItem* searchAnnotationSet(const ClassObject* clazz,
1067 const DexAnnotationSetItem* pAnnoSet, const char* descriptor,
1070 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1071 const DexAnnotationItem* result = NULL;
1075 //printf("##### searchAnnotationSet %s %d\n", descriptor, visibility);
1077 for (i = 0; i < (int) pAnnoSet->size; i++) {
1078 const DexAnnotationItem* pAnnoItem;
1080 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
1081 if (pAnnoItem->visibility != visibility)
1083 const u1* ptr = pAnnoItem->annotation;
1084 typeIdx = readUleb128(&ptr);
1086 if (compareClassDescriptor(pDexFile, typeIdx, descriptor) == 0) {
1087 //printf("##### match on %x/%p at %d\n", typeIdx, pDexFile, i);
1097 * Find an annotation value in the annotation_item whose name matches "name".
1098 * A pointer to the annotation_value is returned, or NULL if it's not found.
1100 static const u1* searchEncodedAnnotation(const ClassObject* clazz,
1101 const u1* ptr, const char* name)
1103 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1106 typeIdx = readUleb128(&ptr);
1107 size = readUleb128(&ptr);
1108 //printf("##### searching ptr=%p type=%u size=%u\n", ptr, typeIdx, size);
1112 const char* elemName;
1114 elementNameIdx = readUleb128(&ptr);
1115 elemName = dexStringById(pDexFile, elementNameIdx);
1116 if (strcmp(name, elemName) == 0) {
1117 //printf("##### item match on %s\n", name);
1118 return ptr; /* points to start of value */
1121 skipAnnotationValue(clazz, &ptr);
1124 //printf("##### no item match on %s\n", name);
1128 #define GAV_FAILED ((Object*) 0x10000001)
1131 * Extract an encoded annotation value from the field specified by "annoName".
1133 * "expectedType" is an annotation value type, e.g. kDexAnnotationString.
1134 * "debugAnnoName" is only used in debug messages.
1136 * Returns GAV_FAILED on failure. If an allocation failed, an exception
1139 static Object* getAnnotationValue(const ClassObject* clazz,
1140 const DexAnnotationItem* pAnnoItem, const char* annoName,
1141 int expectedType, const char* debugAnnoName)
1144 AnnotationValue avalue;
1146 /* find the annotation */
1147 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, annoName);
1149 ALOGW("%s annotation lacks '%s' member", debugAnnoName, annoName);
1153 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects))
1156 /* make sure it has the expected format */
1157 if (avalue.type != expectedType) {
1158 ALOGW("%s %s has wrong type (0x%02x, expected 0x%02x)",
1159 debugAnnoName, annoName, avalue.type, expectedType);
1163 return (Object*)avalue.value.l;
1168 * Find the Signature attribute and extract its value. (Signatures can
1169 * be found in annotations on classes, constructors, methods, and fields.)
1171 * Caller must call dvmReleaseTrackedAlloc().
1173 * Returns NULL if not found. On memory alloc failure, returns NULL with an
1176 static ArrayObject* getSignatureValue(const ClassObject* clazz,
1177 const DexAnnotationSetItem* pAnnoSet)
1179 const DexAnnotationItem* pAnnoItem;
1182 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrSignature,
1183 kDexVisibilitySystem);
1184 if (pAnnoItem == NULL)
1188 * The Signature annotation has one member, "String value".
1190 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationArray,
1192 if (obj == GAV_FAILED)
1194 assert(obj->clazz == gDvm.classJavaLangObjectArray);
1196 return (ArrayObject*)obj;
1201 * ===========================================================================
1203 * ===========================================================================
1207 * Find the DexAnnotationSetItem for this class.
1209 static const DexAnnotationSetItem* findAnnotationSetForClass(
1210 const ClassObject* clazz)
1213 const DexAnnotationsDirectoryItem* pAnnoDir;
1215 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */
1218 pDexFile = clazz->pDvmDex->pDexFile;
1219 pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1220 if (pAnnoDir != NULL)
1221 return dexGetClassAnnotationSet(pDexFile, pAnnoDir);
1227 * Return an array of Annotation objects for the class. Returns an empty
1228 * array if there are no annotations.
1230 * Caller must call dvmReleaseTrackedAlloc().
1232 * On allocation failure, this returns NULL with an exception raised.
1234 ArrayObject* dvmGetClassAnnotations(const ClassObject* clazz)
1236 ArrayObject* annoArray;
1237 const DexAnnotationSetItem* pAnnoSet = NULL;
1239 pAnnoSet = findAnnotationSetForClass(clazz);
1240 if (pAnnoSet == NULL) {
1241 /* no annotations for anything in class, or no class annotations */
1242 annoArray = emptyAnnoArray();
1244 annoArray = processAnnotationSet(clazz, pAnnoSet,
1245 kDexVisibilityRuntime);
1252 * Returns the annotation or NULL if it doesn't exist.
1254 Object* dvmGetClassAnnotation(const ClassObject* clazz,
1255 const ClassObject* annotationClazz)
1257 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForClass(clazz);
1258 if (pAnnoSet == NULL) {
1261 return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet,
1262 kDexVisibilityRuntime, annotationClazz);
1266 * Returns true if the annotation exists.
1268 bool dvmIsClassAnnotationPresent(const ClassObject* clazz,
1269 const ClassObject* annotationClazz)
1271 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForClass(clazz);
1272 if (pAnnoSet == NULL) {
1275 const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet(
1276 clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz);
1277 return (pAnnoItem != NULL);
1281 * Retrieve the Signature annotation, if any. Returns NULL if no signature
1284 * Caller must call dvmReleaseTrackedAlloc().
1286 ArrayObject* dvmGetClassSignatureAnnotation(const ClassObject* clazz)
1288 ArrayObject* signature = NULL;
1289 const DexAnnotationSetItem* pAnnoSet;
1291 pAnnoSet = findAnnotationSetForClass(clazz);
1292 if (pAnnoSet != NULL)
1293 signature = getSignatureValue(clazz, pAnnoSet);
1299 * Get the EnclosingMethod attribute from an annotation. Returns a Method
1302 * Caller must call dvmReleaseTrackedAlloc().
1304 Object* dvmGetEnclosingMethod(const ClassObject* clazz)
1306 const DexAnnotationItem* pAnnoItem;
1307 const DexAnnotationSetItem* pAnnoSet;
1310 pAnnoSet = findAnnotationSetForClass(clazz);
1311 if (pAnnoSet == NULL)
1314 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingMethod,
1315 kDexVisibilitySystem);
1316 if (pAnnoItem == NULL)
1320 * The EnclosingMethod annotation has one member, "Method value".
1322 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationMethod,
1324 if (obj == GAV_FAILED)
1326 assert(obj->clazz == gDvm.classJavaLangReflectConstructor ||
1327 obj->clazz == gDvm.classJavaLangReflectMethod);
1333 * Find a class' enclosing class. We return what we find in the
1334 * EnclosingClass attribute.
1336 * Returns a Class object, or NULL.
1338 * Caller must call dvmReleaseTrackedAlloc().
1340 ClassObject* dvmGetDeclaringClass(const ClassObject* clazz)
1342 const DexAnnotationItem* pAnnoItem;
1343 const DexAnnotationSetItem* pAnnoSet;
1346 pAnnoSet = findAnnotationSetForClass(clazz);
1347 if (pAnnoSet == NULL)
1350 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingClass,
1351 kDexVisibilitySystem);
1352 if (pAnnoItem == NULL)
1356 * The EnclosingClass annotation has one member, "Class value".
1358 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationType,
1360 if (obj == GAV_FAILED)
1363 assert(dvmIsClassObject(obj));
1364 return (ClassObject*)obj;
1368 * Find a class' enclosing class. We first search for an EnclosingClass
1369 * attribute, and if that's not found we look for an EnclosingMethod.
1371 * Returns a Class object, or NULL.
1373 * Caller must call dvmReleaseTrackedAlloc().
1375 ClassObject* dvmGetEnclosingClass(const ClassObject* clazz)
1377 const DexAnnotationItem* pAnnoItem;
1378 const DexAnnotationSetItem* pAnnoSet;
1381 pAnnoSet = findAnnotationSetForClass(clazz);
1382 if (pAnnoSet == NULL)
1385 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingClass,
1386 kDexVisibilitySystem);
1387 if (pAnnoItem != NULL) {
1389 * The EnclosingClass annotation has one member, "Class value".
1391 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationType,
1393 if (obj != GAV_FAILED) {
1394 assert(dvmIsClassObject(obj));
1395 return (ClassObject*)obj;
1400 * That didn't work. Look for an EnclosingMethod.
1402 * We could create a java.lang.reflect.Method object and extract the
1403 * declaringClass from it, but that's more work than we want to do.
1404 * Instead, we find the "value" item and parse the index out ourselves.
1406 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingMethod,
1407 kDexVisibilitySystem);
1408 if (pAnnoItem == NULL)
1411 /* find the value member */
1413 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "value");
1415 ALOGW("EnclosingMethod annotation lacks 'value' member");
1419 /* parse it, verify the type */
1420 AnnotationValue avalue;
1421 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllRaw)) {
1422 ALOGW("EnclosingMethod parse failed");
1425 if (avalue.type != kDexAnnotationMethod) {
1426 ALOGW("EnclosingMethod value has wrong type (0x%02x, expected 0x%02x)",
1427 avalue.type, kDexAnnotationMethod);
1431 /* pull out the method index and resolve the method */
1432 Method* meth = resolveAmbiguousMethod(clazz, avalue.value.i);
1436 ClassObject* methClazz = meth->clazz;
1437 dvmAddTrackedAlloc((Object*) methClazz, NULL); // balance the Release
1442 * Get the EnclosingClass attribute from an annotation. If found, returns
1443 * "true". A String with the original name of the class and the original
1444 * access flags are returned through the arguments. (The name will be NULL
1445 * for an anonymous inner class.)
1447 * Caller must call dvmReleaseTrackedAlloc().
1449 bool dvmGetInnerClass(const ClassObject* clazz, StringObject** pName,
1452 const DexAnnotationItem* pAnnoItem;
1453 const DexAnnotationSetItem* pAnnoSet;
1455 pAnnoSet = findAnnotationSetForClass(clazz);
1456 if (pAnnoSet == NULL)
1459 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrInnerClass,
1460 kDexVisibilitySystem);
1461 if (pAnnoItem == NULL)
1465 * The InnerClass annotation has two members, "String name" and
1466 * "int accessFlags". We don't want to get the access flags as an
1467 * Integer, so we process that as a simple value.
1470 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "name");
1472 ALOGW("InnerClass annotation lacks 'name' member");
1476 /* parse it into an Object */
1477 AnnotationValue avalue;
1478 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects)) {
1479 ALOGD("processAnnotationValue failed on InnerClass member 'name'");
1483 /* make sure it has the expected format */
1484 if (avalue.type != kDexAnnotationNull &&
1485 avalue.type != kDexAnnotationString)
1487 ALOGW("InnerClass name has bad type (0x%02x, expected STRING or NULL)",
1492 *pName = (StringObject*) avalue.value.l;
1493 assert(*pName == NULL || (*pName)->clazz == gDvm.classJavaLangString);
1495 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "accessFlags");
1497 ALOGW("InnerClass annotation lacks 'accessFlags' member");
1501 /* parse it, verify the type */
1502 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllRaw)) {
1503 ALOGW("InnerClass accessFlags parse failed");
1506 if (avalue.type != kDexAnnotationInt) {
1507 ALOGW("InnerClass value has wrong type (0x%02x, expected 0x%02x)",
1508 avalue.type, kDexAnnotationInt);
1512 *pAccessFlags = avalue.value.i;
1518 * Extract an array of Class objects from the MemberClasses annotation
1521 * Caller must call dvmReleaseTrackedAlloc().
1523 * Returns NULL if we don't find any member classes.
1525 ArrayObject* dvmGetDeclaredClasses(const ClassObject* clazz)
1527 const DexAnnotationSetItem* pAnnoSet;
1528 const DexAnnotationItem* pAnnoItem;
1531 pAnnoSet = findAnnotationSetForClass(clazz);
1532 if (pAnnoSet == NULL)
1535 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrMemberClasses,
1536 kDexVisibilitySystem);
1537 if (pAnnoItem == NULL)
1541 * The MemberClasses annotation has one member, "Class[] value".
1543 obj = getAnnotationValue(clazz, pAnnoItem, "value",
1544 kDexAnnotationArray, "MemberClasses");
1545 if (obj == GAV_FAILED)
1547 assert(dvmIsArray((ArrayObject*)obj));
1548 obj = convertReturnType(obj, gDvm.classJavaLangClassArray);
1549 return (ArrayObject*)obj;
1554 * ===========================================================================
1555 * Method (and Constructor)
1556 * ===========================================================================
1560 * Compare the attributes (class name, method name, method signature) of
1561 * the specified method to "method".
1563 static int compareMethodStr(DexFile* pDexFile, u4 methodIdx,
1564 const Method* method)
1566 const DexMethodId* pMethodId = dexGetMethodId(pDexFile, methodIdx);
1567 const char* str = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
1568 int result = strcmp(str, method->clazz->descriptor);
1571 str = dexStringById(pDexFile, pMethodId->nameIdx);
1572 result = strcmp(str, method->name);
1575 dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
1576 result = dexProtoCompare(&proto, &method->prototype);
1584 * Given a method, determine the method's index.
1586 * We could simply store this in the Method*, but that would cost 4 bytes
1587 * per method. Instead we plow through the DEX data.
1589 * We have two choices: look through the class method data, or look through
1590 * the global method_ids table. The former is awkward because the method
1591 * could have been defined in a superclass or interface. The latter works
1592 * out reasonably well because it's in sorted order, though we're still left
1593 * doing a fair number of string comparisons.
1595 static u4 getMethodIdx(const Method* method)
1597 DexFile* pDexFile = method->clazz->pDvmDex->pDexFile;
1598 u4 hi = pDexFile->pHeader->methodIdsSize -1;
1604 cur = (lo + hi) / 2;
1606 cmp = compareMethodStr(pDexFile, cur, method);
1609 } else if (cmp > 0) {
1617 /* this should be impossible -- the method came out of this DEX */
1618 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1619 ALOGE("Unable to find method %s.%s %s in DEX file!",
1620 method->clazz->descriptor, method->name, desc);
1629 * Find the DexAnnotationSetItem for this method.
1631 * Returns NULL if none found.
1633 static const DexAnnotationSetItem* findAnnotationSetForMethod(
1634 const Method* method)
1636 ClassObject* clazz = method->clazz;
1638 const DexAnnotationsDirectoryItem* pAnnoDir;
1639 const DexMethodAnnotationsItem* pMethodList;
1640 const DexAnnotationSetItem* pAnnoSet = NULL;
1642 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */
1644 pDexFile = clazz->pDvmDex->pDexFile;
1646 pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1647 if (pAnnoDir != NULL) {
1648 pMethodList = dexGetMethodAnnotations(pDexFile, pAnnoDir);
1649 if (pMethodList != NULL) {
1651 * Run through the list and find a matching method. We compare the
1652 * method ref indices in the annotation list with the method's DEX
1655 * TODO: use a binary search for long lists
1657 * Alternate approach: for each entry in the annotations list,
1658 * find the method definition in the DEX file and perform string
1659 * comparisons on class name, method name, and signature.
1661 u4 methodIdx = getMethodIdx(method);
1662 u4 count = dexGetMethodAnnotationsSize(pDexFile, pAnnoDir);
1665 for (idx = 0; idx < count; idx++) {
1666 if (pMethodList[idx].methodIdx == methodIdx) {
1668 pAnnoSet = dexGetMethodAnnotationSetItem(pDexFile,
1680 * Return an array of Annotation objects for the method. Returns an empty
1681 * array if there are no annotations.
1683 * Caller must call dvmReleaseTrackedAlloc().
1685 * On allocation failure, this returns NULL with an exception raised.
1687 ArrayObject* dvmGetMethodAnnotations(const Method* method)
1689 ClassObject* clazz = method->clazz;
1690 const DexAnnotationSetItem* pAnnoSet;
1691 ArrayObject* annoArray = NULL;
1693 pAnnoSet = findAnnotationSetForMethod(method);
1694 if (pAnnoSet == NULL) {
1695 /* no matching annotations found */
1696 annoArray = emptyAnnoArray();
1698 annoArray = processAnnotationSet(clazz, pAnnoSet,kDexVisibilityRuntime);
1705 * Returns the annotation or NULL if it doesn't exist.
1707 Object* dvmGetMethodAnnotation(const ClassObject* clazz, const Method* method,
1708 const ClassObject* annotationClazz)
1710 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForMethod(method);
1711 if (pAnnoSet == NULL) {
1714 return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet,
1715 kDexVisibilityRuntime, annotationClazz);
1719 * Returns true if the annotation exists.
1721 bool dvmIsMethodAnnotationPresent(const ClassObject* clazz,
1722 const Method* method, const ClassObject* annotationClazz)
1724 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForMethod(method);
1725 if (pAnnoSet == NULL) {
1728 const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet(
1729 clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz);
1730 return (pAnnoItem != NULL);
1734 * Retrieve the Signature annotation, if any. Returns NULL if no signature
1737 * Caller must call dvmReleaseTrackedAlloc().
1739 ArrayObject* dvmGetMethodSignatureAnnotation(const Method* method)
1741 ClassObject* clazz = method->clazz;
1742 const DexAnnotationSetItem* pAnnoSet;
1743 ArrayObject* signature = NULL;
1745 pAnnoSet = findAnnotationSetForMethod(method);
1746 if (pAnnoSet != NULL)
1747 signature = getSignatureValue(clazz, pAnnoSet);
1753 * Extract an array of exception classes from the "system" annotation list
1756 * Caller must call dvmReleaseTrackedAlloc().
1758 * Returns NULL if we don't find any exceptions for this method.
1760 ArrayObject* dvmGetMethodThrows(const Method* method)
1762 ClassObject* clazz = method->clazz;
1763 const DexAnnotationSetItem* pAnnoSet;
1764 const DexAnnotationItem* pAnnoItem;
1766 /* find the set for this method */
1767 pAnnoSet = findAnnotationSetForMethod(method);
1768 if (pAnnoSet == NULL)
1769 return NULL; /* nothing for this method */
1771 /* find the "Throws" annotation, if any */
1772 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrThrows,
1773 kDexVisibilitySystem);
1774 if (pAnnoItem == NULL)
1775 return NULL; /* no Throws */
1778 * The Throws annotation has one member, "Class[] value".
1780 Object* obj = getAnnotationValue(clazz, pAnnoItem, "value",
1781 kDexAnnotationArray, "Throws");
1782 if (obj == GAV_FAILED)
1784 assert(dvmIsArray((ArrayObject*)obj));
1785 obj = convertReturnType(obj, gDvm.classJavaLangClassArray);
1786 return (ArrayObject*)obj;
1790 * Given an Annotation's method, find the default value, if any.
1792 * If this is a CLASS annotation, and we can't find a match for the
1793 * default class value, we need to throw a TypeNotPresentException.
1795 * Caller must call dvmReleaseTrackedAlloc().
1797 Object* dvmGetAnnotationDefaultValue(const Method* method)
1799 const ClassObject* clazz = method->clazz;
1800 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1801 const DexAnnotationsDirectoryItem* pAnnoDir;
1802 const DexAnnotationSetItem* pAnnoSet = NULL;
1805 * The method's declaring class (the annotation) will have an
1806 * AnnotationDefault "system" annotation associated with it if any
1807 * of its methods have default values. Start by finding the
1808 * DexAnnotationItem associated with the class.
1810 pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1811 if (pAnnoDir != NULL)
1812 pAnnoSet = dexGetClassAnnotationSet(pDexFile, pAnnoDir);
1813 if (pAnnoSet == NULL) {
1814 /* no annotations for anything in class, or no class annotations */
1818 /* find the "AnnotationDefault" annotation, if any */
1819 const DexAnnotationItem* pAnnoItem;
1820 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrAnnotationDefault,
1821 kDexVisibilitySystem);
1822 if (pAnnoItem == NULL) {
1823 /* no default values for any member in this annotation */
1824 //printf("##### no default annotations for %s.%s\n",
1825 // method->clazz->descriptor, method->name);
1830 * The AnnotationDefault annotation has one member, "Annotation value".
1831 * We need to pull that out.
1834 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "value");
1836 ALOGW("AnnotationDefault annotation lacks 'value'");
1839 if ((*ptr & kDexAnnotationValueTypeMask) != kDexAnnotationAnnotation) {
1840 ALOGW("AnnotationDefault value has wrong type (0x%02x)",
1841 *ptr & kDexAnnotationValueTypeMask);
1846 * The value_type byte for VALUE_ANNOTATION is followed by
1847 * encoded_annotation data. We want to scan through it to find an
1848 * entry whose name matches our method name.
1851 ptr = searchEncodedAnnotation(clazz, ptr, method->name);
1853 return NULL; /* no default annotation for this method */
1855 /* got it, pull it out */
1856 AnnotationValue avalue;
1857 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects)) {
1858 ALOGD("processAnnotationValue failed on default for '%s'",
1863 /* convert the return type, if necessary */
1864 ClassObject* methodReturn = dvmGetBoxedReturnType(method);
1865 Object* obj = (Object*)avalue.value.l;
1866 obj = convertReturnType(obj, methodReturn);
1873 * ===========================================================================
1875 * ===========================================================================
1879 * Compare the attributes (class name, field name, field signature) of
1880 * the specified field to "field".
1882 static int compareFieldStr(DexFile* pDexFile, u4 idx, const Field* field)
1884 const DexFieldId* pFieldId = dexGetFieldId(pDexFile, idx);
1885 const char* str = dexStringByTypeIdx(pDexFile, pFieldId->classIdx);
1886 int result = strcmp(str, field->clazz->descriptor);
1889 str = dexStringById(pDexFile, pFieldId->nameIdx);
1890 result = strcmp(str, field->name);
1892 str = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
1893 result = strcmp(str, field->signature);
1901 * Given a field, determine the field's index.
1903 * This has the same tradeoffs as getMethodIdx.
1905 static u4 getFieldIdx(const Field* field)
1907 DexFile* pDexFile = field->clazz->pDvmDex->pDexFile;
1908 u4 hi = pDexFile->pHeader->fieldIdsSize -1;
1914 cur = (lo + hi) / 2;
1916 cmp = compareFieldStr(pDexFile, cur, field);
1919 } else if (cmp > 0) {
1927 /* this should be impossible -- the field came out of this DEX */
1928 ALOGE("Unable to find field %s.%s %s in DEX file!",
1929 field->clazz->descriptor, field->name, field->signature);
1937 * Find the DexAnnotationSetItem for this field.
1939 * Returns NULL if none found.
1941 static const DexAnnotationSetItem* findAnnotationSetForField(const Field* field)
1943 ClassObject* clazz = field->clazz;
1944 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1945 const DexAnnotationsDirectoryItem* pAnnoDir;
1946 const DexFieldAnnotationsItem* pFieldList;
1948 pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1949 if (pAnnoDir == NULL)
1952 pFieldList = dexGetFieldAnnotations(pDexFile, pAnnoDir);
1953 if (pFieldList == NULL)
1957 * Run through the list and find a matching field. We compare the
1958 * field ref indices in the annotation list with the field's DEX
1961 * TODO: use a binary search for long lists
1963 * Alternate approach: for each entry in the annotations list,
1964 * find the field definition in the DEX file and perform string
1965 * comparisons on class name, field name, and signature.
1967 u4 fieldIdx = getFieldIdx(field);
1968 u4 count = dexGetFieldAnnotationsSize(pDexFile, pAnnoDir);
1971 for (idx = 0; idx < count; idx++) {
1972 if (pFieldList[idx].fieldIdx == fieldIdx) {
1974 return dexGetFieldAnnotationSetItem(pDexFile, &pFieldList[idx]);
1982 * Return an array of Annotation objects for the field. Returns an empty
1983 * array if there are no annotations.
1985 * Caller must call dvmReleaseTrackedAlloc().
1987 * On allocation failure, this returns NULL with an exception raised.
1989 ArrayObject* dvmGetFieldAnnotations(const Field* field)
1991 ClassObject* clazz = field->clazz;
1992 ArrayObject* annoArray = NULL;
1993 const DexAnnotationSetItem* pAnnoSet = NULL;
1995 pAnnoSet = findAnnotationSetForField(field);
1996 if (pAnnoSet == NULL) {
1997 /* no matching annotations found */
1998 annoArray = emptyAnnoArray();
2000 annoArray = processAnnotationSet(clazz, pAnnoSet,
2001 kDexVisibilityRuntime);
2008 * Returns the annotation or NULL if it doesn't exist.
2010 Object* dvmGetFieldAnnotation(const ClassObject* clazz, const Field* field,
2011 const ClassObject* annotationClazz)
2013 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForField(field);
2014 if (pAnnoSet == NULL) {
2017 return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet,
2018 kDexVisibilityRuntime, annotationClazz);
2022 * Returns true if the annotation exists.
2024 bool dvmIsFieldAnnotationPresent(const ClassObject* clazz,
2025 const Field* field, const ClassObject* annotationClazz)
2027 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForField(field);
2028 if (pAnnoSet == NULL) {
2031 const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet(
2032 clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz);
2033 return (pAnnoItem != NULL);
2037 * Retrieve the Signature annotation, if any. Returns NULL if no signature
2040 * Caller must call dvmReleaseTrackedAlloc().
2042 ArrayObject* dvmGetFieldSignatureAnnotation(const Field* field)
2044 ClassObject* clazz = field->clazz;
2045 const DexAnnotationSetItem* pAnnoSet;
2046 ArrayObject* signature = NULL;
2048 pAnnoSet = findAnnotationSetForField(field);
2049 if (pAnnoSet != NULL)
2050 signature = getSignatureValue(clazz, pAnnoSet);
2057 * ===========================================================================
2059 * ===========================================================================
2063 * We have an annotation_set_ref_list, which is essentially a list of
2064 * entries that we pass to processAnnotationSet().
2066 * The returned object must be released with dvmReleaseTrackedAlloc.
2068 static ArrayObject* processAnnotationSetRefList(const ClassObject* clazz,
2069 const DexAnnotationSetRefList* pAnnoSetList, u4 count)
2071 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2072 ArrayObject* annoArrayArray = NULL;
2075 /* allocate an array of Annotation arrays to hold results */
2076 annoArrayArray = dvmAllocArrayByClass(
2077 gDvm.classJavaLangAnnotationAnnotationArrayArray, count, ALLOC_DEFAULT);
2078 if (annoArrayArray == NULL) {
2079 ALOGW("annotation set ref array alloc failed");
2083 for (idx = 0; idx < count; idx++) {
2084 Thread* self = dvmThreadSelf();
2085 const DexAnnotationSetRefItem* pItem;
2086 const DexAnnotationSetItem* pAnnoSet;
2089 pItem = dexGetParameterAnnotationSetRef(pAnnoSetList, idx);
2090 pAnnoSet = dexGetSetRefItemItem(pDexFile, pItem);
2091 annoSet = (Object *)processAnnotationSet(clazz,
2093 kDexVisibilityRuntime);
2094 if (annoSet == NULL) {
2095 ALOGW("processAnnotationSet failed");
2096 annoArrayArray = NULL;
2099 dvmSetObjectArrayElement(annoArrayArray, idx, annoSet);
2100 dvmReleaseTrackedAlloc((Object*) annoSet, self);
2104 return annoArrayArray;
2108 * Find the DexAnnotationSetItem for this parameter.
2110 * Returns NULL if none found.
2112 static const DexParameterAnnotationsItem* findAnnotationsItemForMethod(
2113 const Method* method)
2115 ClassObject* clazz = method->clazz;
2117 const DexAnnotationsDirectoryItem* pAnnoDir;
2118 const DexParameterAnnotationsItem* pParameterList;
2120 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */
2123 pDexFile = clazz->pDvmDex->pDexFile;
2124 pAnnoDir = getAnnoDirectory(pDexFile, clazz);
2125 if (pAnnoDir == NULL)
2128 pParameterList = dexGetParameterAnnotations(pDexFile, pAnnoDir);
2129 if (pParameterList == NULL)
2133 * Run through the list and find a matching method. We compare the
2134 * method ref indices in the annotation list with the method's DEX
2137 * TODO: use a binary search for long lists
2139 * Alternate approach: for each entry in the annotations list,
2140 * find the method definition in the DEX file and perform string
2141 * comparisons on class name, method name, and signature.
2143 u4 methodIdx = getMethodIdx(method);
2144 u4 count = dexGetParameterAnnotationsSize(pDexFile, pAnnoDir);
2147 for (idx = 0; idx < count; idx++) {
2148 if (pParameterList[idx].methodIdx == methodIdx) {
2150 return &pParameterList[idx];
2159 * Count up the number of arguments the method takes. The "this" pointer
2162 static int countMethodArguments(const Method* method)
2164 /* method->shorty[0] is the return type */
2165 return strlen(method->shorty + 1);
2169 * Return an array of arrays of Annotation objects. The outer array has
2170 * one entry per method parameter, the inner array has the list of annotations
2171 * associated with that parameter.
2173 * If the method has no parameters, we return an array of length zero. If
2174 * the method has one or more parameters, we return an array whose length
2175 * is equal to the number of parameters; if a given parameter does not have
2176 * an annotation, the corresponding entry will be null.
2178 * Caller must call dvmReleaseTrackedAlloc().
2180 ArrayObject* dvmGetParameterAnnotations(const Method* method)
2182 ClassObject* clazz = method->clazz;
2183 const DexParameterAnnotationsItem* pItem;
2184 ArrayObject* annoArrayArray = NULL;
2186 pItem = findAnnotationsItemForMethod(method);
2187 if (pItem != NULL) {
2188 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2189 const DexAnnotationSetRefList* pAnnoSetList;
2192 size = dexGetParameterAnnotationSetRefSize(pDexFile, pItem);
2193 pAnnoSetList = dexGetParameterAnnotationSetRefList(pDexFile, pItem);
2194 annoArrayArray = processAnnotationSetRefList(clazz, pAnnoSetList, size);
2196 /* no matching annotations found */
2197 annoArrayArray = emptyAnnoArrayArray(countMethodArguments(method));
2200 return annoArrayArray;
2205 * ===========================================================================
2206 * DexEncodedArray interpretation
2207 * ===========================================================================
2211 * Initializes an encoded array iterator.
2213 * @param iterator iterator to initialize
2214 * @param encodedArray encoded array to iterate over
2215 * @param clazz class to use when resolving strings and types
2217 void dvmEncodedArrayIteratorInitialize(EncodedArrayIterator* iterator,
2218 const DexEncodedArray* encodedArray, const ClassObject* clazz) {
2219 iterator->encodedArray = encodedArray;
2220 iterator->cursor = encodedArray->array;
2221 iterator->size = readUleb128(&iterator->cursor);
2222 iterator->elementsLeft = iterator->size;
2223 iterator->clazz = clazz;
2227 * Returns whether there are more elements to be read.
2229 bool dvmEncodedArrayIteratorHasNext(const EncodedArrayIterator* iterator) {
2230 return (iterator->elementsLeft != 0);
2234 * Returns the next decoded value from the iterator, advancing its
2235 * cursor. This returns primitive values in their corresponding union
2236 * slots, and returns everything else (including nulls) as object
2237 * references in the "l" union slot.
2239 * The caller must call dvmReleaseTrackedAlloc() on any returned reference.
2241 * @param value pointer to store decoded value into
2242 * @returns true if a value was decoded and the cursor advanced; false if
2243 * the last value had already been decoded or if there was a problem decoding
2245 bool dvmEncodedArrayIteratorGetNext(EncodedArrayIterator* iterator,
2246 AnnotationValue* value) {
2249 if (iterator->elementsLeft == 0) {
2253 processed = processAnnotationValue(iterator->clazz, &iterator->cursor,
2254 value, kPrimitivesOrObjects);
2257 ALOGE("Failed to process array element %d from %p",
2258 iterator->size - iterator->elementsLeft,
2259 iterator->encodedArray);
2260 iterator->elementsLeft = 0;
2264 iterator->elementsLeft--;