Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      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
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     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.
     15  */
     16 
     17 /*
     18  * java.lang.reflect.Field
     19  */
     20 #include "Dalvik.h"
     21 #include "native/InternalNativePriv.h"
     22 
     23 
     24 /*
     25  * Validate access to a field.  Returns a pointer to the Field struct.
     26  *
     27  * "declaringClass" is the class in which the field was declared.  For an
     28  * instance field, "obj" is the object that holds the field data; for a
     29  * static field its value is ignored.
     30  *
     31  * "If the underlying field is static, the class that declared the
     32  * field is initialized if it has not already been initialized."
     33  *
     34  * On failure, throws an exception and returns NULL.
     35  *
     36  * The documentation lists exceptional conditions and the exceptions that
     37  * should be thrown, but doesn't say which exception prevails when two or
     38  * more exceptional conditions exist at the same time.  For example,
     39  * attempting to set a protected field from an unrelated class causes an
     40  * IllegalAccessException, while passing in a data type that doesn't match
     41  * the field causes an IllegalArgumentException.  If code does both at the
     42  * same time, we have to choose one or the other.
     43  *
     44  * The expected order is:
     45  *  (1) Check for illegal access. Throw IllegalAccessException.
     46  *  (2) Make sure the object actually has the field.  Throw
     47  *      IllegalArgumentException.
     48  *  (3) Make sure the field matches the expected type, e.g. if we issued
     49  *      a "getInteger" call make sure the field is an integer or can be
     50  *      converted to an int with a widening conversion.  Throw
     51  *      IllegalArgumentException.
     52  *  (4) Make sure "obj" is not null.  Throw NullPointerException.
     53  *
     54  * TODO: we're currently handling #3 after #4, because we don't check the
     55  * widening conversion until we're actually extracting the value from the
     56  * object (which won't work well if it's a null reference).
     57  */
     58 static Field* validateFieldAccess(Object* obj, ClassObject* declaringClass,
     59     int slot, bool isSetOperation, bool noAccessCheck)
     60 {
     61     Field* field;
     62 
     63     field = dvmSlotToField(declaringClass, slot);
     64     assert(field != NULL);
     65 
     66     /* verify access */
     67     if (!noAccessCheck) {
     68         if (isSetOperation && dvmIsFinalField(field)) {
     69             dvmThrowIllegalAccessException("field is marked 'final'");
     70             return NULL;
     71         }
     72 
     73         ClassObject* callerClass =
     74             dvmGetCaller2Class(dvmThreadSelf()->interpSave.curFrame);
     75 
     76         /*
     77          * We need to check two things:
     78          *  (1) Would an instance of the calling class have access to the field?
     79          *  (2) If the field is "protected", is the object an instance of the
     80          *      calling class, or is the field's declaring class in the same
     81          *      package as the calling class?
     82          *
     83          * #1 is basic access control.  #2 ensures that, just because
     84          * you're a subclass of Foo, you can't mess with protected fields
     85          * in arbitrary Foo objects from other packages.
     86          */
     87         if (!dvmCheckFieldAccess(callerClass, field)) {
     88             dvmThrowIllegalAccessException("access to field not allowed");
     89             return NULL;
     90         }
     91         if (dvmIsProtectedField(field)) {
     92             bool isInstance, samePackage;
     93 
     94             if (obj != NULL)
     95                 isInstance = dvmInstanceof(obj->clazz, callerClass);
     96             else
     97                 isInstance = false;
     98             samePackage = dvmInSamePackage(declaringClass, callerClass);
     99 
    100             if (!isInstance && !samePackage) {
    101                 dvmThrowIllegalAccessException(
    102                     "access to protected field not allowed");
    103                 return NULL;
    104             }
    105         }
    106     }
    107 
    108     if (dvmIsStaticField(field)) {
    109         /* init class if necessary, then return ptr to storage in "field" */
    110         if (!dvmIsClassInitialized(declaringClass)) {
    111             if (!dvmInitClass(declaringClass)) {
    112                 assert(dvmCheckException(dvmThreadSelf()));
    113                 return NULL;
    114             }
    115         }
    116 
    117     } else {
    118         /*
    119          * Verify object is of correct type (i.e. it actually has the
    120          * expected field in it), then grab a pointer to obj storage.
    121          * The call to dvmVerifyObjectInClass throws an NPE if "obj" is NULL.
    122          */
    123         if (!dvmVerifyObjectInClass(obj, declaringClass)) {
    124             assert(dvmCheckException(dvmThreadSelf()));
    125             return NULL;
    126         }
    127     }
    128 
    129     return field;
    130 }
    131 
    132 /*
    133  * Extracts the value of a static field.  Provides appropriate barriers
    134  * for volatile fields.
    135  *
    136  * Sub-32-bit values are sign- or zero-extended to fill out 32 bits.
    137  */
    138 static void getStaticFieldValue(const StaticField* sfield, JValue* value)
    139 {
    140     if (!dvmIsVolatileField(sfield)) {
    141         /* just copy the whole thing */
    142         *value = sfield->value;
    143     } else {
    144         /* need memory barriers and/or 64-bit atomic ops */
    145         switch (sfield->signature[0]) {
    146         case 'Z':
    147             value->i = dvmGetStaticFieldBooleanVolatile(sfield);
    148             break;
    149         case 'B':
    150             value->i = dvmGetStaticFieldByteVolatile(sfield);
    151             break;
    152         case 'S':
    153             value->i = dvmGetStaticFieldShortVolatile(sfield);
    154             break;
    155         case 'C':
    156             value->i = dvmGetStaticFieldCharVolatile(sfield);
    157             break;
    158         case 'I':
    159             value->i = dvmGetStaticFieldIntVolatile(sfield);
    160             break;
    161         case 'F':
    162             value->f = dvmGetStaticFieldFloatVolatile(sfield);
    163             break;
    164         case 'J':
    165             value->j = dvmGetStaticFieldLongVolatile(sfield);
    166             break;
    167         case 'D':
    168             value->d = dvmGetStaticFieldDoubleVolatile(sfield);
    169             break;
    170         case 'L':
    171         case '[':
    172             value->l = dvmGetStaticFieldObjectVolatile(sfield);
    173             break;
    174         default:
    175             LOGE("Unhandled field signature '%s'", sfield->signature);
    176             dvmAbort();
    177         }
    178     }
    179 }
    180 
    181 /*
    182  * Extracts the value of an instance field.  Provides appropriate barriers
    183  * for volatile fields.
    184  *
    185  * Sub-32-bit values are sign- or zero-extended to fill out 32 bits.
    186  */
    187 static void getInstFieldValue(const InstField* ifield, Object* obj,
    188     JValue* value)
    189 {
    190     if (!dvmIsVolatileField(ifield)) {
    191         /* use type-specific get; really just 32-bit vs. 64-bit */
    192         switch (ifield->signature[0]) {
    193         case 'Z':
    194             value->i = dvmGetFieldBoolean(obj, ifield->byteOffset);
    195             break;
    196         case 'B':
    197             value->i = dvmGetFieldByte(obj, ifield->byteOffset);
    198             break;
    199         case 'S':
    200             value->i = dvmGetFieldShort(obj, ifield->byteOffset);
    201             break;
    202         case 'C':
    203             value->i = dvmGetFieldChar(obj, ifield->byteOffset);
    204             break;
    205         case 'I':
    206             value->i = dvmGetFieldInt(obj, ifield->byteOffset);
    207             break;
    208         case 'F':
    209             value->f = dvmGetFieldFloat(obj, ifield->byteOffset);
    210             break;
    211         case 'J':
    212             value->j = dvmGetFieldLong(obj, ifield->byteOffset);
    213             break;
    214         case 'D':
    215             value->d = dvmGetFieldDouble(obj, ifield->byteOffset);
    216             break;
    217         case 'L':
    218         case '[':
    219             value->l = dvmGetFieldObject(obj, ifield->byteOffset);
    220             break;
    221         default:
    222             LOGE("Unhandled field signature '%s'", ifield->signature);
    223             dvmAbort();
    224         }
    225     } else {
    226         /* need memory barriers and/or 64-bit atomic ops */
    227         switch (ifield->signature[0]) {
    228         case 'Z':
    229             value->i = dvmGetFieldBooleanVolatile(obj, ifield->byteOffset);
    230             break;
    231         case 'B':
    232             value->i = dvmGetFieldByteVolatile(obj, ifield->byteOffset);
    233             break;
    234         case 'S':
    235             value->i = dvmGetFieldShortVolatile(obj, ifield->byteOffset);
    236             break;
    237         case 'C':
    238             value->i = dvmGetFieldCharVolatile(obj, ifield->byteOffset);
    239             break;
    240         case 'I':
    241             value->i = dvmGetFieldIntVolatile(obj, ifield->byteOffset);
    242             break;
    243         case 'F':
    244             value->f = dvmGetFieldFloatVolatile(obj, ifield->byteOffset);
    245             break;
    246         case 'J':
    247             value->j = dvmGetFieldLongVolatile(obj, ifield->byteOffset);
    248             break;
    249         case 'D':
    250             value->d = dvmGetFieldDoubleVolatile(obj, ifield->byteOffset);
    251             break;
    252         case 'L':
    253         case '[':
    254             value->l = dvmGetFieldObjectVolatile(obj, ifield->byteOffset);
    255             break;
    256         default:
    257             LOGE("Unhandled field signature '%s'", ifield->signature);
    258             dvmAbort();
    259         }
    260     }
    261 }
    262 
    263 /*
    264  * Copies the value of the static or instance field into "*value".
    265  */
    266 static void getFieldValue(const Field* field, Object* obj, JValue* value)
    267 {
    268     if (dvmIsStaticField(field)) {
    269         return getStaticFieldValue((const StaticField*) field, value);
    270     } else {
    271         return getInstFieldValue((const InstField*) field, obj, value);
    272     }
    273 }
    274 
    275 /*
    276  * Sets the value of a static field.  Provides appropriate barriers
    277  * for volatile fields.
    278  */
    279 static void setStaticFieldValue(StaticField* sfield, const JValue* value)
    280 {
    281     if (!dvmIsVolatileField(sfield)) {
    282         switch (sfield->signature[0]) {
    283         case 'L':
    284         case '[':
    285             dvmSetStaticFieldObject(sfield, (Object*)value->l);
    286             break;
    287         default:
    288             /* just copy the whole thing */
    289             sfield->value = *value;
    290             break;
    291         }
    292     } else {
    293         /* need memory barriers and/or 64-bit atomic ops */
    294         switch (sfield->signature[0]) {
    295         case 'Z':
    296             dvmSetStaticFieldBooleanVolatile(sfield, value->z);
    297             break;
    298         case 'B':
    299             dvmSetStaticFieldByteVolatile(sfield, value->b);
    300             break;
    301         case 'S':
    302             dvmSetStaticFieldShortVolatile(sfield, value->s);
    303             break;
    304         case 'C':
    305             dvmSetStaticFieldCharVolatile(sfield, value->c);
    306             break;
    307         case 'I':
    308             dvmSetStaticFieldIntVolatile(sfield, value->i);
    309             break;
    310         case 'F':
    311             dvmSetStaticFieldFloatVolatile(sfield, value->f);
    312             break;
    313         case 'J':
    314             dvmSetStaticFieldLongVolatile(sfield, value->j);
    315             break;
    316         case 'D':
    317             dvmSetStaticFieldDoubleVolatile(sfield, value->d);
    318             break;
    319         case 'L':
    320         case '[':
    321             dvmSetStaticFieldObjectVolatile(sfield, (Object*)value->l);
    322             break;
    323         default:
    324             LOGE("Unhandled field signature '%s'", sfield->signature);
    325             dvmAbort();
    326         }
    327     }
    328 }
    329 
    330 /*
    331  * Sets the value of an instance field.  Provides appropriate barriers
    332  * for volatile fields.
    333  */
    334 static void setInstFieldValue(InstField* ifield, Object* obj,
    335     const JValue* value)
    336 {
    337     if (!dvmIsVolatileField(ifield)) {
    338         /* use type-specific set; really just 32-bit vs. 64-bit */
    339         switch (ifield->signature[0]) {
    340         case 'Z':
    341             dvmSetFieldBoolean(obj, ifield->byteOffset, value->z);
    342             break;
    343         case 'B':
    344             dvmSetFieldByte(obj, ifield->byteOffset, value->b);
    345             break;
    346         case 'S':
    347             dvmSetFieldShort(obj, ifield->byteOffset, value->s);
    348             break;
    349         case 'C':
    350             dvmSetFieldChar(obj, ifield->byteOffset, value->c);
    351             break;
    352         case 'I':
    353             dvmSetFieldInt(obj, ifield->byteOffset, value->i);
    354             break;
    355         case 'F':
    356             dvmSetFieldFloat(obj, ifield->byteOffset, value->f);
    357             break;
    358         case 'J':
    359             dvmSetFieldLong(obj, ifield->byteOffset, value->j);
    360             break;
    361         case 'D':
    362             dvmSetFieldDouble(obj, ifield->byteOffset, value->d);
    363             break;
    364         case 'L':
    365         case '[':
    366             dvmSetFieldObject(obj, ifield->byteOffset, (Object *)value->l);
    367             break;
    368         default:
    369             LOGE("Unhandled field signature '%s'", ifield->signature);
    370             dvmAbort();
    371         }
    372 #if ANDROID_SMP != 0
    373         /*
    374          * Special handling for final fields on SMP systems.  We need a
    375          * store/store barrier here (JMM requirement).
    376          */
    377         if (dvmIsFinalField(ifield)) {
    378             ANDROID_MEMBAR_STORE();
    379         }
    380 #endif
    381     } else {
    382         /* need memory barriers and/or 64-bit atomic ops */
    383         switch (ifield->signature[0]) {
    384         case 'Z':
    385             dvmSetFieldBooleanVolatile(obj, ifield->byteOffset, value->z);
    386             break;
    387         case 'B':
    388             dvmSetFieldByteVolatile(obj, ifield->byteOffset, value->b);
    389             break;
    390         case 'S':
    391             dvmSetFieldShortVolatile(obj, ifield->byteOffset, value->s);
    392             break;
    393         case 'C':
    394             dvmSetFieldCharVolatile(obj, ifield->byteOffset, value->c);
    395             break;
    396         case 'I':
    397             dvmSetFieldIntVolatile(obj, ifield->byteOffset, value->i);
    398             break;
    399         case 'F':
    400             dvmSetFieldFloatVolatile(obj, ifield->byteOffset, value->f);
    401             break;
    402         case 'J':
    403             dvmSetFieldLongVolatile(obj, ifield->byteOffset, value->j);
    404             break;
    405         case 'D':
    406             dvmSetFieldDoubleVolatile(obj, ifield->byteOffset, value->d);
    407             break;
    408         case 'L':
    409         case '[':
    410             dvmSetFieldObjectVolatile(obj, ifield->byteOffset, (Object*)value->l);
    411             break;
    412         default:
    413             LOGE("Unhandled field signature '%s'", ifield->signature);
    414             dvmAbort();
    415         }
    416     }
    417 }
    418 
    419 /*
    420  * Copy "*value" into the static or instance field.
    421  */
    422 static void setFieldValue(Field* field, Object* obj, const JValue* value)
    423 {
    424     if (dvmIsStaticField(field)) {
    425         return setStaticFieldValue((StaticField*) field, value);
    426     } else {
    427         return setInstFieldValue((InstField*) field, obj, value);
    428     }
    429 }
    430 
    431 
    432 
    433 /*
    434  * public int getFieldModifiers(Class declaringClass, int slot)
    435  */
    436 static void Dalvik_java_lang_reflect_Field_getFieldModifiers(const u4* args,
    437     JValue* pResult)
    438 {
    439     /* ignore thisPtr in args[0] */
    440     ClassObject* declaringClass = (ClassObject*) args[1];
    441     int slot = args[2];
    442     Field* field;
    443 
    444     field = dvmSlotToField(declaringClass, slot);
    445     RETURN_INT(field->accessFlags & JAVA_FLAGS_MASK);
    446 }
    447 
    448 /*
    449  * private Object getField(Object o, Class declaringClass, Class type,
    450  *     int slot, boolean noAccessCheck)
    451  *
    452  * Primitive types need to be boxed.
    453  */
    454 static void Dalvik_java_lang_reflect_Field_getField(const u4* args,
    455     JValue* pResult)
    456 {
    457     /* ignore thisPtr in args[0] */
    458     Object* obj = (Object*) args[1];
    459     ClassObject* declaringClass = (ClassObject*) args[2];
    460     ClassObject* fieldType = (ClassObject*) args[3];
    461     int slot = args[4];
    462     bool noAccessCheck = (args[5] != 0);
    463     Field* field;
    464     JValue value;
    465     DataObject* result;
    466 
    467     //dvmDumpClass(obj->clazz, kDumpClassFullDetail);
    468 
    469     /* get a pointer to the Field after validating access */
    470     field = validateFieldAccess(obj, declaringClass, slot, false,noAccessCheck);
    471     if (field == NULL)
    472         RETURN_VOID();
    473 
    474     getFieldValue(field, obj, &value);
    475 
    476     /* if it's primitive, box it up */
    477     result = dvmBoxPrimitive(value, fieldType);
    478     dvmReleaseTrackedAlloc((Object*) result, NULL);
    479     RETURN_PTR(result);
    480 }
    481 
    482 /*
    483  * private void setField(Object o, Class declaringClass, Class type,
    484  *     int slot, boolean noAccessCheck, Object value)
    485  *
    486  * When assigning into a primitive field we will automatically extract
    487  * the value from box types.
    488  */
    489 static void Dalvik_java_lang_reflect_Field_setField(const u4* args,
    490     JValue* pResult)
    491 {
    492     /* ignore thisPtr in args[0] */
    493     Object* obj = (Object*) args[1];
    494     ClassObject* declaringClass = (ClassObject*) args[2];
    495     ClassObject* fieldType = (ClassObject*) args[3];
    496     int slot = args[4];
    497     bool noAccessCheck = (args[5] != 0);
    498     Object* valueObj = (Object*) args[6];
    499     Field* field;
    500     JValue value;
    501 
    502     /* unbox primitive, or verify object type */
    503     if (!dvmUnboxPrimitive(valueObj, fieldType, &value)) {
    504         dvmThrowIllegalArgumentException("invalid value for field");
    505         RETURN_VOID();
    506     }
    507 
    508     /* get a pointer to the Field after validating access */
    509     field = validateFieldAccess(obj, declaringClass, slot, true, noAccessCheck);
    510 
    511     if (field != NULL) {
    512         setFieldValue(field, obj, &value);
    513     }
    514     RETURN_VOID();
    515 }
    516 
    517 /*
    518  * Primitive field getters, e.g.:
    519  * private double getIField(Object o, Class declaringClass,
    520  *     Class type, int slot, boolean noAccessCheck, char descriptor)
    521  */
    522 static void Dalvik_java_lang_reflect_Field_getPrimitiveField(const u4* args,
    523     JValue* pResult)
    524 {
    525     /* ignore thisPtr in args[0] */
    526     Object* obj = (Object*) args[1];
    527     ClassObject* declaringClass = (ClassObject*) args[2];
    528     ClassObject* fieldType = (ClassObject*) args[3];
    529     int slot = args[4];
    530     bool noAccessCheck = (args[5] != 0);
    531     jchar descriptor = args[6];
    532     PrimitiveType targetType = dexGetPrimitiveTypeFromDescriptorChar(descriptor);
    533     const Field* field;
    534     JValue value;
    535 
    536     if (!dvmIsPrimitiveClass(fieldType)) {
    537         dvmThrowIllegalArgumentException("not a primitive field");
    538         RETURN_VOID();
    539     }
    540 
    541     /* get a pointer to the Field after validating access */
    542     field = validateFieldAccess(obj, declaringClass, slot, false,noAccessCheck);
    543     if (field == NULL)
    544         RETURN_VOID();
    545 
    546     getFieldValue(field, obj, &value);
    547 
    548     /* retrieve value, performing a widening conversion if necessary */
    549     if (dvmConvertPrimitiveValue(fieldType->primitiveType, targetType,
    550         &(value.i), &(pResult->i)) < 0)
    551     {
    552         dvmThrowIllegalArgumentException("invalid primitive conversion");
    553         RETURN_VOID();
    554     }
    555 }
    556 
    557 /*
    558  * Primitive field setters, e.g.:
    559  * private void setIField(Object o, Class declaringClass,
    560  *     Class type, int slot, boolean noAccessCheck, char descriptor, int value)
    561  */
    562 static void Dalvik_java_lang_reflect_Field_setPrimitiveField(const u4* args,
    563     JValue* pResult)
    564 {
    565     /* ignore thisPtr in args[0] */
    566     Object* obj = (Object*) args[1];
    567     ClassObject* declaringClass = (ClassObject*) args[2];
    568     ClassObject* fieldType = (ClassObject*) args[3];
    569     int slot = args[4];
    570     bool noAccessCheck = (args[5] != 0);
    571     jchar descriptor = args[6];
    572     const s4* valuePtr = (s4*) &args[7];    /* 64-bit vars spill into args[8] */
    573     PrimitiveType srcType = dexGetPrimitiveTypeFromDescriptorChar(descriptor);
    574     Field* field;
    575     JValue value;
    576 
    577     if (!dvmIsPrimitiveClass(fieldType)) {
    578         dvmThrowIllegalArgumentException("not a primitive field");
    579         RETURN_VOID();
    580     }
    581 
    582     /* convert the 32/64-bit arg to a JValue matching the field type */
    583     if (dvmConvertPrimitiveValue(srcType, fieldType->primitiveType,
    584         valuePtr, &(value.i)) < 0)
    585     {
    586         dvmThrowIllegalArgumentException("invalid primitive conversion");
    587         RETURN_VOID();
    588     }
    589 
    590     /* get a pointer to the Field after validating access */
    591     field = validateFieldAccess(obj, declaringClass, slot, true, noAccessCheck);
    592 
    593     if (field != NULL) {
    594         setFieldValue(field, obj, &value);
    595     }
    596     RETURN_VOID();
    597 }
    598 
    599 /*
    600  * private static Annotation[] getDeclaredAnnotations(
    601  *         Class declaringClass, int slot)
    602  *
    603  * Return the annotations declared for this field.
    604  */
    605 static void Dalvik_java_lang_reflect_Field_getDeclaredAnnotations(
    606     const u4* args, JValue* pResult)
    607 {
    608     ClassObject* declaringClass = (ClassObject*) args[0];
    609     int slot = args[1];
    610     Field* field;
    611 
    612     field = dvmSlotToField(declaringClass, slot);
    613     assert(field != NULL);
    614 
    615     ArrayObject* annos = dvmGetFieldAnnotations(field);
    616     dvmReleaseTrackedAlloc((Object*) annos, NULL);
    617     RETURN_PTR(annos);
    618 }
    619 
    620 /*
    621  * static Annotation getAnnotation(
    622  *         Class declaringClass, int slot, Class annotationType);
    623  */
    624 static void Dalvik_java_lang_reflect_Field_getAnnotation(const u4* args,
    625     JValue* pResult)
    626 {
    627     ClassObject* clazz = (ClassObject*) args[0];
    628     int slot = args[1];
    629     ClassObject* annotationClazz = (ClassObject*) args[2];
    630 
    631     Field* field = dvmSlotToField(clazz, slot);
    632     RETURN_PTR(dvmGetFieldAnnotation(clazz, field, annotationClazz));
    633 }
    634 
    635 /*
    636  * static boolean isAnnotationPresent(
    637  *         Class declaringClass, int slot, Class annotationType);
    638  */
    639 static void Dalvik_java_lang_reflect_Field_isAnnotationPresent(const u4* args,
    640     JValue* pResult)
    641 {
    642     ClassObject* clazz = (ClassObject*) args[0];
    643     int slot = args[1];
    644     ClassObject* annotationClazz = (ClassObject*) args[2];
    645 
    646     Field* field = dvmSlotToField(clazz, slot);
    647     RETURN_BOOLEAN(dvmIsFieldAnnotationPresent(clazz, field, annotationClazz));
    648 }
    649 
    650 /*
    651  * private Object[] getSignatureAnnotation()
    652  *
    653  * Returns the signature annotation.
    654  */
    655 static void Dalvik_java_lang_reflect_Field_getSignatureAnnotation(const u4* args,
    656     JValue* pResult)
    657 {
    658     /* ignore thisPtr in args[0] */
    659     ClassObject* declaringClass = (ClassObject*) args[1];
    660     int slot = args[2];
    661     Field* field;
    662 
    663     field = dvmSlotToField(declaringClass, slot);
    664     assert(field != NULL);
    665 
    666     ArrayObject* arr = dvmGetFieldSignatureAnnotation(field);
    667     dvmReleaseTrackedAlloc((Object*) arr, NULL);
    668     RETURN_PTR(arr);
    669 }
    670 
    671 const DalvikNativeMethod dvm_java_lang_reflect_Field[] = {
    672     { "getFieldModifiers",  "(Ljava/lang/Class;I)I",
    673         Dalvik_java_lang_reflect_Field_getFieldModifiers },
    674     { "getField",           "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;",
    675         Dalvik_java_lang_reflect_Field_getField },
    676     { "getBField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)B",
    677         Dalvik_java_lang_reflect_Field_getPrimitiveField },
    678     { "getCField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)C",
    679         Dalvik_java_lang_reflect_Field_getPrimitiveField },
    680     { "getDField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)D",
    681         Dalvik_java_lang_reflect_Field_getPrimitiveField },
    682     { "getFField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)F",
    683         Dalvik_java_lang_reflect_Field_getPrimitiveField },
    684     { "getIField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)I",
    685         Dalvik_java_lang_reflect_Field_getPrimitiveField },
    686     { "getJField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)J",
    687         Dalvik_java_lang_reflect_Field_getPrimitiveField },
    688     { "getSField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)S",
    689         Dalvik_java_lang_reflect_Field_getPrimitiveField },
    690     { "getZField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)Z",
    691         Dalvik_java_lang_reflect_Field_getPrimitiveField },
    692     { "setField",           "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZLjava/lang/Object;)V",
    693         Dalvik_java_lang_reflect_Field_setField },
    694     { "setBField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCB)V",
    695         Dalvik_java_lang_reflect_Field_setPrimitiveField },
    696     { "setCField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCC)V",
    697         Dalvik_java_lang_reflect_Field_setPrimitiveField },
    698     { "setDField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCD)V",
    699         Dalvik_java_lang_reflect_Field_setPrimitiveField },
    700     { "setFField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCF)V",
    701         Dalvik_java_lang_reflect_Field_setPrimitiveField },
    702     { "setIField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCI)V",
    703         Dalvik_java_lang_reflect_Field_setPrimitiveField },
    704     { "setJField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCJ)V",
    705         Dalvik_java_lang_reflect_Field_setPrimitiveField },
    706     { "setSField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCS)V",
    707         Dalvik_java_lang_reflect_Field_setPrimitiveField },
    708     { "setZField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCZ)V",
    709         Dalvik_java_lang_reflect_Field_setPrimitiveField },
    710     { "getDeclaredAnnotations", "(Ljava/lang/Class;I)[Ljava/lang/annotation/Annotation;",
    711         Dalvik_java_lang_reflect_Field_getDeclaredAnnotations },
    712     { "getAnnotation", "(Ljava/lang/Class;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;",
    713         Dalvik_java_lang_reflect_Field_getAnnotation },
    714     { "isAnnotationPresent", "(Ljava/lang/Class;ILjava/lang/Class;)Z",
    715         Dalvik_java_lang_reflect_Field_isAnnotationPresent },
    716     { "getSignatureAnnotation",  "(Ljava/lang/Class;I)[Ljava/lang/Object;",
    717         Dalvik_java_lang_reflect_Field_getSignatureAnnotation },
    718     { NULL, NULL, NULL },
    719 };
    720