/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * java.lang.reflect.Field
 */
#include "Dalvik.h"
#include "native/InternalNativePriv.h"


/*
 * Validate access to a field.  Returns a pointer to the Field struct.
 *
 * "declaringClass" is the class in which the field was declared.  For an
 * instance field, "obj" is the object that holds the field data; for a
 * static field its value is ignored.
 *
 * "If the underlying field is static, the class that declared the
 * field is initialized if it has not already been initialized."
 *
 * On failure, throws an exception and returns NULL.
 *
 * The documentation lists exceptional conditions and the exceptions that
 * should be thrown, but doesn't say which exception prevails when two or
 * more exceptional conditions exist at the same time.  For example,
 * attempting to set a protected field from an unrelated class causes an
 * IllegalAccessException, while passing in a data type that doesn't match
 * the field causes an IllegalArgumentException.  If code does both at the
 * same time, we have to choose one or the other.
 *
 * The expected order is:
 *  (1) Check for illegal access. Throw IllegalAccessException.
 *  (2) Make sure the object actually has the field.  Throw
 *      IllegalArgumentException.
 *  (3) Make sure the field matches the expected type, e.g. if we issued
 *      a "getInteger" call make sure the field is an integer or can be
 *      converted to an int with a widening conversion.  Throw
 *      IllegalArgumentException.
 *  (4) Make sure "obj" is not null.  Throw NullPointerException.
 *
 * TODO: we're currently handling #3 after #4, because we don't check the
 * widening conversion until we're actually extracting the value from the
 * object (which won't work well if it's a null reference).
 */
static Field* validateFieldAccess(Object* obj, ClassObject* declaringClass,
    int slot, bool isSetOperation, bool noAccessCheck)
{
    Field* field;

    field = dvmSlotToField(declaringClass, slot);
    assert(field != NULL);

    /* verify access */
    if (!noAccessCheck) {
        if (isSetOperation && dvmIsFinalField(field)) {
            dvmThrowIllegalAccessException("field is marked 'final'");
            return NULL;
        }

        ClassObject* callerClass =
            dvmGetCaller2Class(dvmThreadSelf()->interpSave.curFrame);

        /*
         * We need to check two things:
         *  (1) Would an instance of the calling class have access to the field?
         *  (2) If the field is "protected", is the object an instance of the
         *      calling class, or is the field's declaring class in the same
         *      package as the calling class?
         *
         * #1 is basic access control.  #2 ensures that, just because
         * you're a subclass of Foo, you can't mess with protected fields
         * in arbitrary Foo objects from other packages.
         */
        if (!dvmCheckFieldAccess(callerClass, field)) {
            dvmThrowIllegalAccessException("access to field not allowed");
            return NULL;
        }
        if (dvmIsProtectedField(field)) {
            bool isInstance, samePackage;

            if (obj != NULL)
                isInstance = dvmInstanceof(obj->clazz, callerClass);
            else
                isInstance = false;
            samePackage = dvmInSamePackage(declaringClass, callerClass);

            if (!isInstance && !samePackage) {
                dvmThrowIllegalAccessException(
                    "access to protected field not allowed");
                return NULL;
            }
        }
    }

    if (dvmIsStaticField(field)) {
        /* init class if necessary, then return ptr to storage in "field" */
        if (!dvmIsClassInitialized(declaringClass)) {
            if (!dvmInitClass(declaringClass)) {
                assert(dvmCheckException(dvmThreadSelf()));
                return NULL;
            }
        }

    } else {
        /*
         * Verify object is of correct type (i.e. it actually has the
         * expected field in it), then grab a pointer to obj storage.
         * The call to dvmVerifyObjectInClass throws an NPE if "obj" is NULL.
         */
        if (!dvmVerifyObjectInClass(obj, declaringClass)) {
            assert(dvmCheckException(dvmThreadSelf()));
            return NULL;
        }
    }

    return field;
}

/*
 * Extracts the value of a static field.  Provides appropriate barriers
 * for volatile fields.
 *
 * Sub-32-bit values are sign- or zero-extended to fill out 32 bits.
 */
