Home | History | Annotate | Download | only in native
      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.Method
     19  */
     20 #include "Dalvik.h"
     21 #include "native/InternalNativePriv.h"
     22 
     23 
     24 /*
     25  * static int getMethodModifiers(Class decl_class, int slot)
     26  *
     27  * (Not sure why the access flags weren't stored in the class along with
     28  * everything else.  Not sure why this isn't static.)
     29  */
     30 static void Dalvik_java_lang_reflect_Method_getMethodModifiers(const u4* args,
     31     JValue* pResult)
     32 {
     33     ClassObject* declaringClass = (ClassObject*) args[0];
     34     int slot = args[1];
     35     Method* meth;
     36 
     37     meth = dvmSlotToMethod(declaringClass, slot);
     38     RETURN_INT(dvmFixMethodFlags(meth->accessFlags));
     39 }
     40 
     41 /*
     42  * private Object invokeNative(Object obj, Object[] args, Class declaringClass,
     43  *   Class[] parameterTypes, Class returnType, int slot, boolean noAccessCheck)
     44  *
     45  * Invoke a static or virtual method via reflection.
     46  */
     47 static void Dalvik_java_lang_reflect_Method_invokeNative(const u4* args,
     48     JValue* pResult)
     49 {
     50     // ignore thisPtr in args[0]
     51     Object* methObj = (Object*) args[1];        // null for static methods
     52     ArrayObject* argList = (ArrayObject*) args[2];
     53     ClassObject* declaringClass = (ClassObject*) args[3];
     54     ArrayObject* params = (ArrayObject*) args[4];
     55     ClassObject* returnType = (ClassObject*) args[5];
     56     int slot = args[6];
     57     bool noAccessCheck = (args[7] != 0);
     58     const Method* meth;
     59     Object* result;
     60 
     61     /*
     62      * "If the underlying method is static, the class that declared the
     63      * method is initialized if it has not already been initialized."
     64      */
     65     meth = dvmSlotToMethod(declaringClass, slot);
     66     assert(meth != NULL);
     67 
     68     if (dvmIsStaticMethod(meth)) {
     69         if (!dvmIsClassInitialized(declaringClass)) {
     70             if (!dvmInitClass(declaringClass))
     71                 goto init_failed;
     72         }
     73     } else {
     74         /* looks like interfaces need this too? */
     75         if (dvmIsInterfaceClass(declaringClass) &&
     76             !dvmIsClassInitialized(declaringClass))
     77         {
     78             if (!dvmInitClass(declaringClass))
     79                 goto init_failed;
     80         }
     81 
     82         /* make sure the object is an instance of the expected class */
     83         if (!dvmVerifyObjectInClass(methObj, declaringClass)) {
     84             assert(dvmCheckException(dvmThreadSelf()));
     85             RETURN_VOID();
     86         }
     87 
     88         /* do the virtual table lookup for the method */
     89         meth = dvmGetVirtualizedMethod(methObj->clazz, meth);
     90         if (meth == NULL) {
     91             assert(dvmCheckException(dvmThreadSelf()));
     92             RETURN_VOID();
     93         }
     94     }
     95 
     96     /*
     97      * If the method has a return value, "result" will be an object or
     98      * a boxed primitive.
     99      */
    100     result = dvmInvokeMethod(methObj, meth, argList, params, returnType,
    101                 noAccessCheck);
    102 
    103     RETURN_PTR(result);
    104 
    105 init_failed:
    106     /*
    107      * If initialization failed, an exception will be raised.
    108      */
    109     ALOGD("Method.invoke() on bad class %s failed",
    110         declaringClass->descriptor);
    111     assert(dvmCheckException(dvmThreadSelf()));
    112     RETURN_VOID();
    113 }
    114 
    115 /*
    116  * static Annotation[] getDeclaredAnnotations(Class declaringClass, int slot)
    117  *
    118  * Return the annotations declared for this method.
    119  */
    120 static void Dalvik_java_lang_reflect_Method_getDeclaredAnnotations(
    121     const u4* args, JValue* pResult)
    122 {
    123     ClassObject* declaringClass = (ClassObject*) args[0];
    124     int slot = args[1];
    125     Method* meth;
    126 
    127     meth = dvmSlotToMethod(declaringClass, slot);
    128     assert(meth != NULL);
    129 
    130     ArrayObject* annos = dvmGetMethodAnnotations(meth);
    131     dvmReleaseTrackedAlloc((Object*)annos, NULL);
    132     RETURN_PTR(annos);
    133 }
    134 
    135 /*
    136  * static Annotation getAnnotation(
    137  *         Class declaringClass, int slot, Class annotationType);
    138  */
    139 static void Dalvik_java_lang_reflect_Method_getAnnotation(const u4* args,
    140     JValue* pResult)
    141 {
    142     ClassObject* clazz = (ClassObject*) args[0];
    143     int slot = args[1];
    144     ClassObject* annotationClazz = (ClassObject*) args[2];
    145 
    146     Method* meth = dvmSlotToMethod(clazz, slot);
    147     RETURN_PTR(dvmGetMethodAnnotation(clazz, meth, annotationClazz));
    148 }
    149 
    150 /*
    151  * static boolean isAnnotationPresent(
    152  *         Class declaringClass, int slot, Class annotationType);
    153  */
    154 static void Dalvik_java_lang_reflect_Method_isAnnotationPresent(const u4* args,
    155     JValue* pResult)
    156 {
    157     ClassObject* clazz = (ClassObject*) args[0];
    158     int slot = args[1];
    159     ClassObject* annotationClazz = (ClassObject*) args[2];
    160 
    161     Method* meth = dvmSlotToMethod(clazz, slot);
    162     RETURN_BOOLEAN(dvmIsMethodAnnotationPresent(clazz, meth, annotationClazz));
    163 }
    164 
    165 /*
    166  * static Annotation[][] getParameterAnnotations(Class declaringClass, int slot)
    167  *
    168  * Return the annotations declared for this method's parameters.
    169  */
    170 static void Dalvik_java_lang_reflect_Method_getParameterAnnotations(
    171     const u4* args, JValue* pResult)
    172 {
    173     ClassObject* declaringClass = (ClassObject*) args[0];
    174     int slot = args[1];
    175     Method* meth;
    176 
    177     meth = dvmSlotToMethod(declaringClass, slot);
    178     assert(meth != NULL);
    179 
    180     ArrayObject* annos = dvmGetParameterAnnotations(meth);
    181     dvmReleaseTrackedAlloc((Object*)annos, NULL);
    182     RETURN_PTR(annos);
    183 }
    184 
    185 /*
    186  * private Object getDefaultValue(Class declaringClass, int slot)
    187  *
    188  * Return the default value for the annotation member represented by
    189  * this Method instance.  Returns NULL if none is defined.
    190  */
    191 static void Dalvik_java_lang_reflect_Method_getDefaultValue(const u4* args,
    192     JValue* pResult)
    193 {
    194     // ignore thisPtr in args[0]
    195     ClassObject* declaringClass = (ClassObject*) args[1];
    196     int slot = args[2];
    197     Method* meth;
    198 
    199     /* make sure this is an annotation class member */
    200     if (!dvmIsAnnotationClass(declaringClass))
    201         RETURN_PTR(NULL);
    202 
    203     meth = dvmSlotToMethod(declaringClass, slot);
    204     assert(meth != NULL);
    205 
    206     Object* def = dvmGetAnnotationDefaultValue(meth);
    207     dvmReleaseTrackedAlloc(def, NULL);
    208     RETURN_PTR(def);
    209 }
    210 
    211 /*
    212  * static Object[] getSignatureAnnotation()
    213  *
    214  * Returns the signature annotation.
    215  */
    216 static void Dalvik_java_lang_reflect_Method_getSignatureAnnotation(
    217     const u4* args, JValue* pResult)
    218 {
    219     ClassObject* declaringClass = (ClassObject*) args[0];
    220     int slot = args[1];
    221     Method* meth;
    222 
    223     meth = dvmSlotToMethod(declaringClass, slot);
    224     assert(meth != NULL);
    225 
    226     ArrayObject* arr = dvmGetMethodSignatureAnnotation(meth);
    227     dvmReleaseTrackedAlloc((Object*) arr, NULL);
    228     RETURN_PTR(arr);
    229 }
    230 
    231 const DalvikNativeMethod dvm_java_lang_reflect_Method[] = {
    232     { "getMethodModifiers", "(Ljava/lang/Class;I)I",
    233         Dalvik_java_lang_reflect_Method_getMethodModifiers },
    234     { "invokeNative",       "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;",
    235         Dalvik_java_lang_reflect_Method_invokeNative },
    236     { "getDeclaredAnnotations", "(Ljava/lang/Class;I)[Ljava/lang/annotation/Annotation;",
    237         Dalvik_java_lang_reflect_Method_getDeclaredAnnotations },
    238     { "getAnnotation", "(Ljava/lang/Class;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;",
    239         Dalvik_java_lang_reflect_Method_getAnnotation },
    240     { "isAnnotationPresent", "(Ljava/lang/Class;ILjava/lang/Class;)Z",
    241         Dalvik_java_lang_reflect_Method_isAnnotationPresent },
    242     { "getParameterAnnotations", "(Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;",
    243         Dalvik_java_lang_reflect_Method_getParameterAnnotations },
    244     { "getDefaultValue",    "(Ljava/lang/Class;I)Ljava/lang/Object;",
    245         Dalvik_java_lang_reflect_Method_getDefaultValue },
    246     { "getSignatureAnnotation",  "(Ljava/lang/Class;I)[Ljava/lang/Object;",
    247         Dalvik_java_lang_reflect_Method_getSignatureAnnotation },
    248     { NULL, NULL, NULL },
    249 };
    250