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.Class
19 */
20 #include "Dalvik.h"
21 #include "native/InternalNativePriv.h"
22
23
24 /*
25 * native public boolean desiredAssertionStatus()
26 *
27 * Determine the class-init-time assertion status of a class. This is
28 * called from <clinit> in javac-generated classes that use the Java
29 * programming language "assert" keyword.
30 */
Dalvik_java_lang_Class_desiredAssertionStatus(const u4 * args,JValue * pResult)31 static void Dalvik_java_lang_Class_desiredAssertionStatus(const u4* args,
32 JValue* pResult)
33 {
34 ClassObject* thisPtr = (ClassObject*) args[0];
35 char* className = dvmDescriptorToName(thisPtr->descriptor);
36 int i;
37 bool enable = false;
38
39 /*
40 * Run through the list of arguments specified on the command line. The
41 * last matching argument takes precedence.
42 */
43 for (i = 0; i < gDvm.assertionCtrlCount; i++) {
44 const AssertionControl* pCtrl = &gDvm.assertionCtrl[i];
45
46 if (pCtrl->isPackage) {
47 /*
48 * Given "dalvik/system/Debug" or "MyStuff", compute the
49 * length of the package portion of the class name string.
50 *
51 * Unlike most package operations, we allow matching on
52 * "sub-packages", so "dalvik..." will match "dalvik.Foo"
53 * and "dalvik.system.Foo".
54 *
55 * The pkgOrClass string looks like "dalvik/system/", i.e. it still
56 * has the terminating slash, so we can be sure we're comparing
57 * against full package component names.
58 */
59 const char* lastSlash;
60 int pkgLen;
61
62 lastSlash = strrchr(className, '/');
63 if (lastSlash == NULL) {
64 pkgLen = 0;
65 } else {
66 pkgLen = lastSlash - className +1;
67 }
68
69 if (pCtrl->pkgOrClassLen > pkgLen ||
70 memcmp(pCtrl->pkgOrClass, className, pCtrl->pkgOrClassLen) != 0)
71 {
72 LOGV("ASRT: pkg no match: '%s'(%d) vs '%s'\n",
73 className, pkgLen, pCtrl->pkgOrClass);
74 } else {
75 LOGV("ASRT: pkg match: '%s'(%d) vs '%s' --> %d\n",
76 className, pkgLen, pCtrl->pkgOrClass, pCtrl->enable);
77 enable = pCtrl->enable;
78 }
79 } else {
80 /*
81 * "pkgOrClass" holds a fully-qualified class name, converted from
82 * dot-form to slash-form. An empty string means all classes.
83 */
84 if (pCtrl->pkgOrClass == NULL) {
85 /* -esa/-dsa; see if class is a "system" class */
86 if (strncmp(className, "java/", 5) != 0) {
87 LOGV("ASRT: sys no match: '%s'\n", className);
88 } else {
89 LOGV("ASRT: sys match: '%s' --> %d\n",
90 className, pCtrl->enable);
91 enable = pCtrl->enable;
92 }
93 } else if (*pCtrl->pkgOrClass == '\0') {
94 LOGV("ASRT: class all: '%s' --> %d\n",
95 className, pCtrl->enable);
96 enable = pCtrl->enable;
97 } else {
98 if (strcmp(pCtrl->pkgOrClass, className) != 0) {
99 LOGV("ASRT: cls no match: '%s' vs '%s'\n",
100 className, pCtrl->pkgOrClass);
101 } else {
102 LOGV("ASRT: cls match: '%s' vs '%s' --> %d\n",
103 className, pCtrl->pkgOrClass, pCtrl->enable);
104 enable = pCtrl->enable;
105 }
106 }
107 }
108 }
109
110 free(className);
111 RETURN_INT(enable);
112 }
113
114 /*
115 * static public Class<?> classForName(String name, boolean initialize,
116 * ClassLoader loader)
117 *
118 * Return the Class object associated with the class or interface with
119 * the specified name.
120 *
121 * "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
122 */
Dalvik_java_lang_Class_classForName(const u4 * args,JValue * pResult)123 static void Dalvik_java_lang_Class_classForName(const u4* args, JValue* pResult)
124 {
125 StringObject* nameObj = (StringObject*) args[0];
126 bool initialize = (args[1] != 0);
127 Object* loader = (Object*) args[2];
128
129 RETURN_PTR(dvmFindClassByName(nameObj, loader, initialize));
130 }
131
132 /*
133 * static private ClassLoader getClassLoader(Class clazz)
134 *
135 * Return the class' defining class loader.
136 */
Dalvik_java_lang_Class_getClassLoader(const u4 * args,JValue * pResult)137 static void Dalvik_java_lang_Class_getClassLoader(const u4* args,
138 JValue* pResult)
139 {
140 ClassObject* clazz = (ClassObject*) args[0];
141
142 RETURN_PTR(clazz->classLoader);
143 }
144
145 /*
146 * public Class<?> getComponentType()
147 *
148 * If this is an array type, return the class of the elements; otherwise
149 * return NULL.
150 */
Dalvik_java_lang_Class_getComponentType(const u4 * args,JValue * pResult)151 static void Dalvik_java_lang_Class_getComponentType(const u4* args,
152 JValue* pResult)
153 {
154 ClassObject* thisPtr = (ClassObject*) args[0];
155
156 if (!dvmIsArrayClass(thisPtr))
157 RETURN_PTR(NULL);
158
159 /*
160 * We can't just return thisPtr->elementClass, because that gives
161 * us the base type (e.g. X[][][] returns X). If this is a multi-
162 * dimensional array, we have to do the lookup by name.
163 */
164 if (thisPtr->descriptor[1] == '[')
165 RETURN_PTR(dvmFindArrayClass(&thisPtr->descriptor[1],
166 thisPtr->classLoader));
167 else
168 RETURN_PTR(thisPtr->elementClass);
169 }
170
171 /*
172 * private static Class<?>[] getDeclaredClasses(Class<?> clazz,
173 * boolean publicOnly)
174 *
175 * Return an array with the classes that are declared by the specified class.
176 * If "publicOnly" is set, we strip out any classes that don't have "public"
177 * access.
178 */
Dalvik_java_lang_Class_getDeclaredClasses(const u4 * args,JValue * pResult)179 static void Dalvik_java_lang_Class_getDeclaredClasses(const u4* args,
180 JValue* pResult)
181 {
182 ClassObject* clazz = (ClassObject*) args[0];
183 bool publicOnly = (args[1] != 0);
184 ArrayObject* classes;
185
186 classes = dvmGetDeclaredClasses(clazz);
187 if (classes == NULL) {
188 if (!dvmCheckException(dvmThreadSelf())) {
189 /* empty list, so create a zero-length array */
190 classes = dvmAllocArrayByClass(gDvm.classJavaLangClassArray,
191 0, ALLOC_DEFAULT);
192 }
193 } else if (publicOnly) {
194 u4 count, newIdx, publicCount = 0;
195 ClassObject** pSource = (ClassObject**) classes->contents;
196 u4 length = classes->length;
197
198 /* count up public classes */
199 for (count = 0; count < length; count++) {
200 if (dvmIsPublicClass(pSource[count]))
201 publicCount++;
202 }
203
204 /* create a new array to hold them */
205 ArrayObject* newClasses;
206 newClasses = dvmAllocArrayByClass(gDvm.classJavaLangClassArray,
207 publicCount, ALLOC_DEFAULT);
208
209 /* copy them over */
210 for (count = newIdx = 0; count < length; count++) {
211 if (dvmIsPublicClass(pSource[count])) {
212 dvmSetObjectArrayElement(newClasses, newIdx,
213 (Object *)pSource[count]);
214 newIdx++;
215 }
216 }
217 assert(newIdx == publicCount);
218 dvmReleaseTrackedAlloc((Object*) classes, NULL);
219 classes = newClasses;
220 }
221
222 dvmReleaseTrackedAlloc((Object*) classes, NULL);
223 RETURN_PTR(classes);
224 }
225
226 /*
227 * static Constructor[] getDeclaredConstructors(Class clazz, boolean publicOnly)
228 * throws SecurityException
229 */
Dalvik_java_lang_Class_getDeclaredConstructors(const u4 * args,JValue * pResult)230 static void Dalvik_java_lang_Class_getDeclaredConstructors(const u4* args,
231 JValue* pResult)
232 {
233 ClassObject* clazz = (ClassObject*) args[0];
234 bool publicOnly = (args[1] != 0);
235 ArrayObject* constructors;
236
237 constructors = dvmGetDeclaredConstructors(clazz, publicOnly);
238 dvmReleaseTrackedAlloc((Object*) constructors, NULL);
239
240 RETURN_PTR(constructors);
241 }
242
243 /*
244 * static Field[] getDeclaredFields(Class klass, boolean publicOnly)
245 * throws SecurityException
246 */
Dalvik_java_lang_Class_getDeclaredFields(const u4 * args,JValue * pResult)247 static void Dalvik_java_lang_Class_getDeclaredFields(const u4* args,
248 JValue* pResult)
249 {
250 ClassObject* clazz = (ClassObject*) args[0];
251 bool publicOnly = (args[1] != 0);
252 ArrayObject* fields;
253
254 fields = dvmGetDeclaredFields(clazz, publicOnly);
255 dvmReleaseTrackedAlloc((Object*) fields, NULL);
256
257 RETURN_PTR(fields);
258 }
259
260 /*
261 * static Method[] getDeclaredMethods(Class clazz, boolean publicOnly)
262 * throws SecurityException
263 */
Dalvik_java_lang_Class_getDeclaredMethods(const u4 * args,JValue * pResult)264 static void Dalvik_java_lang_Class_getDeclaredMethods(const u4* args,
265 JValue* pResult)
266 {
267 ClassObject* clazz = (ClassObject*) args[0];
268 bool publicOnly = (args[1] != 0);
269 ArrayObject* methods;
270
271 methods = dvmGetDeclaredMethods(clazz, publicOnly);
272 dvmReleaseTrackedAlloc((Object*) methods, NULL);
273
274 RETURN_PTR(methods);
275 }
276
277 /*
278 * Class[] getInterfaces()
279 */
Dalvik_java_lang_Class_getInterfaces(const u4 * args,JValue * pResult)280 static void Dalvik_java_lang_Class_getInterfaces(const u4* args,
281 JValue* pResult)
282 {
283 ClassObject* clazz = (ClassObject*) args[0];
284 ArrayObject* interfaces;
285
286 interfaces = dvmGetInterfaces(clazz);
287 dvmReleaseTrackedAlloc((Object*) interfaces, NULL);
288
289 RETURN_PTR(interfaces);
290 }
291
292 /*
293 * private static int getModifiers(Class klass, boolean
294 * ignoreInnerClassesAttrib)
295 *
296 * Return the class' modifier flags. If "ignoreInnerClassesAttrib" is false,
297 * and this is an inner class, we return the access flags from the inner class
298 * attribute.
299 */
Dalvik_java_lang_Class_getModifiers(const u4 * args,JValue * pResult)300 static void Dalvik_java_lang_Class_getModifiers(const u4* args, JValue* pResult)
301 {
302 ClassObject* clazz = (ClassObject*) args[0];
303 bool ignoreInner = args[1];
304 u4 accessFlags;
305
306 accessFlags = clazz->accessFlags & JAVA_FLAGS_MASK;
307
308 if (!ignoreInner) {
309 /* see if we have an InnerClass annotation with flags in it */
310 StringObject* className = NULL;
311 int innerFlags;
312
313 if (dvmGetInnerClass(clazz, &className, &innerFlags))
314 accessFlags = innerFlags & JAVA_FLAGS_MASK;
315
316 dvmReleaseTrackedAlloc((Object*) className, NULL);
317 }
318
319 RETURN_INT(accessFlags);
320 }
321
322 /*
323 * private native String getNameNative()
324 *
325 * Return the class' name.
326 */
Dalvik_java_lang_Class_getNameNative(const u4 * args,JValue * pResult)327 static void Dalvik_java_lang_Class_getNameNative(const u4* args, JValue* pResult)
328 {
329 ClassObject* clazz = (ClassObject*) args[0];
330 const char* descriptor = clazz->descriptor;
331 StringObject* nameObj;
332
333 if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
334 /*
335 * The descriptor indicates that this is the class for
336 * a primitive type; special-case the return value.
337 */
338 const char* name;
339 switch (descriptor[0]) {
340 case 'Z': name = "boolean"; break;
341 case 'B': name = "byte"; break;
342 case 'C': name = "char"; break;
343 case 'S': name = "short"; break;
344 case 'I': name = "int"; break;
345 case 'J': name = "long"; break;
346 case 'F': name = "float"; break;
347 case 'D': name = "double"; break;
348 case 'V': name = "void"; break;
349 default: {
350 LOGE("Unknown primitive type '%c'\n", descriptor[0]);
351 assert(false);
352 RETURN_PTR(NULL);
353 }
354 }
355
356 nameObj = dvmCreateStringFromCstr(name);
357 } else {
358 /*
359 * Convert the UTF-8 name to a java.lang.String. The
360 * name must use '.' to separate package components.
361 *
362 * TODO: this could be more efficient. Consider a custom
363 * conversion function here that walks the string once and
364 * avoids the allocation for the common case (name less than,
365 * say, 128 bytes).
366 */
367 char* dotName = dvmDescriptorToDot(clazz->descriptor);
368 nameObj = dvmCreateStringFromCstr(dotName);
369 free(dotName);
370 }
371
372 dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
373
374 #if 0
375 /* doesn't work -- need "java.lang.String" not "java/lang/String" */
376 {
377 /*
378 * Find the string in the DEX file and use the copy in the intern
379 * table if it already exists (else put one there). Only works
380 * for strings in the DEX file, e.g. not arrays.
381 *
382 * We have to do the class lookup by name in the DEX file because
383 * we don't have a DexClassDef pointer in the ClassObject, and it's
384 * not worth adding one there just for this. Should be cheaper
385 * to do this than the string-creation above.
386 */
387 const DexFile* pDexFile = clazz->pDexFile;
388 const DexClassDef* pClassDef;
389 const DexClassId* pClassId;
390
391 pDexFile = clazz->pDexFile;
392 pClassDef = dvmDexFindClass(pDexFile, clazz->descriptor);
393 pClassId = dvmDexGetClassId(pDexFile, pClassDef->classIdx);
394 nameObj = dvmDexGetResolvedString(pDexFile, pClassId->nameIdx);
395 if (nameObj == NULL) {
396 nameObj = dvmResolveString(clazz, pClassId->nameIdx);
397 if (nameObj == NULL)
398 LOGW("WARNING: couldn't find string %u for '%s'\n",
399 pClassId->nameIdx, clazz->name);
400 }
401 }
402 #endif
403
404 RETURN_PTR(nameObj);
405 }
406
407 /*
408 * Return the superclass for instances of this class.
409 *
410 * If the class represents a java/lang/Object, an interface, a primitive
411 * type, or void (which *is* a primitive type??), return NULL.
412 *
413 * For an array, return the java/lang/Object ClassObject.
414 */
Dalvik_java_lang_Class_getSuperclass(const u4 * args,JValue * pResult)415 static void Dalvik_java_lang_Class_getSuperclass(const u4* args,
416 JValue* pResult)
417 {
418 ClassObject* clazz = (ClassObject*) args[0];
419
420 if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz))
421 RETURN_PTR(NULL);
422 else
423 RETURN_PTR(clazz->super);
424 }
425
426 /*
427 * public boolean isAssignableFrom(Class<?> cls)
428 *
429 * Determine if this class is either the same as, or is a superclass or
430 * superinterface of, the class specified in the "cls" parameter.
431 */
Dalvik_java_lang_Class_isAssignableFrom(const u4 * args,JValue * pResult)432 static void Dalvik_java_lang_Class_isAssignableFrom(const u4* args,
433 JValue* pResult)
434 {
435 ClassObject* thisPtr = (ClassObject*) args[0];
436 ClassObject* testClass = (ClassObject*) args[1];
437
438 if (testClass == NULL) {
439 dvmThrowException("Ljava/lang/NullPointerException;", NULL);
440 RETURN_INT(false);
441 }
442 RETURN_INT(dvmInstanceof(testClass, thisPtr));
443 }
444
445 /*
446 * public boolean isInstance(Object o)
447 *
448 * Dynamic equivalent of Java programming language "instanceof".
449 */
Dalvik_java_lang_Class_isInstance(const u4 * args,JValue * pResult)450 static void Dalvik_java_lang_Class_isInstance(const u4* args,
451 JValue* pResult)
452 {
453 ClassObject* thisPtr = (ClassObject*) args[0];
454 Object* testObj = (Object*) args[1];
455
456 if (testObj == NULL)
457 RETURN_INT(false);
458 RETURN_INT(dvmInstanceof(testObj->clazz, thisPtr));
459 }
460
461 /*
462 * public boolean isInterface()
463 */
Dalvik_java_lang_Class_isInterface(const u4 * args,JValue * pResult)464 static void Dalvik_java_lang_Class_isInterface(const u4* args,
465 JValue* pResult)
466 {
467 ClassObject* thisPtr = (ClassObject*) args[0];
468
469 RETURN_INT(dvmIsInterfaceClass(thisPtr));
470 }
471
472 /*
473 * public boolean isPrimitive()
474 */
Dalvik_java_lang_Class_isPrimitive(const u4 * args,JValue * pResult)475 static void Dalvik_java_lang_Class_isPrimitive(const u4* args,
476 JValue* pResult)
477 {
478 ClassObject* thisPtr = (ClassObject*) args[0];
479
480 RETURN_INT(dvmIsPrimitiveClass(thisPtr));
481 }
482
483 /*
484 * public T newInstance() throws InstantiationException, IllegalAccessException
485 *
486 * Create a new instance of this class.
487 */
Dalvik_java_lang_Class_newInstance(const u4 * args,JValue * pResult)488 static void Dalvik_java_lang_Class_newInstance(const u4* args, JValue* pResult)
489 {
490 Thread* self = dvmThreadSelf();
491 ClassObject* clazz = (ClassObject*) args[0];
492 Method* init;
493 Object* newObj;
494
495 /* can't instantiate these */
496 if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz)
497 || dvmIsArrayClass(clazz) || dvmIsAbstractClass(clazz))
498 {
499 LOGD("newInstance failed: p%d i%d [%d a%d\n",
500 dvmIsPrimitiveClass(clazz), dvmIsInterfaceClass(clazz),
501 dvmIsArrayClass(clazz), dvmIsAbstractClass(clazz));
502 dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;",
503 clazz->descriptor);
504 RETURN_VOID();
505 }
506
507 /* initialize the class if it hasn't been already */
508 if (!dvmIsClassInitialized(clazz)) {
509 if (!dvmInitClass(clazz)) {
510 LOGW("Class init failed in newInstance call (%s)\n",
511 clazz->descriptor);
512 assert(dvmCheckException(self));
513 RETURN_VOID();
514 }
515 }
516
517 /* find the "nullary" constructor */
518 init = dvmFindDirectMethodByDescriptor(clazz, "<init>", "()V");
519 if (init == NULL) {
520 /* common cause: secret "this" arg on non-static inner class ctor */
521 LOGD("newInstance failed: no <init>()\n");
522 dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;",
523 clazz->descriptor);
524 RETURN_VOID();
525 }
526
527 /*
528 * Verify access from the call site.
529 *
530 * First, make sure the method invoking Class.newInstance() has permission
531 * to access the class.
532 *
533 * Second, make sure it has permission to invoke the constructor. The
534 * constructor must be public or, if the caller is in the same package,
535 * have package scope.
536 */
537 ClassObject* callerClass = dvmGetCaller2Class(self->curFrame);
538
539 if (!dvmCheckClassAccess(callerClass, clazz)) {
540 LOGD("newInstance failed: %s not accessible to %s\n",
541 clazz->descriptor, callerClass->descriptor);
542 dvmThrowException("Ljava/lang/IllegalAccessException;",
543 "access to class not allowed");
544 RETURN_VOID();
545 }
546 if (!dvmCheckMethodAccess(callerClass, init)) {
547 LOGD("newInstance failed: %s.<init>() not accessible to %s\n",
548 clazz->descriptor, callerClass->descriptor);
549 dvmThrowException("Ljava/lang/IllegalAccessException;",
550 "access to constructor not allowed");
551 RETURN_VOID();
552 }
553
554 newObj = dvmAllocObject(clazz, ALLOC_DEFAULT);
555 JValue unused;
556
557 /* invoke constructor; unlike reflection calls, we don't wrap exceptions */
558 dvmCallMethod(self, init, newObj, &unused);
559 dvmReleaseTrackedAlloc(newObj, NULL);
560
561 RETURN_PTR(newObj);
562 }
563
564 /*
565 * private Object[] getSignatureAnnotation()
566 *
567 * Returns the signature annotation array.
568 */
Dalvik_java_lang_Class_getSignatureAnnotation(const u4 * args,JValue * pResult)569 static void Dalvik_java_lang_Class_getSignatureAnnotation(const u4* args,
570 JValue* pResult)
571 {
572 ClassObject* clazz = (ClassObject*) args[0];
573 ArrayObject* arr = dvmGetClassSignatureAnnotation(clazz);
574
575 dvmReleaseTrackedAlloc((Object*) arr, NULL);
576 RETURN_PTR(arr);
577 }
578
579 /*
580 * public Class getDeclaringClass()
581 *
582 * Get the class that encloses this class (if any).
583 */
Dalvik_java_lang_Class_getDeclaringClass(const u4 * args,JValue * pResult)584 static void Dalvik_java_lang_Class_getDeclaringClass(const u4* args,
585 JValue* pResult)
586 {
587 ClassObject* clazz = (ClassObject*) args[0];
588
589 ClassObject* enclosing = dvmGetDeclaringClass(clazz);
590 dvmReleaseTrackedAlloc((Object*) enclosing, NULL);
591 RETURN_PTR(enclosing);
592 }
593
594 /*
595 * public Class getEnclosingClass()
596 *
597 * Get the class that encloses this class (if any).
598 */
Dalvik_java_lang_Class_getEnclosingClass(const u4 * args,JValue * pResult)599 static void Dalvik_java_lang_Class_getEnclosingClass(const u4* args,
600 JValue* pResult)
601 {
602 ClassObject* clazz = (ClassObject*) args[0];
603
604 ClassObject* enclosing = dvmGetEnclosingClass(clazz);
605 dvmReleaseTrackedAlloc((Object*) enclosing, NULL);
606 RETURN_PTR(enclosing);
607 }
608
609 /*
610 * public Constructor getEnclosingConstructor()
611 *
612 * Get the constructor that encloses this class (if any).
613 */
Dalvik_java_lang_Class_getEnclosingConstructor(const u4 * args,JValue * pResult)614 static void Dalvik_java_lang_Class_getEnclosingConstructor(const u4* args,
615 JValue* pResult)
616 {
617 ClassObject* clazz = (ClassObject*) args[0];
618
619 Object* enclosing = dvmGetEnclosingMethod(clazz);
620 if (enclosing != NULL) {
621 dvmReleaseTrackedAlloc(enclosing, NULL);
622 if (enclosing->clazz == gDvm.classJavaLangReflectConstructor) {
623 RETURN_PTR(enclosing);
624 }
625 assert(enclosing->clazz == gDvm.classJavaLangReflectMethod);
626 }
627 RETURN_PTR(NULL);
628 }
629
630 /*
631 * public Method getEnclosingMethod()
632 *
633 * Get the method that encloses this class (if any).
634 */
Dalvik_java_lang_Class_getEnclosingMethod(const u4 * args,JValue * pResult)635 static void Dalvik_java_lang_Class_getEnclosingMethod(const u4* args,
636 JValue* pResult)
637 {
638 ClassObject* clazz = (ClassObject*) args[0];
639
640 Object* enclosing = dvmGetEnclosingMethod(clazz);
641 if (enclosing != NULL) {
642 dvmReleaseTrackedAlloc(enclosing, NULL);
643 if (enclosing->clazz == gDvm.classJavaLangReflectMethod) {
644 RETURN_PTR(enclosing);
645 }
646 assert(enclosing->clazz == gDvm.classJavaLangReflectConstructor);
647 }
648 RETURN_PTR(NULL);
649 }
650
651 #if 0
652 static void Dalvik_java_lang_Class_getGenericInterfaces(const u4* args,
653 JValue* pResult)
654 {
655 dvmThrowException("Ljava/lang/UnsupportedOperationException;",
656 "native method not implemented");
657
658 RETURN_PTR(NULL);
659 }
660
661 static void Dalvik_java_lang_Class_getGenericSuperclass(const u4* args,
662 JValue* pResult)
663 {
664 dvmThrowException("Ljava/lang/UnsupportedOperationException;",
665 "native method not implemented");
666
667 RETURN_PTR(NULL);
668 }
669
670 static void Dalvik_java_lang_Class_getTypeParameters(const u4* args,
671 JValue* pResult)
672 {
673 dvmThrowException("Ljava/lang/UnsupportedOperationException;",
674 "native method not implemented");
675
676 RETURN_PTR(NULL);
677 }
678 #endif
679
680 /*
681 * public boolean isAnonymousClass()
682 *
683 * Returns true if this is an "anonymous" class.
684 */
Dalvik_java_lang_Class_isAnonymousClass(const u4 * args,JValue * pResult)685 static void Dalvik_java_lang_Class_isAnonymousClass(const u4* args,
686 JValue* pResult)
687 {
688 ClassObject* clazz = (ClassObject*) args[0];
689 StringObject* className = NULL;
690 int accessFlags;
691
692 /*
693 * If this has an InnerClass annotation, pull it out. Lack of the
694 * annotation, or an annotation with a NULL class name, indicates
695 * that this is an anonymous inner class.
696 */
697 if (!dvmGetInnerClass(clazz, &className, &accessFlags))
698 RETURN_BOOLEAN(false);
699
700 dvmReleaseTrackedAlloc((Object*) className, NULL);
701 RETURN_BOOLEAN(className == NULL);
702 }
703
704 /*
705 * private Annotation[] getDeclaredAnnotations()
706 *
707 * Return the annotations declared on this class.
708 */
Dalvik_java_lang_Class_getDeclaredAnnotations(const u4 * args,JValue * pResult)709 static void Dalvik_java_lang_Class_getDeclaredAnnotations(const u4* args,
710 JValue* pResult)
711 {
712 ClassObject* clazz = (ClassObject*) args[0];
713
714 ArrayObject* annos = dvmGetClassAnnotations(clazz);
715 dvmReleaseTrackedAlloc((Object*) annos, NULL);
716 RETURN_PTR(annos);
717 }
718
719 /*
720 * public String getInnerClassName()
721 *
722 * Returns the simple name of a member class or local class, or null otherwise.
723 */
Dalvik_java_lang_Class_getInnerClassName(const u4 * args,JValue * pResult)724 static void Dalvik_java_lang_Class_getInnerClassName(const u4* args,
725 JValue* pResult)
726 {
727 ClassObject* clazz = (ClassObject*) args[0];
728 StringObject* nameObj;
729 int flags;
730
731 if (dvmGetInnerClass(clazz, &nameObj, &flags)) {
732 dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
733 RETURN_PTR(nameObj);
734 } else {
735 RETURN_PTR(NULL);
736 }
737 }
738
739 /*
740 * static native void setAccessibleNoCheck(AccessibleObject ao, boolean flag);
741 */
Dalvik_java_lang_Class_setAccessibleNoCheck(const u4 * args,JValue * pResult)742 static void Dalvik_java_lang_Class_setAccessibleNoCheck(const u4* args,
743 JValue* pResult)
744 {
745 Object* target = (Object*) args[0];
746 u4 flag = (u4) args[1];
747
748 dvmSetFieldBoolean(target, gDvm.offJavaLangReflectAccessibleObject_flag,
749 flag);
750 }
751
752 const DalvikNativeMethod dvm_java_lang_Class[] = {
753 { "desiredAssertionStatus", "()Z",
754 Dalvik_java_lang_Class_desiredAssertionStatus },
755 { "classForName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;",
756 Dalvik_java_lang_Class_classForName },
757 { "getClassLoader", "(Ljava/lang/Class;)Ljava/lang/ClassLoader;",
758 Dalvik_java_lang_Class_getClassLoader },
759 { "getComponentType", "()Ljava/lang/Class;",
760 Dalvik_java_lang_Class_getComponentType },
761 { "getSignatureAnnotation", "()[Ljava/lang/Object;",
762 Dalvik_java_lang_Class_getSignatureAnnotation },
763 { "getDeclaredClasses", "(Ljava/lang/Class;Z)[Ljava/lang/Class;",
764 Dalvik_java_lang_Class_getDeclaredClasses },
765 { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;",
766 Dalvik_java_lang_Class_getDeclaredConstructors },
767 { "getDeclaredFields", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;",
768 Dalvik_java_lang_Class_getDeclaredFields },
769 { "getDeclaredMethods", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;",
770 Dalvik_java_lang_Class_getDeclaredMethods },
771 { "getInterfaces", "()[Ljava/lang/Class;",
772 Dalvik_java_lang_Class_getInterfaces },
773 { "getModifiers", "(Ljava/lang/Class;Z)I",
774 Dalvik_java_lang_Class_getModifiers },
775 { "getNameNative", "()Ljava/lang/String;",
776 Dalvik_java_lang_Class_getNameNative },
777 { "getSuperclass", "()Ljava/lang/Class;",
778 Dalvik_java_lang_Class_getSuperclass },
779 { "isAssignableFrom", "(Ljava/lang/Class;)Z",
780 Dalvik_java_lang_Class_isAssignableFrom },
781 { "isInstance", "(Ljava/lang/Object;)Z",
782 Dalvik_java_lang_Class_isInstance },
783 { "isInterface", "()Z",
784 Dalvik_java_lang_Class_isInterface },
785 { "isPrimitive", "()Z",
786 Dalvik_java_lang_Class_isPrimitive },
787 { "newInstanceImpl", "()Ljava/lang/Object;",
788 Dalvik_java_lang_Class_newInstance },
789 { "getDeclaringClass", "()Ljava/lang/Class;",
790 Dalvik_java_lang_Class_getDeclaringClass },
791 { "getEnclosingClass", "()Ljava/lang/Class;",
792 Dalvik_java_lang_Class_getEnclosingClass },
793 { "getEnclosingConstructor", "()Ljava/lang/reflect/Constructor;",
794 Dalvik_java_lang_Class_getEnclosingConstructor },
795 { "getEnclosingMethod", "()Ljava/lang/reflect/Method;",
796 Dalvik_java_lang_Class_getEnclosingMethod },
797 #if 0
798 { "getGenericInterfaces", "()[Ljava/lang/reflect/Type;",
799 Dalvik_java_lang_Class_getGenericInterfaces },
800 { "getGenericSuperclass", "()Ljava/lang/reflect/Type;",
801 Dalvik_java_lang_Class_getGenericSuperclass },
802 { "getTypeParameters", "()Ljava/lang/reflect/TypeVariable;",
803 Dalvik_java_lang_Class_getTypeParameters },
804 #endif
805 { "isAnonymousClass", "()Z",
806 Dalvik_java_lang_Class_isAnonymousClass },
807 { "getDeclaredAnnotations", "()[Ljava/lang/annotation/Annotation;",
808 Dalvik_java_lang_Class_getDeclaredAnnotations },
809 { "getInnerClassName", "()Ljava/lang/String;",
810 Dalvik_java_lang_Class_getInnerClassName },
811 { "setAccessibleNoCheck", "(Ljava/lang/reflect/AccessibleObject;Z)V",
812 Dalvik_java_lang_Class_setAccessibleNoCheck },
813 { NULL, NULL, NULL },
814 };
815