static void getStaticFieldValue(const StaticField* sfield, JValue* value)
{
    if (!dvmIsVolatileField(sfield)) {
        /* just copy the whole thing */
        *value = sfield->value;
    } else {
        /* need memory barriers and/or 64-bit atomic ops */
        switch (sfield->signature[0]) {
        case 'Z':
            value->i = dvmGetStaticFieldBooleanVolatile(sfield);
            break;
        case 'B':
            value->i = dvmGetStaticFieldByteVolatile(sfield);
            break;
        case 'S':
            value->i = dvmGetStaticFieldShortVolatile(sfield);
            break;
        case 'C':
            value->i = dvmGetStaticFieldCharVolatile(sfield);
            break;
        case 'I':
            value->i = dvmGetStaticFieldIntVolatile(sfield);
            break;
        case 'F':
            value->f = dvmGetStaticFieldFloatVolatile(sfield);
            break;
        case 'J':
            value->j = dvmGetStaticFieldLongVolatile(sfield);
            break;
        case 'D':
            value->d = dvmGetStaticFieldDoubleVolatile(sfield);
            break;
        case 'L':
        case '[':
            value->l = dvmGetStaticFieldObjectVolatile(sfield);
            break;
        default:
            LOGE("Unhandled field signature '%s'", sfield->signature);
            dvmAbort();
        }
    }
}

/*
 * Extracts the value of an instance field.  Provides appropriate barriers
 * for volatile fields.
 *
 * Sub-32-bit values are sign- or zero-extended to fill out 32 bits.
 */
static void getInstFieldValue(const InstField* ifield, Object* obj,
    JValue* value)
{
    if (!dvmIsVolatileField(ifield)) {
        /* use type-specific get; really just 32-bit vs. 64-bit */
        switch (ifield->signature[0]) {
        case 'Z':
            value->i = dvmGetFieldBoolean(obj, ifield->byteOffset);
            break;
        case 'B':
            value->i = dvmGetFieldByte(obj, ifield->byteOffset);
            break;
        case 'S':
            value->i = dvmGetFieldShort(obj, ifield->byteOffset);
            break;
        case 'C':
            value->i = dvmGetFieldChar(obj, ifield->byteOffset);
            break;
        case 'I':
            value->i = dvmGetFieldInt(obj, ifield->byteOffset);
            break;
        case 'F':
            value->f = dvmGetFieldFloat(obj, ifield->byteOffset);
            break;
        case 'J':
            value->j = dvmGetFieldLong(obj, ifield->byteOffset);
            break;
        case 'D':
            value->d = dvmGetFieldDouble(obj, ifield->byteOffset);
            break;
        case 'L':
        case '[':
            value->l = dvmGetFieldObject(obj, ifield->byteOffset);
            break;
        default:
            LOGE("Unhandled field signature '%s'", ifield->signature);
            dvmAbort();
        }
    } else {
        /* need memory barriers and/or 64-bit atomic ops */
        switch (ifield->signature[0]) {
        case 'Z':
            value->i = dvmGetFieldBooleanVolatile(obj, ifield->byteOffset);
            break;
        case 'B':
            value->i = dvmGetFieldByteVolatile(obj, ifield->byteOffset);
            break;
        case 'S':
            value->i = dvmGetFieldShortVolatile(obj, ifield->byteOffset);
            break;
        case 'C':
            value->i = dvmGetFieldCharVolatile(obj, ifield->byteOffset);
            break;
        case 'I':
            value->i = dvmGetFieldIntVolatile(obj, ifield->byteOffset);
            break;
        case 'F':
            value->f = dvmGetFieldFloatVolatile(obj, ifield->byteOffset);
            break;
        case 'J':
            value->j = dvmGetFieldLongVolatile(obj, ifield->byteOffset);
            break;
        case 'D':
            value->d = dvmGetFieldDoubleVolatile(obj, ifield->byteOffset);
            break;
        case 'L':
        case '[':
            value->l = dvmGetFieldObjectVolatile(obj, ifield->byteOffset);
            break;
        default:
            LOGE("Unhandled field signature '%s'", ifield->signature);
            dvmAbort();
        }
    }
}

