diff options
Diffstat (limited to 'vm/native/java_lang_reflect_Field.cpp')
-rw-r--r-- | vm/native/java_lang_reflect_Field.cpp | 719 |
1 files changed, 719 insertions, 0 deletions
diff --git a/vm/native/java_lang_reflect_Field.cpp b/vm/native/java_lang_reflect_Field.cpp new file mode 100644 index 0000000..d1918bc --- /dev/null +++ b/vm/native/java_lang_reflect_Field.cpp @@ -0,0 +1,719 @@ +/* + * 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 }, +}; |