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 */
Dalvik_java_lang_reflect_Method_getMethodModifiers(const u4 * args,JValue * pResult)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 */
Dalvik_java_lang_reflect_Method_invokeNative(const u4 * args,JValue * pResult)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 LOGD("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 */
Dalvik_java_lang_reflect_Method_getDeclaredAnnotations(const u4 * args,JValue * pResult)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 */
Dalvik_java_lang_reflect_Method_getAnnotation(const u4 * args,JValue * pResult)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 */
Dalvik_java_lang_reflect_Method_isAnnotationPresent(const u4 * args,JValue * pResult)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 */
Dalvik_java_lang_reflect_Method_getParameterAnnotations(const u4 * args,JValue * pResult)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 */
Dalvik_java_lang_reflect_Method_getDefaultValue(const u4 * args,JValue * pResult)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 */
Dalvik_java_lang_reflect_Method_getSignatureAnnotation(const u4 * args,JValue * pResult)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