/*
 * Copies the value of the static or instance field into "*value".
 */
static void getFieldValue(const Field* field, Object* obj, JValue* value)
{
    if (dvmIsStaticField(field)) {
        return getStaticFieldValue((const StaticField*) field, value);
    } else {
        return getInstFieldValue((const InstField*) field, obj, value);
    }
}

/*
 * Sets the value of a static field.  Provides appropriate barriers
 * for volatile fields.
 */
static void setStaticFieldValue(StaticField* sfield, const JValue* value)
{
    if (!dvmIsVolatileField(sfield)) {
        switch (sfield->signature[0]) {
        case 'L':
        case '[':
            dvmSetStaticFieldObject(sfield, (Object*)value->l);
            break;
        default:
            /* just copy the whole thing */
            sfield->value = *value;
            break;
        }
    } else {
        /* need memory barriers and/or 64-bit atomic ops */
        switch (sfield->signature[0]) {
        case 'Z':
            dvmSetStaticFieldBooleanVolatile(sfield, value->z);
            break;
        case 'B':
            dvmSetStaticFieldByteVolatile(sfield, value->b);
            break;
        case 'S':
            dvmSetStaticFieldShortVolatile(sfield, value->s);
            break;
        case 'C':
            dvmSetStaticFieldCharVolatile(sfield, value->c);
            break;
        case 'I':
            dvmSetStaticFieldIntVolatile(sfield, value->i);
            break;
        case 'F':
            dvmSetStaticFieldFloatVolatile(sfield, value->f);
            break;
        case 'J':
            dvmSetStaticFieldLongVolatile(sfield, value->j);
            break;
        case 'D':
            dvmSetStaticFieldDoubleVolatile(sfield, value->d);
            break;
        case 'L':
        case '[':
            dvmSetStaticFieldObjectVolatile(sfield, (Object*)value->l);
            break;
        default:
            LOGE("Unhandled field signature '%s'", sfield->signature);
            dvmAbort();
        }
    }
}

/*
 * Sets the value of an instance field.  Provides appropriate barriers
 * for volatile fields.
 */
static void setInstFieldValue(InstField* ifield, Object* obj,
    const JValue* value)
{
    if (!dvmIsVolatileField(ifield)) {
        /* use type-specific set; really just 32-bit vs. 64-bit */
        switch (ifield->signature[0]) {
        case 'Z':
            dvmSetFieldBoolean(obj, ifield->byteOffset, value->z);
            break;
        case 'B':
            dvmSetFieldByte(obj, ifield->byteOffset, value->b);
            break;
        case 'S':
            dvmSetFieldShort(obj, ifield->byteOffset, value->s);
            break;
        case 'C':
            dvmSetFieldChar(obj, ifield->byteOffset, value->c);
            break;
        case 'I':
            dvmSetFieldInt(obj, ifield->byteOffset, value->i);
            break;
        case 'F':
            dvmSetFieldFloat(obj, ifield->byteOffset, value->f);
            break;
        case 'J':
            dvmSetFieldLong(obj, ifield->byteOffset, value->j);
            break;
        case 'D':
            dvmSetFieldDouble(obj, ifield->byteOffset, value->d);
            break;
        case 'L':
        case '[':
            dvmSetFieldObject(obj, ifield->byteOffset, (Object *)value->l);
            break;
        default:
            LOGE("Unhandled field signature '%s'", ifield->signature);
            dvmAbort();
        }
#if ANDROID_SMP != 0
        /*
         * Special handling for final fields on SMP systems.  We need a
         * store/store barrier here (JMM requirement).
         */
        if (dvmIsFinalField(ifield)) {
            ANDROID_MEMBAR_STORE();
        }
#endif
    } else {
        /* need memory barriers and/or 64-bit atomic ops */
        switch (ifield->signature[0]) {
        case 'Z':
            dvmSetFieldBooleanVolatile(obj, ifield->byteOffset, value->z);
            break;
        case 'B':
            dvmSetFieldByteVolatile(obj, ifield->byteOffset, value->b);
            break;
        case 'S':
            dvmSetFieldShortVolatile(obj, ifield->byteOffset, value->s);
            break;
        case 'C':
            dvmSetFieldCharVolatile(obj, ifield->byteOffset, value->c);
            break;
        case 'I':
            dvmSetFieldIntVolatile(obj, ifield->byteOffset, value->i);
            break;
        case 'F':
            dvmSetFieldFloatVolatile(obj, ifield->byteOffset, value->f);
            break;
        case 'J':
            dvmSetFieldLongVolatile(obj, ifield->byteOffset, value->j);
            break;
        case 'D':
            dvmSetFieldDoubleVolatile(obj, ifield->byteOffset, value->d);
            break;
        case 'L':
        case '[':
            dvmSetFieldObjectVolatile(obj, ifield->byteOffset, (Object*)value->l);
            break;
        default:
            LOGE("Unhandled field signature '%s'", ifield->signature);
            dvmAbort();
        }
    }
}

