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 #include "ScopedPthreadMutexLock.h" 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 */ 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 ALOGV("ASRT: pkg no match: '%s'(%d) vs '%s'", 73 className, pkgLen, pCtrl->pkgOrClass); 74 } else { 75 ALOGV("ASRT: pkg match: '%s'(%d) vs '%s' --> %d", 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 ALOGV("ASRT: sys no match: '%s'", className); 88 } else { 89 ALOGV("ASRT: sys match: '%s' --> %d", 90 className, pCtrl->enable); 91 enable = pCtrl->enable; 92 } 93 } else if (*pCtrl->pkgOrClass == '\0') { 94 ALOGV("ASRT: class all: '%s' --> %d", 95 className, pCtrl->enable); 96 enable = pCtrl->enable; 97 } else { 98 if (strcmp(pCtrl->pkgOrClass, className) != 0) { 99 ALOGV("ASRT: cls no match: '%s' vs '%s'", 100 className, pCtrl->pkgOrClass); 101 } else { 102 ALOGV("ASRT: cls match: '%s' vs '%s' --> %d", 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 */ 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 */ 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 */ 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 */ 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**)(void*)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 */ 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 */ 246 static void Dalvik_java_lang_Class_getDeclaredFields(const u4* args, 247 JValue* pResult) 248 { 249 ClassObject* clazz = (ClassObject*) args[0]; 250 bool publicOnly = (args[1] != 0); 251 ArrayObject* fields; 252 253 fields = dvmGetDeclaredFields(clazz, publicOnly); 254 dvmReleaseTrackedAlloc((Object*) fields, NULL); 255 256 RETURN_PTR(fields); 257 } 258 259 /* 260 * static Field getDeclaredField(Class klass, String name) 261 */ 262 static void Dalvik_java_lang_Class_getDeclaredField(const u4* args, 263 JValue* pResult) 264 { 265 ClassObject* clazz = (ClassObject*) args[0]; 266 StringObject* nameObj = (StringObject*) args[1]; 267 Object* fieldObj = dvmGetDeclaredField(clazz, nameObj); 268 dvmReleaseTrackedAlloc((Object*) fieldObj, NULL); 269 RETURN_PTR(fieldObj); 270 } 271 272 /* 273 * static Method[] getDeclaredMethods(Class clazz, boolean publicOnly) 274 * throws SecurityException 275 */ 276 static void Dalvik_java_lang_Class_getDeclaredMethods(const u4* args, 277 JValue* pResult) 278 { 279 ClassObject* clazz = (ClassObject*) args[0]; 280 bool publicOnly = (args[1] != 0); 281 ArrayObject* methods; 282 283 methods = dvmGetDeclaredMethods(clazz, publicOnly); 284 dvmReleaseTrackedAlloc((Object*) methods, NULL); 285 286 RETURN_PTR(methods); 287 } 288 289 /* 290 * static native Member getDeclaredConstructorOrMethod( 291 * Class clazz, String name, Class[] args); 292 */ 293 static void Dalvik_java_lang_Class_getDeclaredConstructorOrMethod( 294 const u4* args, JValue* pResult) 295 { 296 ClassObject* clazz = (ClassObject*) args[0]; 297 StringObject* nameObj = (StringObject*) args[1]; 298 ArrayObject* methodArgs = (ArrayObject*) args[2]; 299 300 Object* methodObj; 301 302 methodObj = dvmGetDeclaredConstructorOrMethod(clazz, nameObj, methodArgs); 303 dvmReleaseTrackedAlloc(methodObj, NULL); 304 305 RETURN_PTR(methodObj); 306 } 307 308 /* 309 * Class[] getInterfaces() 310 */ 311 static void Dalvik_java_lang_Class_getInterfaces(const u4* args, 312 JValue* pResult) 313 { 314 ClassObject* clazz = (ClassObject*) args[0]; 315 ArrayObject* interfaces; 316 317 interfaces = dvmGetInterfaces(clazz); 318 dvmReleaseTrackedAlloc((Object*) interfaces, NULL); 319 320 RETURN_PTR(interfaces); 321 } 322 323 /* 324 * private static int getModifiers(Class klass, boolean 325 * ignoreInnerClassesAttrib) 326 * 327 * Return the class' modifier flags. If "ignoreInnerClassesAttrib" is false, 328 * and this is an inner class, we return the access flags from the inner class 329 * attribute. 330 */ 331 static void Dalvik_java_lang_Class_getModifiers(const u4* args, JValue* pResult) 332 { 333 ClassObject* clazz = (ClassObject*) args[0]; 334 bool ignoreInner = args[1]; 335 u4 accessFlags; 336 337 accessFlags = clazz->accessFlags & JAVA_FLAGS_MASK; 338 339 if (!ignoreInner) { 340 /* see if we have an InnerClass annotation with flags in it */ 341 StringObject* className = NULL; 342 int innerFlags; 343 344 if (dvmGetInnerClass(clazz, &className, &innerFlags)) 345 accessFlags = innerFlags & JAVA_FLAGS_MASK; 346 347 dvmReleaseTrackedAlloc((Object*) className, NULL); 348 } 349 350 RETURN_INT(accessFlags); 351 } 352 353 /* 354 * private native String getNameNative() 355 * 356 * Return the class' name. The exact format is bizarre, but it's the specified 357 * behavior: keywords for primitive types, regular "[I" form for primitive 358 * arrays (so "int" but "[I"), and arrays of reference types written 359 * between "L" and ";" but with dots rather than slashes (so "java.lang.String" 360 * but "[Ljava.lang.String;"). Madness. 361 */ 362 static void Dalvik_java_lang_Class_getNameNative(const u4* args, JValue* pResult) 363 { 364 ClassObject* clazz = (ClassObject*) args[0]; 365 const char* descriptor = clazz->descriptor; 366 StringObject* nameObj; 367 368 if ((descriptor[0] != 'L') && (descriptor[0] != '[')) { 369 /* 370 * The descriptor indicates that this is the class for 371 * a primitive type; special-case the return value. 372 */ 373 const char* name; 374 switch (descriptor[0]) { 375 case 'Z': name = "boolean"; break; 376 case 'B': name = "byte"; break; 377 case 'C': name = "char"; break; 378 case 'S': name = "short"; break; 379 case 'I': name = "int"; break; 380 case 'J': name = "long"; break; 381 case 'F': name = "float"; break; 382 case 'D': name = "double"; break; 383 case 'V': name = "void"; break; 384 default: { 385 ALOGE("Unknown primitive type '%c'", descriptor[0]); 386 assert(false); 387 RETURN_PTR(NULL); 388 } 389 } 390 391 nameObj = dvmCreateStringFromCstr(name); 392 } else { 393 /* 394 * Convert the UTF-8 name to a java.lang.String. The 395 * name must use '.' to separate package components. 396 * 397 * TODO: this could be more efficient. Consider a custom 398 * conversion function here that walks the string once and 399 * avoids the allocation for the common case (name less than, 400 * say, 128 bytes). 401 */ 402 char* dotName = dvmDescriptorToDot(clazz->descriptor); 403 nameObj = dvmCreateStringFromCstr(dotName); 404 free(dotName); 405 } 406 407 dvmReleaseTrackedAlloc((Object*) nameObj, NULL); 408 RETURN_PTR(nameObj); 409 } 410 411 /* 412 * Return the superclass for instances of this class. 413 * 414 * If the class represents a java/lang/Object, an interface, a primitive 415 * type, or void (which *is* a primitive type??), return NULL. 416 * 417 * For an array, return the java/lang/Object ClassObject. 418 */ 419 static void Dalvik_java_lang_Class_getSuperclass(const u4* args, 420 JValue* pResult) 421 { 422 ClassObject* clazz = (ClassObject*) args[0]; 423 424 if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz)) 425 RETURN_PTR(NULL); 426 else 427 RETURN_PTR(clazz->super); 428 } 429 430 /* 431 * public boolean isAssignableFrom(Class<?> cls) 432 * 433 * Determine if this class is either the same as, or is a superclass or 434 * superinterface of, the class specified in the "cls" parameter. 435 */ 436 static void Dalvik_java_lang_Class_isAssignableFrom(const u4* args, 437 JValue* pResult) 438 { 439 ClassObject* thisPtr = (ClassObject*) args[0]; 440 ClassObject* testClass = (ClassObject*) args[1]; 441 442 if (testClass == NULL) { 443 dvmThrowNullPointerException("cls == null"); 444 RETURN_INT(false); 445 } 446 RETURN_INT(dvmInstanceof(testClass, thisPtr)); 447 } 448 449 /* 450 * public boolean isInstance(Object o) 451 * 452 * Dynamic equivalent of Java programming language "instanceof". 453 */ 454 static void Dalvik_java_lang_Class_isInstance(const u4* args, 455 JValue* pResult) 456 { 457 ClassObject* thisPtr = (ClassObject*) args[0]; 458 Object* testObj = (Object*) args[1]; 459 460 if (testObj == NULL) 461 RETURN_INT(false); 462 RETURN_INT(dvmInstanceof(testObj->clazz, thisPtr)); 463 } 464 465 /* 466 * public boolean isInterface() 467 */ 468 static void Dalvik_java_lang_Class_isInterface(const u4* args, 469 JValue* pResult) 470 { 471 ClassObject* thisPtr = (ClassObject*) args[0]; 472 473 RETURN_INT(dvmIsInterfaceClass(thisPtr)); 474 } 475 476 /* 477 * public boolean isPrimitive() 478 */ 479 static void Dalvik_java_lang_Class_isPrimitive(const u4* args, 480 JValue* pResult) 481 { 482 ClassObject* thisPtr = (ClassObject*) args[0]; 483 484 RETURN_INT(dvmIsPrimitiveClass(thisPtr)); 485 } 486 487 /* 488 * public T newInstance() throws InstantiationException, IllegalAccessException 489 * 490 * Create a new instance of this class. 491 */ 492 static void Dalvik_java_lang_Class_newInstance(const u4* args, JValue* pResult) 493 { 494 Thread* self = dvmThreadSelf(); 495 ClassObject* clazz = (ClassObject*) args[0]; 496 Method* init; 497 Object* newObj; 498 499 /* can't instantiate these */ 500 if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz) 501 || dvmIsArrayClass(clazz) || dvmIsAbstractClass(clazz)) 502 { 503 ALOGD("newInstance failed: p%d i%d [%d a%d", 504 dvmIsPrimitiveClass(clazz), dvmIsInterfaceClass(clazz), 505 dvmIsArrayClass(clazz), dvmIsAbstractClass(clazz)); 506 dvmThrowInstantiationException(clazz, NULL); 507 RETURN_VOID(); 508 } 509 510 /* initialize the class if it hasn't been already */ 511 if (!dvmIsClassInitialized(clazz)) { 512 if (!dvmInitClass(clazz)) { 513 ALOGW("Class init failed in newInstance call (%s)", 514 clazz->descriptor); 515 assert(dvmCheckException(self)); 516 RETURN_VOID(); 517 } 518 } 519 520 /* find the "nullary" constructor */ 521 init = dvmFindDirectMethodByDescriptor(clazz, "<init>", "()V"); 522 if (init == NULL) { 523 /* common cause: secret "this" arg on non-static inner class ctor */ 524 ALOGD("newInstance failed: no <init>()"); 525 dvmThrowInstantiationException(clazz, "no empty constructor"); 526 RETURN_VOID(); 527 } 528 529 /* 530 * Verify access from the call site. 531 * 532 * First, make sure the method invoking Class.newInstance() has permission 533 * to access the class. 534 * 535 * Second, make sure it has permission to invoke the constructor. The 536 * constructor must be public or, if the caller is in the same package, 537 * have package scope. 538 */ 539 ClassObject* callerClass = dvmGetCaller2Class(self->interpSave.curFrame); 540 541 if (!dvmCheckClassAccess(callerClass, clazz)) { 542 ALOGD("newInstance failed: %s not accessible to %s", 543 clazz->descriptor, callerClass->descriptor); 544 dvmThrowIllegalAccessException("access to class not allowed"); 545 RETURN_VOID(); 546 } 547 if (!dvmCheckMethodAccess(callerClass, init)) { 548 ALOGD("newInstance failed: %s.<init>() not accessible to %s", 549 clazz->descriptor, callerClass->descriptor); 550 dvmThrowIllegalAccessException("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 */ 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 */ 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 */ 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 */ 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 */ 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 dvmThrowUnsupportedOperationException("native method not implemented"); 656 657 RETURN_PTR(NULL); 658 } 659 660 static void Dalvik_java_lang_Class_getGenericSuperclass(const u4* args, 661 JValue* pResult) 662 { 663 dvmThrowUnsupportedOperationException("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 dvmThrowUnsupportedOperationException("native method not implemented"); 672 673 RETURN_PTR(NULL); 674 } 675 #endif 676 677 /* 678 * public boolean isAnonymousClass() 679 * 680 * Returns true if this is an "anonymous" class. 681 */ 682 static void Dalvik_java_lang_Class_isAnonymousClass(const u4* args, 683 JValue* pResult) 684 { 685 ClassObject* clazz = (ClassObject*) args[0]; 686 StringObject* className = NULL; 687 int accessFlags; 688 689 /* 690 * If this has an InnerClass annotation, pull it out. Lack of the 691 * annotation, or an annotation with a NULL class name, indicates 692 * that this is an anonymous inner class. 693 */ 694 if (!dvmGetInnerClass(clazz, &className, &accessFlags)) 695 RETURN_BOOLEAN(false); 696 697 dvmReleaseTrackedAlloc((Object*) className, NULL); 698 RETURN_BOOLEAN(className == NULL); 699 } 700 701 /* 702 * private Annotation[] getDeclaredAnnotations() 703 * 704 * Return the annotations declared on this class. 705 */ 706 static void Dalvik_java_lang_Class_getDeclaredAnnotations(const u4* args, 707 JValue* pResult) 708 { 709 ClassObject* clazz = (ClassObject*) args[0]; 710 711 ArrayObject* annos = dvmGetClassAnnotations(clazz); 712 dvmReleaseTrackedAlloc((Object*) annos, NULL); 713 RETURN_PTR(annos); 714 } 715 716 /* 717 * private Annotation getDeclaredAnnotation(Class annotationClass) 718 */ 719 static void Dalvik_java_lang_Class_getDeclaredAnnotation(const u4* args, 720 JValue* pResult) 721 { 722 ClassObject* clazz = (ClassObject*) args[0]; 723 ClassObject* annotationClazz = (ClassObject*) args[1]; 724 725 RETURN_PTR(dvmGetClassAnnotation(clazz, annotationClazz)); 726 } 727 728 /* 729 * private boolean isDeclaredAnnotationPresent(Class annotationClass); 730 */ 731 static void Dalvik_java_lang_Class_isDeclaredAnnotationPresent(const u4* args, 732 JValue* pResult) 733 { 734 ClassObject* clazz = (ClassObject*) args[0]; 735 ClassObject* annotationClazz = (ClassObject*) args[1]; 736 737 RETURN_BOOLEAN(dvmIsClassAnnotationPresent(clazz, annotationClazz)); 738 } 739 740 /* 741 * public String getInnerClassName() 742 * 743 * Returns the simple name of a member class or local class, or null otherwise. 744 */ 745 static void Dalvik_java_lang_Class_getInnerClassName(const u4* args, 746 JValue* pResult) 747 { 748 ClassObject* clazz = (ClassObject*) args[0]; 749 StringObject* nameObj; 750 int flags; 751 752 if (dvmGetInnerClass(clazz, &nameObj, &flags)) { 753 dvmReleaseTrackedAlloc((Object*) nameObj, NULL); 754 RETURN_PTR(nameObj); 755 } else { 756 RETURN_PTR(NULL); 757 } 758 } 759 760 JNIEXPORT jobject JNICALL Java_java_lang_Class_getDex(JNIEnv* env, jclass javaClass) { 761 Thread* self = dvmThreadSelf(); 762 ClassObject* c = (ClassObject*) dvmDecodeIndirectRef(self, javaClass); 763 764 DvmDex* dvm_dex = c->pDvmDex; 765 if (dvm_dex == NULL) { 766 return NULL; 767 } 768 // Already cached? 769 if (dvm_dex->dex_object != NULL) { 770 return dvm_dex->dex_object; 771 } 772 jobject byte_buffer = env->NewDirectByteBuffer(dvm_dex->memMap.addr, dvm_dex->memMap.length); 773 if (byte_buffer == NULL) { 774 return NULL; 775 } 776 777 jclass com_android_dex_Dex = env->FindClass("com/android/dex/Dex"); 778 if (com_android_dex_Dex == NULL) { 779 return NULL; 780 } 781 782 jmethodID com_android_dex_Dex_create = 783 env->GetStaticMethodID(com_android_dex_Dex, 784 "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;"); 785 if (com_android_dex_Dex_create == NULL) { 786 return NULL; 787 } 788 789 jvalue args[1]; 790 args[0].l = byte_buffer; 791 jobject local_ref = env->CallStaticObjectMethodA(com_android_dex_Dex, 792 com_android_dex_Dex_create, 793 args); 794 if (local_ref == NULL) { 795 return NULL; 796 } 797 798 // Check another thread didn't cache an object, if we've won install the object. 799 ScopedPthreadMutexLock lock(&dvm_dex->modLock); 800 801 if (dvm_dex->dex_object == NULL) { 802 dvm_dex->dex_object = env->NewGlobalRef(local_ref); 803 } 804 return dvm_dex->dex_object; 805 } 806 807 const DalvikNativeMethod dvm_java_lang_Class[] = { 808 { "desiredAssertionStatus", "()Z", 809 Dalvik_java_lang_Class_desiredAssertionStatus }, 810 { "classForName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", 811 Dalvik_java_lang_Class_classForName }, 812 { "getClassLoader", "(Ljava/lang/Class;)Ljava/lang/ClassLoader;", 813 Dalvik_java_lang_Class_getClassLoader }, 814 { "getComponentType", "()Ljava/lang/Class;", 815 Dalvik_java_lang_Class_getComponentType }, 816 { "getSignatureAnnotation", "()[Ljava/lang/Object;", 817 Dalvik_java_lang_Class_getSignatureAnnotation }, 818 { "getDeclaredClasses", "(Ljava/lang/Class;Z)[Ljava/lang/Class;", 819 Dalvik_java_lang_Class_getDeclaredClasses }, 820 { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;", 821 Dalvik_java_lang_Class_getDeclaredConstructors }, 822 { "getDeclaredFields", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;", 823 Dalvik_java_lang_Class_getDeclaredFields }, 824 { "getDeclaredMethods", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;", 825 Dalvik_java_lang_Class_getDeclaredMethods }, 826 { "getDeclaredField", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;", 827 Dalvik_java_lang_Class_getDeclaredField }, 828 { "getDeclaredConstructorOrMethod", "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;", 829 Dalvik_java_lang_Class_getDeclaredConstructorOrMethod }, 830 { "getInterfaces", "()[Ljava/lang/Class;", 831 Dalvik_java_lang_Class_getInterfaces }, 832 { "getModifiers", "(Ljava/lang/Class;Z)I", 833 Dalvik_java_lang_Class_getModifiers }, 834 { "getNameNative", "()Ljava/lang/String;", 835 Dalvik_java_lang_Class_getNameNative }, 836 { "getSuperclass", "()Ljava/lang/Class;", 837 Dalvik_java_lang_Class_getSuperclass }, 838 { "isAssignableFrom", "(Ljava/lang/Class;)Z", 839 Dalvik_java_lang_Class_isAssignableFrom }, 840 { "isInstance", "(Ljava/lang/Object;)Z", 841 Dalvik_java_lang_Class_isInstance }, 842 { "isInterface", "()Z", 843 Dalvik_java_lang_Class_isInterface }, 844 { "isPrimitive", "()Z", 845 Dalvik_java_lang_Class_isPrimitive }, 846 { "newInstanceImpl", "()Ljava/lang/Object;", 847 Dalvik_java_lang_Class_newInstance }, 848 { "getDeclaringClass", "()Ljava/lang/Class;", 849 Dalvik_java_lang_Class_getDeclaringClass }, 850 { "getEnclosingClass", "()Ljava/lang/Class;", 851 Dalvik_java_lang_Class_getEnclosingClass }, 852 { "getEnclosingConstructor", "()Ljava/lang/reflect/Constructor;", 853 Dalvik_java_lang_Class_getEnclosingConstructor }, 854 { "getEnclosingMethod", "()Ljava/lang/reflect/Method;", 855 Dalvik_java_lang_Class_getEnclosingMethod }, 856 #if 0 857 { "getGenericInterfaces", "()[Ljava/lang/reflect/Type;", 858 Dalvik_java_lang_Class_getGenericInterfaces }, 859 { "getGenericSuperclass", "()Ljava/lang/reflect/Type;", 860 Dalvik_java_lang_Class_getGenericSuperclass }, 861 { "getTypeParameters", "()Ljava/lang/reflect/TypeVariable;", 862 Dalvik_java_lang_Class_getTypeParameters }, 863 #endif 864 { "isAnonymousClass", "()Z", 865 Dalvik_java_lang_Class_isAnonymousClass }, 866 { "getDeclaredAnnotations", "()[Ljava/lang/annotation/Annotation;", 867 Dalvik_java_lang_Class_getDeclaredAnnotations }, 868 { "getDeclaredAnnotation", "(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;", 869 Dalvik_java_lang_Class_getDeclaredAnnotation }, 870 { "isDeclaredAnnotationPresent", "(Ljava/lang/Class;)Z", 871 Dalvik_java_lang_Class_isDeclaredAnnotationPresent }, 872 { "getInnerClassName", "()Ljava/lang/String;", 873 Dalvik_java_lang_Class_getInnerClassName }, 874 { NULL, NULL, NULL }, 875 }; 876