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