/*
 * Copy "*value" into the static or instance field.
 */
static void setFieldValue(Field* field, Object* obj, const JValue* value)
{
    if (dvmIsStaticField(field)) {
        return setStaticFieldValue((StaticField*) field, value);
    } else {
        return setInstFieldValue((InstField*) field, obj, value);
    }
}



/*
 * public int getFieldModifiers(Class declaringClass, int slot)
 */
static void Dalvik_java_lang_reflect_Field_getFieldModifiers(const u4* args,
    JValue* pResult)
{
    /* ignore thisPtr in args[0] */
    ClassObject* declaringClass = (ClassObject*) args[1];
    int slot = args[2];
    Field* field;

    field = dvmSlotToField(declaringClass, slot);
    RETURN_INT(field->accessFlags & JAVA_FLAGS_MASK);
}

/*
 * private Object getField(Object o, Class declaringClass, Class type,
 *     int slot, boolean noAccessCheck)
 *
 * Primitive types need to be boxed.
 */
static void Dalvik_java_lang_reflect_Field_getField(const u4* args,
    JValue* pResult)
{
    /* ignore thisPtr in args[0] */
    Object* obj = (Object*) args[1];
    ClassObject* declaringClass = (ClassObject*) args[2];
    ClassObject* fieldType = (ClassObject*) args[3];
    int slot = args[4];
    bool noAccessCheck = (args[5] != 0);
    Field* field;
    JValue value;
    DataObject* result;

    //dvmDumpClass(obj->clazz, kDumpClassFullDetail);

    /* get a pointer to the Field after validating access */
    field = validateFieldAccess(obj, declaringClass, slot, false,noAccessCheck);
    if (field == NULL)
        RETURN_VOID();

    getFieldValue(field, obj, &value);

    /* if it's primitive, box it up */
    result = dvmBoxPrimitive(value, fieldType);
    dvmReleaseTrackedAlloc((Object*) result, NULL);
    RETURN_PTR(result);
}

/*
 * private void setField(Object o, Class declaringClass, Class type,
 *     int slot, boolean noAccessCheck, Object value)
 *
 * When assigning into a primitive field we will automatically extract
 * the value from box types.
 */
static void Dalvik_java_lang_reflect_Field_setField(const u4* args,
    JValue* pResult)
{
    /* ignore thisPtr in args[0] */
    Object* obj = (Object*) args[1];
    ClassObject* declaringClass = (ClassObject*) args[2];
    ClassObject* fieldType = (ClassObject*) args[3];
    int slot = args[4];
    bool noAccessCheck = (args[5] != 0);
    Object* valueObj = (Object*) args[6];
    Field* field;
    JValue value;

    /* unbox primitive, or verify object type */
    if (!dvmUnboxPrimitive(valueObj, fieldType, &value)) {
        dvmThrowIllegalArgumentException("invalid value for field");
        RETURN_VOID();
    }

    /* get a pointer to the Field after validating access */
    field = validateFieldAccess(obj, declaringClass, slot, true, noAccessCheck);

    if (field != NULL) {
        setFieldValue(field, obj, &value);
    }
    RETURN_VOID();
}

/*
 * Primitive field getters, e.g.:
 * private double getIField(Object o, Class declaringClass,
 *     Class type, int slot, boolean noAccessCheck, char descriptor)
 */
