• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
validateFieldAccess(Object * obj,ClassObject * declaringClass,int slot,bool isSetOperation,bool noAccessCheck)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  */
getStaticFieldValue(const StaticField * sfield,JValue * value)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             ALOGE("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  */
getInstFieldValue(const InstField * ifield,Object * obj,JValue * value)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             ALOGE("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             ALOGE("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  */
getFieldValue(const Field * field,Object * obj,JValue * value)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  */
setStaticFieldValue(StaticField * sfield,const JValue * value)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             ALOGE("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  */
setInstFieldValue(InstField * ifield,Object * obj,const JValue * value)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             ALOGE("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             ALOGE("Unhandled field signature '%s'", ifield->signature);
414             dvmAbort();
415         }
416     }
417 }
418 
419 /*
420  * Copy "*value" into the static or instance field.
421  */
setFieldValue(Field * field,Object * obj,const JValue * value)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  */
Dalvik_java_lang_reflect_Field_getFieldModifiers(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_reflect_Field_getField(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_reflect_Field_setField(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_reflect_Field_getPrimitiveField(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_reflect_Field_setPrimitiveField(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_reflect_Field_getDeclaredAnnotations(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_reflect_Field_getAnnotation(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_reflect_Field_isAnnotationPresent(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_reflect_Field_getSignatureAnnotation(const u4 * args,JValue * pResult)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