| /* |
| * 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" |
| |
| |
| /* |
| * static 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) |
| { |
| ClassObject* declaringClass = (ClassObject*) args[0]; |
| int slot = args[1]; |
| 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", |
| declaringClass->descriptor); |
| assert(dvmCheckException(dvmThreadSelf())); |
| RETURN_VOID(); |
| } |
| |
| /* |
| * static 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) |
| { |
| ClassObject* declaringClass = (ClassObject*) args[0]; |
| int slot = args[1]; |
| Method* meth; |
| |
| meth = dvmSlotToMethod(declaringClass, slot); |
| assert(meth != NULL); |
| |
| ArrayObject* annos = dvmGetMethodAnnotations(meth); |
| dvmReleaseTrackedAlloc((Object*)annos, NULL); |
| RETURN_PTR(annos); |
| } |
| |
| /* |
| * static Annotation getAnnotation( |
| * Class declaringClass, int slot, Class annotationType); |
| */ |
| static void Dalvik_java_lang_reflect_Method_getAnnotation(const u4* args, |
| JValue* pResult) |
| { |
| ClassObject* clazz = (ClassObject*) args[0]; |
| int slot = args[1]; |
| ClassObject* annotationClazz = (ClassObject*) args[2]; |
| |
| Method* meth = dvmSlotToMethod(clazz, slot); |
| RETURN_PTR(dvmGetMethodAnnotation(clazz, meth, annotationClazz)); |
| } |
| |
| /* |
| * static boolean isAnnotationPresent( |
| * Class declaringClass, int slot, Class annotationType); |
| */ |
| static void Dalvik_java_lang_reflect_Method_isAnnotationPresent(const u4* args, |
| JValue* pResult) |
| { |
| ClassObject* clazz = (ClassObject*) args[0]; |
| int slot = args[1]; |
| ClassObject* annotationClazz = (ClassObject*) args[2]; |
| |
| Method* meth = dvmSlotToMethod(clazz, slot); |
| RETURN_BOOLEAN(dvmIsMethodAnnotationPresent(clazz, meth, annotationClazz)); |
| } |
| |
| /* |
| * static 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) |
| { |
| ClassObject* declaringClass = (ClassObject*) args[0]; |
| int slot = args[1]; |
| 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); |
| } |
| |
| /* |
| * static Object[] getSignatureAnnotation() |
| * |
| * Returns the signature annotation. |
| */ |
| static void Dalvik_java_lang_reflect_Method_getSignatureAnnotation( |
| const u4* args, JValue* pResult) |
| { |
| ClassObject* declaringClass = (ClassObject*) args[0]; |
| int slot = args[1]; |
| 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 }, |
| { "getAnnotation", "(Ljava/lang/Class;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;", |
| Dalvik_java_lang_reflect_Method_getAnnotation }, |
| { "isAnnotationPresent", "(Ljava/lang/Class;ILjava/lang/Class;)Z", |
| Dalvik_java_lang_reflect_Method_isAnnotationPresent }, |
| { "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 }, |
| }; |