static void Dalvik_java_lang_reflect_Field_getPrimitiveField(const u4* args,
    JValue* pResult)
{
    /* ignore thisPtr in args[0] */
    Object* obj = (Object*) args[1];
    ClassObject* declaringClass = (ClassObject*) args[2];
    ClassObject* fieldType = (ClassObject*) args[3];
    int slot = args[4];
    bool noAccessCheck = (args[5] != 0);
    jchar descriptor = args[6];
    PrimitiveType targetType = dexGetPrimitiveTypeFromDescriptorChar(descriptor);
    const Field* field;
    JValue value;

    if (!dvmIsPrimitiveClass(fieldType)) {
        dvmThrowIllegalArgumentException("not a primitive field");
        RETURN_VOID();
    }

    /* get a pointer to the Field after validating access */
    field = validateFieldAccess(obj, declaringClass, slot, false,noAccessCheck);
    if (field == NULL)
        RETURN_VOID();

    getFieldValue(field, obj, &value);

    /* retrieve value, performing a widening conversion if necessary */
    if (dvmConvertPrimitiveValue(fieldType->primitiveType, targetType,
        &(value.i), &(pResult->i)) < 0)
    {
        dvmThrowIllegalArgumentException("invalid primitive conversion");
        RETURN_VOID();
    }
}

/*
 * Primitive field setters, e.g.:
 * private void setIField(Object o, Class declaringClass,
 *     Class type, int slot, boolean noAccessCheck, char descriptor, int value)
 */
static void Dalvik_java_lang_reflect_Field_setPrimitiveField(const u4* args,
    JValue* pResult)
{
    /* ignore thisPtr in args[0] */
    Object* obj = (Object*) args[1];
    ClassObject* declaringClass = (ClassObject*) args[2];
    ClassObject* fieldType = (ClassObject*) args[3];
    int slot = args[4];
    bool noAccessCheck = (args[5] != 0);
    jchar descriptor = args[6];
    const s4* valuePtr = (s4*) &args[7];    /* 64-bit vars spill into args[8] */
    PrimitiveType srcType = dexGetPrimitiveTypeFromDescriptorChar(descriptor);
    Field* field;
    JValue value;

    if (!dvmIsPrimitiveClass(fieldType)) {
        dvmThrowIllegalArgumentException("not a primitive field");
        RETURN_VOID();
    }

    /* convert the 32/64-bit arg to a JValue matching the field type */
    if (dvmConvertPrimitiveValue(srcType, fieldType->primitiveType,
        valuePtr, &(value.i)) < 0)
    {
        dvmThrowIllegalArgumentException("invalid primitive conversion");
        RETURN_VOID();
    }

    /* get a pointer to the Field after validating access */
    field = validateFieldAccess(obj, declaringClass, slot, true, noAccessCheck);

    if (field != NULL) {
        setFieldValue(field, obj, &value);
    }
    RETURN_VOID();
}

/*
 * private static Annotation[] getDeclaredAnnotations(
 *         Class declaringClass, int slot)
 *
 * Return the annotations declared for this field.
 */
static void Dalvik_java_lang_reflect_Field_getDeclaredAnnotations(
    const u4* args, JValue* pResult)
{
    ClassObject* declaringClass = (ClassObject*) args[0];
    int slot = args[1];
    Field* field;

    field = dvmSlotToField(declaringClass, slot);
    assert(field != NULL);

    ArrayObject* annos = dvmGetFieldAnnotations(field);
    dvmReleaseTrackedAlloc((Object*) annos, NULL);
    RETURN_PTR(annos);
}

/*
 * static Annotation getAnnotation(
 *         Class declaringClass, int slot, Class annotationType);
 */
static void Dalvik_java_lang_reflect_Field_getAnnotation(const u4* args,
    JValue* pResult)
{
    ClassObject* clazz = (ClassObject*) args[0];
    int slot = args[1];
    ClassObject* annotationClazz = (ClassObject*) args[2];

    Field* field = dvmSlotToField(clazz, slot);
    RETURN_PTR(dvmGetFieldAnnotation(clazz, field, annotationClazz));
}

