diff options
Diffstat (limited to 'vm/native/java_lang_reflect_Method.c')
-rw-r--r-- | vm/native/java_lang_reflect_Method.c | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/vm/native/java_lang_reflect_Method.c b/vm/native/java_lang_reflect_Method.c new file mode 100644 index 0000000..f73c8d0 --- /dev/null +++ b/vm/native/java_lang_reflect_Method.c @@ -0,0 +1,219 @@ +/* + * 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.Method + */ +#include "Dalvik.h" +#include "native/InternalNativePriv.h" + + +/* + * private int getMethodModifiers(Class decl_class, int slot) + * + * (Not sure why the access flags weren't stored in the class along with + * everything else. Not sure why this isn't static.) + */ +static void Dalvik_java_lang_reflect_Method_getMethodModifiers(const u4* args, + JValue* pResult) +{ + // ignore thisPtr in args[0] + ClassObject* declaringClass = (ClassObject*) args[1]; + int slot = args[2]; + Method* meth; + + meth = dvmSlotToMethod(declaringClass, slot); + RETURN_INT(dvmFixMethodFlags(meth->accessFlags)); +} + +/* + * private Object invokeNative(Object obj, Object[] args, Class declaringClass, + * Class[] parameterTypes, Class returnType, int slot, boolean noAccessCheck) + * + * Invoke a static or virtual method via reflection. + */ +static void Dalvik_java_lang_reflect_Method_invokeNative(const u4* args, + JValue* pResult) +{ + // ignore thisPtr in args[0] + Object* methObj = (Object*) args[1]; // null for static methods + ArrayObject* argList = (ArrayObject*) args[2]; + ClassObject* declaringClass = (ClassObject*) args[3]; + ArrayObject* params = (ArrayObject*) args[4]; + ClassObject* returnType = (ClassObject*) args[5]; + int slot = args[6]; + bool noAccessCheck = (args[7] != 0); + const Method* meth; + Object* result; + + /* + * "If the underlying method is static, the class that declared the + * method is initialized if it has not already been initialized." + */ + meth = dvmSlotToMethod(declaringClass, slot); + assert(meth != NULL); + + if (dvmIsStaticMethod(meth)) { + if (!dvmIsClassInitialized(declaringClass)) { + if (!dvmInitClass(declaringClass)) + goto init_failed; + } + } else { + /* looks like interfaces need this too? */ + if (dvmIsInterfaceClass(declaringClass) && + !dvmIsClassInitialized(declaringClass)) + { + if (!dvmInitClass(declaringClass)) + goto init_failed; + } + + /* make sure the object is an instance of the expected class */ + if (!dvmVerifyObjectInClass(methObj, declaringClass)) { + assert(dvmCheckException(dvmThreadSelf())); + RETURN_VOID(); + } + + /* do the virtual table lookup for the method */ + meth = dvmGetVirtualizedMethod(methObj->clazz, meth); + if (meth == NULL) { + assert(dvmCheckException(dvmThreadSelf())); + RETURN_VOID(); + } + } + + /* + * If the method has a return value, "result" will be an object or + * a boxed primitive. + */ + result = dvmInvokeMethod(methObj, meth, argList, params, returnType, + noAccessCheck); + + RETURN_PTR(result); + +init_failed: + /* + * If initialization failed, an exception will be raised. + */ + LOGD("Method.invoke() on bad class %s failed\n", + declaringClass->descriptor); + assert(dvmCheckException(dvmThreadSelf())); + RETURN_VOID(); +} + +/* + * public Annotation[] getDeclaredAnnotations(Class declaringClass, int slot) + * + * Return the annotations declared for this method. + */ +static void Dalvik_java_lang_reflect_Method_getDeclaredAnnotations( + const u4* args, JValue* pResult) +{ + // ignore thisPtr in args[0] + ClassObject* declaringClass = (ClassObject*) args[1]; + int slot = args[2]; + Method* meth; + + meth = dvmSlotToMethod(declaringClass, slot); + assert(meth != NULL); + + ArrayObject* annos = dvmGetMethodAnnotations(meth); + dvmReleaseTrackedAlloc((Object*)annos, NULL); + RETURN_PTR(annos); +} + +/* + * public Annotation[] getParameterAnnotations(Class declaringClass, int slot) + * + * Return the annotations declared for this method's parameters. + */ +static void Dalvik_java_lang_reflect_Method_getParameterAnnotations( + const u4* args, JValue* pResult) +{ + // ignore thisPtr in args[0] + ClassObject* declaringClass = (ClassObject*) args[1]; + int slot = args[2]; + Method* meth; + + meth = dvmSlotToMethod(declaringClass, slot); + assert(meth != NULL); + + ArrayObject* annos = dvmGetParameterAnnotations(meth); + dvmReleaseTrackedAlloc((Object*)annos, NULL); + RETURN_PTR(annos); +} + +/* + * private Object getDefaultValue(Class declaringClass, int slot) + * + * Return the default value for the annotation member represented by + * this Method instance. Returns NULL if none is defined. + */ +static void Dalvik_java_lang_reflect_Method_getDefaultValue(const u4* args, + JValue* pResult) +{ + // ignore thisPtr in args[0] + ClassObject* declaringClass = (ClassObject*) args[1]; + int slot = args[2]; + Method* meth; + + /* make sure this is an annotation class member */ + if (!dvmIsAnnotationClass(declaringClass)) + RETURN_PTR(NULL); + + meth = dvmSlotToMethod(declaringClass, slot); + assert(meth != NULL); + + Object* def = dvmGetAnnotationDefaultValue(meth); + dvmReleaseTrackedAlloc(def, NULL); + RETURN_PTR(def); +} + +/* + * private Object[] getSignatureAnnotation() + * + * Returns the signature annotation. + */ +static void Dalvik_java_lang_reflect_Method_getSignatureAnnotation( + const u4* args, JValue* pResult) +{ + // ignore thisPtr in args[0] + ClassObject* declaringClass = (ClassObject*) args[1]; + int slot = args[2]; + Method* meth; + + meth = dvmSlotToMethod(declaringClass, slot); + assert(meth != NULL); + + ArrayObject* arr = dvmGetMethodSignatureAnnotation(meth); + dvmReleaseTrackedAlloc((Object*) arr, NULL); + RETURN_PTR(arr); +} + +const DalvikNativeMethod dvm_java_lang_reflect_Method[] = { + { "getMethodModifiers", "(Ljava/lang/Class;I)I", + Dalvik_java_lang_reflect_Method_getMethodModifiers }, + { "invokeNative", "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;", + Dalvik_java_lang_reflect_Method_invokeNative }, + { "getDeclaredAnnotations", "(Ljava/lang/Class;I)[Ljava/lang/annotation/Annotation;", + Dalvik_java_lang_reflect_Method_getDeclaredAnnotations }, + { "getParameterAnnotations", "(Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;", + Dalvik_java_lang_reflect_Method_getParameterAnnotations }, + { "getDefaultValue", "(Ljava/lang/Class;I)Ljava/lang/Object;", + Dalvik_java_lang_reflect_Method_getDefaultValue }, + { "getSignatureAnnotation", "(Ljava/lang/Class;I)[Ljava/lang/Object;", + Dalvik_java_lang_reflect_Method_getSignatureAnnotation }, + { NULL, NULL, NULL }, +}; |