java_lang_reflect_Field.cpp revision c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2ef
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 */
58static 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 */
138static 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 */
187static 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 */
266static 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 */
279static 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 */
334static 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 */
422static 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 */
436static 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 */
454static 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 */
489static 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 */
522static 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 */
562static 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 */
605static 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 */
624static 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 */
639static 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 */
655static 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
671const 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