/*
 * static boolean isAnnotationPresent(
 *         Class declaringClass, int slot, Class annotationType);
 */
static void Dalvik_java_lang_reflect_Field_isAnnotationPresent(const u4* args,
    JValue* pResult)
{
    ClassObject* clazz = (ClassObject*) args[0];
    int slot = args[1];
    ClassObject* annotationClazz = (ClassObject*) args[2];

    Field* field = dvmSlotToField(clazz, slot);
    RETURN_BOOLEAN(dvmIsFieldAnnotationPresent(clazz, field, annotationClazz));
}

/*
 * private Object[] getSignatureAnnotation()
 *
 * Returns the signature annotation.
 */
static void Dalvik_java_lang_reflect_Field_getSignatureAnnotation(const u4* args,
    JValue* pResult)
{
    /* ignore thisPtr in args[0] */
    ClassObject* declaringClass = (ClassObject*) args[1];
    int slot = args[2];
    Field* field;

    field = dvmSlotToField(declaringClass, slot);
    assert(field != NULL);

    ArrayObject* arr = dvmGetFieldSignatureAnnotation(field);
    dvmReleaseTrackedAlloc((Object*) arr, NULL);
    RETURN_PTR(arr);
}

const DalvikNativeMethod dvm_java_lang_reflect_Field[] = {
    { "getFieldModifiers",  "(Ljava/lang/Class;I)I",
        Dalvik_java_lang_reflect_Field_getFieldModifiers },
    { "getField",           "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;",
        Dalvik_java_lang_reflect_Field_getField },
    { "getBField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)B",
        Dalvik_java_lang_reflect_Field_getPrimitiveField },
    { "getCField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)C",
        Dalvik_java_lang_reflect_Field_getPrimitiveField },
    { "getDField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)D",
        Dalvik_java_lang_reflect_Field_getPrimitiveField },
    { "getFField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)F",
        Dalvik_java_lang_reflect_Field_getPrimitiveField },
    { "getIField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)I",
        Dalvik_java_lang_reflect_Field_getPrimitiveField },
    { "getJField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)J",
        Dalvik_java_lang_reflect_Field_getPrimitiveField },
    { "getSField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)S",
        Dalvik_java_lang_reflect_Field_getPrimitiveField },
    { "getZField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)Z",
        Dalvik_java_lang_reflect_Field_getPrimitiveField },
    { "setField",           "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZLjava/lang/Object;)V",
        Dalvik_java_lang_reflect_Field_setField },
    { "setBField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCB)V",
        Dalvik_java_lang_reflect_Field_setPrimitiveField },
    { "setCField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCC)V",
        Dalvik_java_lang_reflect_Field_setPrimitiveField },
    { "setDField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCD)V",
        Dalvik_java_lang_reflect_Field_setPrimitiveField },
    { "setFField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCF)V",
        Dalvik_java_lang_reflect_Field_setPrimitiveField },
    { "setIField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCI)V",
        Dalvik_java_lang_reflect_Field_setPrimitiveField },
    { "setJField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCJ)V",
        Dalvik_java_lang_reflect_Field_setPrimitiveField },
    { "setSField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCS)V",
        Dalvik_java_lang_reflect_Field_setPrimitiveField },
    { "setZField",          "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCZ)V",
        Dalvik_java_lang_reflect_Field_setPrimitiveField },
    { "getDeclaredAnnotations", "(Ljava/lang/Class;I)[Ljava/lang/annotation/Annotation;",
        Dalvik_java_lang_reflect_Field_getDeclaredAnnotations },
    { "getAnnotation", "(Ljava/lang/Class;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;",
        Dalvik_java_lang_reflect_Field_getAnnotation },
    { "isAnnotationPresent", "(Ljava/lang/Class;ILjava/lang/Class;)Z",
        Dalvik_java_lang_reflect_Field_isAnnotationPresent },
    { "getSignatureAnnotation",  "(Ljava/lang/Class;I)[Ljava/lang/Object;",
        Dalvik_java_lang_reflect_Field_getSignatureAnnotation },
    { NULL, NULL, NULL },
};