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 int i, newIdx, publicCount = 0;
195 ClassObject** pSource = (ClassObject**) classes->contents;
196
197 /* count up public classes */
198 for (i = 0; i < (int)classes->length; i++) {
199 if (dvmIsPublicClass(pSource[i]))
200 publicCount++;
201 }
202
203 /* create a new array to hold them */
204 ArrayObject* newClasses;
205 newClasses = dvmAllocArrayByClass(gDvm.classJavaLangClassArray,
206 publicCount, ALLOC_DEFAULT);
207
208 /* copy them over */
209 ClassObject** pDest = (ClassObject**) newClasses->contents;
210 for (i = newIdx = 0; i < (int)classes->length; i++) {
211 if (dvmIsPublicClass(pSource[i]))
212 pDest[newIdx++] = pSource[i];
213 }
214
215 assert(newIdx == publicCount);
216 dvmReleaseTrackedAlloc((Object*) classes, NULL);
217 classes = newClasses;
218 }
219
220 dvmReleaseTrackedAlloc((Object*) classes, NULL);
221 RETURN_PTR(classes);
222 }
223
224 /*
225 * static Constructor[] getDeclaredConstructors(Class clazz, boolean publicOnly)
226 * throws SecurityException
227 */
Dalvik_java_lang_Class_getDeclaredConstructors(const u4 * args,JValue * pResult)228 static void Dalvik_java_lang_Class_getDeclaredConstructors(const u4* args,
229 JValue* pResult)
230 {
231 ClassObject* clazz = (ClassObject*) args[0];
232 bool publicOnly = (args[1] != 0);
233 ArrayObject* constructors;
234
235 constructors = dvmGetDeclaredConstructors(clazz, publicOnly);
236 dvmReleaseTrackedAlloc((Object*) constructors, NULL);
237
238 RETURN_PTR(constructors);
239 }
240
241 /*
242 * static Field[] getDeclaredFields(Class klass, boolean publicOnly)
243 * throws SecurityException
244 */
Dalvik_java_lang_Class_getDeclaredFields(const u4 * args,JValue * pResult)245 static void Dalvik_java_lang_Class_getDeclaredFields(const u4* args,
246 JValue* pResult)
247 {
248 ClassObject* clazz = (ClassObject*) args[0];
249 bool publicOnly = (args[1] != 0);
250 ArrayObject* fields;
251
252 fields = dvmGetDeclaredFields(clazz, publicOnly);
253 dvmReleaseTrackedAlloc((Object*) fields, NULL);
254
255 RETURN_PTR(fields);
256 }
257
258 /*
259 * static Method[] getDeclaredMethods(Class clazz, boolean publicOnly)
260 * throws SecurityException
261 */
Dalvik_java_lang_Class_getDeclaredMethods(const u4 * args,JValue * pResult)262 static void Dalvik_java_lang_Class_getDeclaredMethods(const u4* args,
263 JValue* pResult)
264 {
265 ClassObject* clazz = (ClassObject*) args[0];
266 bool publicOnly = (args[1] != 0);
267 ArrayObject* methods;
268
269 methods = dvmGetDeclaredMethods(clazz, publicOnly);
270 dvmReleaseTrackedAlloc((Object*) methods, NULL);
271
272 RETURN_PTR(methods);
273 }
274
275 /*
276 * Class[] getInterfaces()
277 */
Dalvik_java_lang_Class_getInterfaces(const u4 * args,JValue * pResult)278 static void Dalvik_java_lang_Class_getInterfaces(const u4* args,
279 JValue* pResult)
280 {
281 ClassObject* clazz = (ClassObject*) args[0];
282 ArrayObject* interfaces;
283
284 interfaces = dvmGetInterfaces(clazz);
285 dvmReleaseTrackedAlloc((Object*) interfaces, NULL);
286
287 RETURN_PTR(interfaces);
288 }
289
290 /*
291 * private static int getModifiers(Class klass, boolean
292 * ignoreInnerClassesAttrib)
293 *
294 * Return the class' modifier flags. If "ignoreInnerClassesAttrib" is false,
295 * and this is an inner class, we return the access flags from the inner class
296 * attribute.
297 */
Dalvik_java_lang_Class_getModifiers(const u4 * args,JValue * pResult)298 static void Dalvik_java_lang_Class_getModifiers(const u4* args, JValue* pResult)
299 {
300 ClassObject* clazz = (ClassObject*) args[0];
301 bool ignoreInner = args[1];
302 u4 accessFlags;
303
304 accessFlags = clazz->accessFlags & JAVA_FLAGS_MASK;
305
306 if (!ignoreInner) {
307 /* see if we have an InnerClass annotation with flags in it */
308 StringObject* className = NULL;
309 int innerFlags;
310
311 if (dvmGetInnerClass(clazz, &className, &innerFlags))
312 accessFlags = innerFlags & JAVA_FLAGS_MASK;
313
314 dvmReleaseTrackedAlloc((Object*) className, NULL);
315 }
316
317 RETURN_INT(accessFlags);
318 }
319
320 /*
321 * public String getName()
322 *
323 * Return the class' name.
324 */
Dalvik_java_lang_Class_getName(const u4 * args,JValue * pResult)325 static void Dalvik_java_lang_Class_getName(const u4* args, JValue* pResult)
326 {
327 ClassObject* clazz = (ClassObject*) args[0];
328 const char* descriptor = clazz->descriptor;
329 StringObject* nameObj;
330
331 if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
332 /*
333 * The descriptor indicates that this is the class for
334 * a primitive type; special-case the return value.
335 */
336 const char* name;
337 switch (descriptor[0]) {
338 case 'Z': name = "boolean"; break;
339 case 'B': name = "byte"; break;
340 case 'C': name = "char"; break;
341 case 'S': name = "short"; break;
342 case 'I': name = "int"; break;
343 case 'J': name = "long"; break;
344 case 'F': name = "float"; break;
345 case 'D': name = "double"; break;
346 case 'V': name = "void"; break;
347 default: {
348 LOGE("Unknown primitive type '%c'\n", descriptor[0]);
349 assert(false);
350 RETURN_PTR(NULL);
351 }
352 }
353
354 nameObj = dvmCreateStringFromCstr(name, ALLOC_DEFAULT);
355 } else {
356 /*
357 * Convert the UTF-8 name to a java.lang.String. The
358 * name must use '.' to separate package components.
359 *
360 * TODO: this could be more efficient. Consider a custom
361 * conversion function here that walks the string once and
362 * avoids the allocation for the common case (name less than,
363 * say, 128 bytes).
364 */
365 char* dotName = dvmDescriptorToDot(clazz->descriptor);
366 nameObj = dvmCreateStringFromCstr(dotName, ALLOC_DEFAULT);
367 free(dotName);
368 }
369
370 dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
371
372 #if 0
373 /* doesn't work -- need "java.lang.String" not "java/lang/String" */
374 {
375 /*
376 * Find the string in the DEX file and use the copy in the intern
377 * table if it already exists (else put one there). Only works
378 * for strings in the DEX file, e.g. not arrays.
379 *
380 * We have to do the class lookup by name in the DEX file because
381 * we don't have a DexClassDef pointer in the ClassObject, and it's
382 * not worth adding one there just for this. Should be cheaper
383 * to do this than the string-creation above.
384 */
385 const DexFile* pDexFile = clazz->pDexFile;
386 const DexClassDef* pClassDef;
387 const DexClassId* pClassId;
388
389 pDexFile = clazz->pDexFile;
390 pClassDef = dvmDexFindClass(pDexFile, clazz->descriptor);
391 pClassId = dvmDexGetClassId(pDexFile, pClassDef->classIdx);
392 nameObj = dvmDexGetResolvedString(pDexFile, pClassId->nameIdx);
393 if (nameObj == NULL) {
394 nameObj = dvmResolveString(clazz, pClassId->nameIdx);
395 if (nameObj == NULL)
396 LOGW("WARNING: couldn't find string %u for '%s'\n",
397 pClassId->nameIdx, clazz->name);
398 }
399 }
400 #endif
401
402 RETURN_PTR(nameObj);
403 }
404
405 /*
406 * Return the superclass for instances of this class.
407 *
408 * If the class represents a java/lang/Object, an interface, a primitive
409 * type, or void (which *is* a primitive type??), return NULL.
410 *
411 * For an array, return the java/lang/Object ClassObject.
412 */
Dalvik_java_lang_Class_getSuperclass(const u4 * args,JValue * pResult)413 static void Dalvik_java_lang_Class_getSuperclass(const u4* args,
414 JValue* pResult)
415 {
416 ClassObject* clazz = (ClassObject*) args[0];
417
418 if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz))
419 RETURN_PTR(NULL);
420 else
421 RETURN_PTR(clazz->super);
422 }
423
424 /*
425 * public boolean isAssignableFrom(Class<?> cls)
426 *
427 * Determine if this class is either the same as, or is a superclass or
428 * superinterface of, the class specified in the "cls" parameter.
429 */
Dalvik_java_lang_Class_isAssignableFrom(const u4 * args,JValue * pResult)430 static void Dalvik_java_lang_Class_isAssignableFrom(const u4* args,
431 JValue* pResult)
432 {
433 ClassObject* thisPtr = (ClassObject*) args[0];
434 ClassObject* testClass = (ClassObject*) args[1];
435
436 if (testClass == NULL) {
437 dvmThrowException("Ljava/lang/NullPointerException;", NULL);
438 RETURN_INT(false);
439 }
440 RETURN_INT(dvmInstanceof(testClass, thisPtr));
441 }
442
443 /*
444 * public boolean isInstance(Object o)
445 *
446 * Dynamic equivalent of Java programming language "instanceof".
447 */
Dalvik_java_lang_Class_isInstance(const u4 * args,JValue * pResult)448 static void Dalvik_java_lang_Class_isInstance(const u4* args,
449 JValue* pResult)
450 {
451 ClassObject* thisPtr = (ClassObject*) args[0];
452 Object* testObj = (Object*) args[1];
453
454 if (testObj == NULL)
455 RETURN_INT(false);
456 RETURN_INT(dvmInstanceof(testObj->clazz, thisPtr));
457 }
458
459 /*
460 * public boolean isInterface()
461 */
Dalvik_java_lang_Class_isInterface(const u4 * args,JValue * pResult)462 static void Dalvik_java_lang_Class_isInterface(const u4* args,
463 JValue* pResult)
464 {
465 ClassObject* thisPtr = (ClassObject*) args[0];
466
467 RETURN_INT(dvmIsInterfaceClass(thisPtr));
468 }
469
470 /*
471 * public boolean isPrimitive()
472 */
Dalvik_java_lang_Class_isPrimitive(const u4 * args,JValue * pResult)473 static void Dalvik_java_lang_Class_isPrimitive(const u4* args,
474 JValue* pResult)
475 {
476 ClassObject* thisPtr = (ClassObject*) args[0];
477
478 RETURN_INT(dvmIsPrimitiveClass(thisPtr));
479 }
480
481 /*
482 * public T newInstance() throws InstantiationException, IllegalAccessException
483 *
484 * Create a new instance of this class.
485 */
Dalvik_java_lang_Class_newInstance(const u4 * args,JValue * pResult)486 static void Dalvik_java_lang_Class_newInstance(const u4* args, JValue* pResult)
487 {
488 Thread* self = dvmThreadSelf();
489 ClassObject* clazz = (ClassObject*) args[0];
490 Method* init;
491 Object* newObj;
492
493 /* can't instantiate these */
494 if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz)
495 || dvmIsArrayClass(clazz) || dvmIsAbstractClass(clazz))
496 {
497 LOGD("newInstance failed: p%d i%d [%d a%d\n",
498 dvmIsPrimitiveClass(clazz), dvmIsInterfaceClass(clazz),
499 dvmIsArrayClass(clazz), dvmIsAbstractClass(clazz));
500 dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;",
501 clazz->descriptor);
502 RETURN_VOID();
503 }
504
505 /* initialize the class if it hasn't been already */
506 if (!dvmIsClassInitialized(clazz)) {
507 if (!dvmInitClass(clazz)) {
508 LOGW("Class init failed in newInstance call (%s)\n",
509 clazz->descriptor);
510 assert(dvmCheckException(self));
511 RETURN_VOID();
512 }
513 }
514
515 /* find the "nullary" constructor */
516 init = dvmFindDirectMethodByDescriptor(clazz, "<init>", "()V");
517 if (init == NULL) {
518 /* common cause: secret "this" arg on non-static inner class ctor */
519 LOGD("newInstance failed: no <init>()\n");
520 dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;",
521 clazz->descriptor);
522 RETURN_VOID();
523 }
524
525 /*
526 * Verify access from the call site.
527 *
528 * First, make sure the method invoking Class.newInstance() has permission
529 * to access the class.
530 *
531 * Second, make sure it has permission to invoke the constructor. The
532 * constructor must be public or, if the caller is in the same package,
533 * have package scope.
534 */
535 ClassObject* callerClass = dvmGetCaller2Class(self->curFrame);
536
537 if (!dvmCheckClassAccess(callerClass, clazz)) {
538 LOGD("newInstance failed: %s not accessible to %s\n",
539 clazz->descriptor, callerClass->descriptor);
540 dvmThrowException("Ljava/lang/IllegalAccessException;",
541 "access to class not allowed");
542 RETURN_VOID();
543 }
544 if (!dvmCheckMethodAccess(callerClass, init)) {
545 LOGD("newInstance failed: %s.<init>() not accessible to %s\n",
546 clazz->descriptor, callerClass->descriptor);
547 dvmThrowException("Ljava/lang/IllegalAccessException;",
548 "access to constructor not allowed");
549 RETURN_VOID();
550 }
551
552 newObj = dvmAllocObject(clazz, ALLOC_DEFAULT);
553 JValue unused;
554
555 /* invoke constructor; unlike reflection calls, we don't wrap exceptions */
556 dvmCallMethod(self, init, newObj, &unused);
557 dvmReleaseTrackedAlloc(newObj, NULL);
558
559 RETURN_PTR(newObj);
560 }
561
562 /*
563 * private Object[] getSignatureAnnotation()
564 *
565 * Returns the signature annotation array.
566 */
Dalvik_java_lang_Class_getSignatureAnnotation(const u4 * args,JValue * pResult)567 static void Dalvik_java_lang_Class_getSignatureAnnotation(const u4* args,
568 JValue* pResult)
569 {
570 ClassObject* clazz = (ClassObject*) args[0];
571 ArrayObject* arr = dvmGetClassSignatureAnnotation(clazz);
572
573 dvmReleaseTrackedAlloc((Object*) arr, NULL);
574 RETURN_PTR(arr);
575 }
576
577 /*
578 * public Class getDeclaringClass()
579 *
580 * Get the class that encloses this class (if any).
581 */
Dalvik_java_lang_Class_getDeclaringClass(const u4 * args,JValue * pResult)582 static void Dalvik_java_lang_Class_getDeclaringClass(const u4* args,
583 JValue* pResult)
584 {
585 ClassObject* clazz = (ClassObject*) args[0];
586
587 ClassObject* enclosing = dvmGetDeclaringClass(clazz);
588 dvmReleaseTrackedAlloc((Object*) enclosing, NULL);
589 RETURN_PTR(enclosing);
590 }
591
592 /*
593 * public Class getEnclosingClass()
594 *
595 * Get the class that encloses this class (if any).
596 */
Dalvik_java_lang_Class_getEnclosingClass(const u4 * args,JValue * pResult)597 static void Dalvik_java_lang_Class_getEnclosingClass(const u4* args,
598 JValue* pResult)
599 {
600 ClassObject* clazz = (ClassObject*) args[0];
601
602 ClassObject* enclosing = dvmGetEnclosingClass(clazz);
603 dvmReleaseTrackedAlloc((Object*) enclosing, NULL);
604 RETURN_PTR(enclosing);
605 }
606
607 /*
608 * public Constructor getEnclosingConstructor()
609 *
610 * Get the constructor that encloses this class (if any).
611 */
Dalvik_java_lang_Class_getEnclosingConstructor(const u4 * args,JValue * pResult)612 static void Dalvik_java_lang_Class_getEnclosingConstructor(const u4* args,
613 JValue* pResult)
614 {
615 ClassObject* clazz = (ClassObject*) args[0];
616
617 Object* enclosing = dvmGetEnclosingMethod(clazz);
618 if (enclosing != NULL) {
619 dvmReleaseTrackedAlloc(enclosing, NULL);
620 if (enclosing->clazz == gDvm.classJavaLangReflectConstructor) {
621 RETURN_PTR(enclosing);
622 }
623 assert(enclosing->clazz == gDvm.classJavaLangReflectMethod);
624 }
625 RETURN_PTR(NULL);
626 }
627
628 /*
629 * public Method getEnclosingMethod()
630 *
631 * Get the method that encloses this class (if any).
632 */
Dalvik_java_lang_Class_getEnclosingMethod(const u4 * args,JValue * pResult)633 static void Dalvik_java_lang_Class_getEnclosingMethod(const u4* args,
634 JValue* pResult)
635 {
636 ClassObject* clazz = (ClassObject*) args[0];
637
638 Object* enclosing = dvmGetEnclosingMethod(clazz);
639 if (enclosing != NULL) {
640 dvmReleaseTrackedAlloc(enclosing, NULL);
641 if (enclosing->clazz == gDvm.classJavaLangReflectMethod) {
642 RETURN_PTR(enclosing);
643 }
644 assert(enclosing->clazz == gDvm.classJavaLangReflectConstructor);
645 }
646 RETURN_PTR(NULL);
647 }
648
649 #if 0
650 static void Dalvik_java_lang_Class_getGenericInterfaces(const u4* args,
651 JValue* pResult)
652 {
653 dvmThrowException("Ljava/lang/UnsupportedOperationException;",
654 "native method not implemented");
655
656 RETURN_PTR(NULL);
657 }
658
659 static void Dalvik_java_lang_Class_getGenericSuperclass(const u4* args,
660 JValue* pResult)
661 {
662 dvmThrowException("Ljava/lang/UnsupportedOperationException;",
663 "native method not implemented");
664
665 RETURN_PTR(NULL);
666 }
667
668 static void Dalvik_java_lang_Class_getTypeParameters(const u4* args,
669 JValue* pResult)
670 {
671 dvmThrowException("Ljava/lang/UnsupportedOperationException;",
672 "native method not implemented");
673
674 RETURN_PTR(NULL);
675 }
676 #endif
677
678 /*
679 * public boolean isAnonymousClass()
680 *
681 * Returns true if this is an "anonymous" class.
682 */
Dalvik_java_lang_Class_isAnonymousClass(const u4 * args,JValue * pResult)683 static void Dalvik_java_lang_Class_isAnonymousClass(const u4* args,
684 JValue* pResult)
685 {
686 ClassObject* clazz = (ClassObject*) args[0];
687 StringObject* className = NULL;
688 int accessFlags;
689
690 /*
691 * If this has an InnerClass annotation, pull it out. Lack of the
692 * annotation, or an annotation with a NULL class name, indicates
693 * that this is an anonymous inner class.
694 */
695 if (!dvmGetInnerClass(clazz, &className, &accessFlags))
696 RETURN_BOOLEAN(false);
697
698 dvmReleaseTrackedAlloc((Object*) className, NULL);
699 RETURN_BOOLEAN(className == NULL);
700 }
701
702 /*
703 * private Annotation[] getDeclaredAnnotations()
704 *
705 * Return the annotations declared on this class.
706 */
Dalvik_java_lang_Class_getDeclaredAnnotations(const u4 * args,JValue * pResult)707 static void Dalvik_java_lang_Class_getDeclaredAnnotations(const u4* args,
708 JValue* pResult)
709 {
710 ClassObject* clazz = (ClassObject*) args[0];
711
712 ArrayObject* annos = dvmGetClassAnnotations(clazz);
713 dvmReleaseTrackedAlloc((Object*) annos, NULL);
714 RETURN_PTR(annos);
715 }
716
717 /*
718 * public String getInnerClassName()
719 *
720 * Returns the simple name of a member class or local class, or null otherwise.
721 */
Dalvik_java_lang_Class_getInnerClassName(const u4 * args,JValue * pResult)722 static void Dalvik_java_lang_Class_getInnerClassName(const u4* args,
723 JValue* pResult)
724 {
725 ClassObject* clazz = (ClassObject*) args[0];
726 StringObject* nameObj;
727 int flags;
728
729 if (dvmGetInnerClass(clazz, &nameObj, &flags)) {
730 dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
731 RETURN_PTR(nameObj);
732 } else {
733 RETURN_PTR(NULL);
734 }
735 }
736
737 /*
738 * static native void setAccessibleNoCheck(AccessibleObject ao, boolean flag);
739 */
Dalvik_java_lang_Class_setAccessibleNoCheck(const u4 * args,JValue * pResult)740 static void Dalvik_java_lang_Class_setAccessibleNoCheck(const u4* args,
741 JValue* pResult)
742 {
743 Object* target = (Object*) args[0];
744 u4 flag = (u4) args[1];
745
746 dvmSetFieldBoolean(target, gDvm.offJavaLangReflectAccessibleObject_flag,
747 flag);
748 }
749
750 const DalvikNativeMethod dvm_java_lang_Class[] = {
751 { "desiredAssertionStatus", "()Z",
752 Dalvik_java_lang_Class_desiredAssertionStatus },
753 { "classForName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;",
754 Dalvik_java_lang_Class_classForName },
755 { "getClassLoader", "(Ljava/lang/Class;)Ljava/lang/ClassLoader;",
756 Dalvik_java_lang_Class_getClassLoader },
757 { "getComponentType", "()Ljava/lang/Class;",
758 Dalvik_java_lang_Class_getComponentType },
759 { "getSignatureAnnotation", "()[Ljava/lang/Object;",
760 Dalvik_java_lang_Class_getSignatureAnnotation },
761 { "getDeclaredClasses", "(Ljava/lang/Class;Z)[Ljava/lang/Class;",
762 Dalvik_java_lang_Class_getDeclaredClasses },
763 { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;",
764 Dalvik_java_lang_Class_getDeclaredConstructors },
765 { "getDeclaredFields", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;",
766 Dalvik_java_lang_Class_getDeclaredFields },
767 { "getDeclaredMethods", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;",
768 Dalvik_java_lang_Class_getDeclaredMethods },
769 { "getInterfaces", "()[Ljava/lang/Class;",
770 Dalvik_java_lang_Class_getInterfaces },
771 { "getModifiers", "(Ljava/lang/Class;Z)I",
772 Dalvik_java_lang_Class_getModifiers },
773 { "getName", "()Ljava/lang/String;",
774 Dalvik_java_lang_Class_getName },
775 { "getSuperclass", "()Ljava/lang/Class;",
776 Dalvik_java_lang_Class_getSuperclass },
777 { "isAssignableFrom", "(Ljava/lang/Class;)Z",
778 Dalvik_java_lang_Class_isAssignableFrom },
779 { "isInstance", "(Ljava/lang/Object;)Z",
780 Dalvik_java_lang_Class_isInstance },
781 { "isInterface", "()Z",
782 Dalvik_java_lang_Class_isInterface },
783 { "isPrimitive", "()Z",
784 Dalvik_java_lang_Class_isPrimitive },
785 { "newInstanceImpl", "()Ljava/lang/Object;",
786 Dalvik_java_lang_Class_newInstance },
787 { "getDeclaringClass", "()Ljava/lang/Class;",
788 Dalvik_java_lang_Class_getDeclaringClass },
789 { "getEnclosingClass", "()Ljava/lang/Class;",
790 Dalvik_java_lang_Class_getEnclosingClass },
791 { "getEnclosingConstructor", "()Ljava/lang/reflect/Constructor;",
792 Dalvik_java_lang_Class_getEnclosingConstructor },
793 { "getEnclosingMethod", "()Ljava/lang/reflect/Method;",
794 Dalvik_java_lang_Class_getEnclosingMethod },
795 #if 0
796 { "getGenericInterfaces", "()[Ljava/lang/reflect/Type;",
797 Dalvik_java_lang_Class_getGenericInterfaces },
798 { "getGenericSuperclass", "()Ljava/lang/reflect/Type;",
799 Dalvik_java_lang_Class_getGenericSuperclass },
800 { "getTypeParameters", "()Ljava/lang/reflect/TypeVariable;",
801 Dalvik_java_lang_Class_getTypeParameters },
802 #endif
803 { "isAnonymousClass", "()Z",
804 Dalvik_java_lang_Class_isAnonymousClass },
805 { "getDeclaredAnnotations", "()[Ljava/lang/annotation/Annotation;",
806 Dalvik_java_lang_Class_getDeclaredAnnotations },
807 { "getInnerClassName", "()Ljava/lang/String;",
808 Dalvik_java_lang_Class_getInnerClassName },
809 { "setAccessibleNoCheck", "(Ljava/lang/reflect/AccessibleObject;Z)V",
810 Dalvik_java_lang_Class_setAccessibleNoCheck },
811 { NULL, NULL, NULL },
812 };
813
814