Class.cpp revision 6daaac12e5de630749f94ff5f15e902e7b18d8e7
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 * Class loading, including bootstrap class loader, linking, and 19 * initialization. 20 */ 21 22#define LOG_CLASS_LOADING 0 23 24#include "Dalvik.h" 25#include "libdex/DexClass.h" 26 27#include <stdlib.h> 28#include <stddef.h> 29#include <sys/stat.h> 30 31#if LOG_CLASS_LOADING 32#include <unistd.h> 33#include <pthread.h> 34#include <cutils/process_name.h> 35#include <sys/types.h> 36#endif 37 38/* 39Notes on Linking and Verification 40 41The basic way to retrieve a class is to load it, make sure its superclass 42and interfaces are available, prepare its fields, and return it. This gets 43a little more complicated when multiple threads can be trying to retrieve 44the class simultaneously, requiring that we use the class object's monitor 45to keep things orderly. 46 47The linking (preparing, resolving) of a class can cause us to recursively 48load superclasses and interfaces. Barring circular references (e.g. two 49classes that are superclasses of each other), this will complete without 50the loader attempting to access the partially-linked class. 51 52With verification, the situation is different. If we try to verify 53every class as we load it, we quickly run into trouble. Even the lowly 54java.lang.Object requires CloneNotSupportedException; follow the list 55of referenced classes and you can head down quite a trail. The trail 56eventually leads back to Object, which is officially not fully-formed yet. 57 58The VM spec (specifically, v2 5.4.1) notes that classes pulled in during 59verification do not need to be prepared or verified. This means that we 60are allowed to have loaded but unverified classes. It further notes that 61the class must be verified before it is initialized, which allows us to 62defer verification for all classes until class init. You can't execute 63code or access fields in an uninitialized class, so this is safe. 64 65It also allows a more peaceful coexistence between verified and 66unverifiable code. If class A refers to B, and B has a method that 67refers to a bogus class C, should we allow class A to be verified? 68If A only exercises parts of B that don't use class C, then there is 69nothing wrong with running code in A. We can fully verify both A and B, 70and allow execution to continue until B causes initialization of C. The 71VerifyError is thrown close to the point of use. 72 73This gets a little weird with java.lang.Class, which is the only class 74that can be instantiated before it is initialized. We have to force 75initialization right after the class is created, because by definition we 76have instances of it on the heap, and somebody might get a class object and 77start making virtual calls on it. We can end up going recursive during 78verification of java.lang.Class, but we avoid that by checking to see if 79verification is already in progress before we try to initialize it. 80*/ 81 82/* 83Notes on class loaders and interaction with optimization / verification 84 85In what follows, "pre-verification" and "optimization" are the steps 86performed by the dexopt command, which attempts to verify and optimize 87classes as part of unpacking jar files and storing the DEX data in the 88dalvik-cache directory. These steps are performed by loading the DEX 89files directly, without any assistance from ClassLoader instances. 90 91When we pre-verify and optimize a class in a DEX file, we make some 92assumptions about where the class loader will go to look for classes. 93If we can't guarantee those assumptions, e.g. because a class ("AppClass") 94references something not defined in the bootstrap jars or the AppClass jar, 95we can't pre-verify or optimize the class. 96 97The VM doesn't define the behavior of user-defined class loaders. 98For example, suppose application class AppClass, loaded by UserLoader, 99has a method that creates a java.lang.String. The first time 100AppClass.stringyMethod tries to do something with java.lang.String, it 101asks UserLoader to find it. UserLoader is expected to defer to its parent 102loader, but isn't required to. UserLoader might provide a replacement 103for String. 104 105We can run into trouble if we pre-verify AppClass with the assumption that 106java.lang.String will come from core.jar, and don't verify this assumption 107at runtime. There are two places that an alternate implementation of 108java.lang.String can come from: the AppClass jar, or from some other jar 109that UserLoader knows about. (Someday UserLoader will be able to generate 110some bytecode and call DefineClass, but not yet.) 111 112To handle the first situation, the pre-verifier will explicitly check for 113conflicts between the class being optimized/verified and the bootstrap 114classes. If an app jar contains a class that has the same package and 115class name as a class in a bootstrap jar, the verification resolver refuses 116to find either, which will block pre-verification and optimization on 117classes that reference ambiguity. The VM will postpone verification of 118the app class until first load. 119 120For the second situation, we need to ensure that all references from a 121pre-verified class are satisified by the class' jar or earlier bootstrap 122jars. In concrete terms: when resolving a reference to NewClass, 123which was caused by a reference in class AppClass, we check to see if 124AppClass was pre-verified. If so, we require that NewClass comes out 125of either the AppClass jar or one of the jars in the bootstrap path. 126(We may not control the class loaders, but we do manage the DEX files. 127We can verify that it's either (loader==null && dexFile==a_boot_dex) 128or (loader==UserLoader && dexFile==AppClass.dexFile). Classes from 129DefineClass can't be pre-verified, so this doesn't apply.) 130 131This should ensure that you can't "fake out" the pre-verifier by creating 132a user-defined class loader that replaces system classes. It should 133also ensure that you can write such a loader and have it work in the 134expected fashion; all you lose is some performance due to "just-in-time 135verification" and the lack of DEX optimizations. 136 137There is a "back door" of sorts in the class resolution check, due to 138the fact that the "class ref" entries are shared between the bytecode 139and meta-data references (e.g. annotations and exception handler lists). 140The class references in annotations have no bearing on class verification, 141so when a class does an annotation query that causes a class reference 142index to be resolved, we don't want to fail just because the calling 143class was pre-verified and the resolved class is in some random DEX file. 144The successful resolution adds the class to the "resolved classes" table, 145so when optimized bytecode references it we don't repeat the resolve-time 146check. We can avoid this by not updating the "resolved classes" table 147when the class reference doesn't come out of something that has been 148checked by the verifier, but that has a nonzero performance impact. 149Since the ultimate goal of this test is to catch an unusual situation 150(user-defined class loaders redefining core classes), the added caution 151may not be worth the performance hit. 152*/ 153 154/* 155 * Class serial numbers start at this value. We use a nonzero initial 156 * value so they stand out in binary dumps (e.g. hprof output). 157 */ 158#define INITIAL_CLASS_SERIAL_NUMBER 0x50000000 159 160 161/* 162 * Constant used to size an auxillary class object data structure. 163 * For optimum memory use this should be equal to or slightly larger than 164 * the number of classes loaded when the zygote finishes initializing. 165 */ 166#define ZYGOTE_CLASS_CUTOFF 2304 167 168static ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap); 169static void freeCpeArray(ClassPathEntry* cpe); 170 171static ClassObject* findClassFromLoaderNoInit( 172 const char* descriptor, Object* loader); 173static ClassObject* findClassNoInit(const char* descriptor, Object* loader,\ 174 DvmDex* pDvmDex); 175static ClassObject* loadClassFromDex(DvmDex* pDvmDex, 176 const DexClassDef* pClassDef, Object* loader); 177static void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,\ 178 Method* meth); 179static int computeJniArgInfo(const DexProto* proto); 180static void loadSFieldFromDex(ClassObject* clazz, 181 const DexField* pDexSField, StaticField* sfield); 182static void loadIFieldFromDex(ClassObject* clazz, 183 const DexField* pDexIField, InstField* field); 184static bool precacheReferenceOffsets(ClassObject* clazz); 185static void computeRefOffsets(ClassObject* clazz); 186static void freeMethodInnards(Method* meth); 187static bool createVtable(ClassObject* clazz); 188static bool createIftable(ClassObject* clazz); 189static bool insertMethodStubs(ClassObject* clazz); 190static bool computeFieldOffsets(ClassObject* clazz); 191static void throwEarlierClassFailure(ClassObject* clazz); 192 193#if LOG_CLASS_LOADING 194/* 195 * Logs information about a class loading with given timestamp. 196 * 197 * TODO: In the case where we fail in dvmLinkClass() and log the class as closing (type='<'), 198 * it would probably be better to use a new type code to indicate the failure. This change would 199 * require a matching change in the parser and analysis code in frameworks/base/tools/preload. 200 */ 201static void logClassLoadWithTime(char type, ClassObject* clazz, u8 time) { 202 pid_t ppid = getppid(); 203 pid_t pid = getpid(); 204 unsigned int tid = (unsigned int) pthread_self(); 205 206 LOG(LOG_INFO, "PRELOAD", "%c%d:%d:%d:%s:%d:%s:%lld\n", type, ppid, pid, tid, 207 get_process_name(), (int) clazz->classLoader, clazz->descriptor, 208 time); 209} 210 211/* 212 * Logs information about a class loading. 213 */ 214static void logClassLoad(char type, ClassObject* clazz) { 215 logClassLoadWithTime(type, clazz, dvmGetThreadCpuTimeNsec()); 216} 217#endif 218 219/* 220 * Some LinearAlloc unit tests. 221 */ 222static void linearAllocTests() 223{ 224 char* fiddle; 225 int try = 1; 226 227 switch (try) { 228 case 0: 229 fiddle = dvmLinearAlloc(NULL, 3200-28); 230 dvmLinearReadOnly(NULL, fiddle); 231 break; 232 case 1: 233 fiddle = dvmLinearAlloc(NULL, 3200-24); 234 dvmLinearReadOnly(NULL, fiddle); 235 break; 236 case 2: 237 fiddle = dvmLinearAlloc(NULL, 3200-20); 238 dvmLinearReadOnly(NULL, fiddle); 239 break; 240 case 3: 241 fiddle = dvmLinearAlloc(NULL, 3200-16); 242 dvmLinearReadOnly(NULL, fiddle); 243 break; 244 case 4: 245 fiddle = dvmLinearAlloc(NULL, 3200-12); 246 dvmLinearReadOnly(NULL, fiddle); 247 break; 248 } 249 fiddle = dvmLinearAlloc(NULL, 896); 250 dvmLinearReadOnly(NULL, fiddle); 251 fiddle = dvmLinearAlloc(NULL, 20); // watch addr of this alloc 252 dvmLinearReadOnly(NULL, fiddle); 253 254 fiddle = dvmLinearAlloc(NULL, 1); 255 fiddle[0] = 'q'; 256 dvmLinearReadOnly(NULL, fiddle); 257 fiddle = dvmLinearAlloc(NULL, 4096); 258 fiddle[0] = 'x'; 259 fiddle[4095] = 'y'; 260 dvmLinearReadOnly(NULL, fiddle); 261 dvmLinearFree(NULL, fiddle); 262 fiddle = dvmLinearAlloc(NULL, 0); 263 dvmLinearReadOnly(NULL, fiddle); 264 fiddle = dvmLinearRealloc(NULL, fiddle, 12); 265 fiddle[11] = 'z'; 266 dvmLinearReadOnly(NULL, fiddle); 267 fiddle = dvmLinearRealloc(NULL, fiddle, 5); 268 dvmLinearReadOnly(NULL, fiddle); 269 fiddle = dvmLinearAlloc(NULL, 17001); 270 fiddle[0] = 'x'; 271 fiddle[17000] = 'y'; 272 dvmLinearReadOnly(NULL, fiddle); 273 274 char* str = dvmLinearStrdup(NULL, "This is a test!"); 275 LOGI("GOT: '%s'\n", str); 276 277 dvmLinearAllocDump(NULL); 278 dvmLinearFree(NULL, str); 279} 280 281/* 282 * Initialize the bootstrap class loader. 283 * 284 * Call this after the bootclasspath string has been finalized. 285 */ 286bool dvmClassStartup(void) 287{ 288 ClassObject* unlinkedClass; 289 290 /* make this a requirement -- don't currently support dirs in path */ 291 if (strcmp(gDvm.bootClassPathStr, ".") == 0) { 292 LOGE("ERROR: must specify non-'.' bootclasspath\n"); 293 return false; 294 } 295 296 gDvm.loadedClasses = 297 dvmHashTableCreate(256, (HashFreeFunc) dvmFreeClassInnards); 298 299 gDvm.pBootLoaderAlloc = dvmLinearAllocCreate(NULL); 300 if (gDvm.pBootLoaderAlloc == NULL) 301 return false; 302 303 if (false) { 304 linearAllocTests(); 305 exit(0); 306 } 307 308 /* 309 * Class serial number. We start with a high value to make it distinct 310 * in binary dumps (e.g. hprof). 311 */ 312 gDvm.classSerialNumber = INITIAL_CLASS_SERIAL_NUMBER; 313 314 /* Set up the table we'll use for tracking initiating loaders for 315 * early classes. 316 * If it's NULL, we just fall back to the InitiatingLoaderList in the 317 * ClassObject, so it's not fatal to fail this allocation. 318 */ 319 gDvm.initiatingLoaderList = 320 calloc(ZYGOTE_CLASS_CUTOFF, sizeof(InitiatingLoaderList)); 321 322 /* This placeholder class is used while a ClassObject is 323 * loading/linking so those not in the know can still say 324 * "obj->clazz->...". 325 */ 326 unlinkedClass = &gDvm.unlinkedJavaLangClassObject; 327 328 memset(unlinkedClass, 0, sizeof(*unlinkedClass)); 329 330 /* Set obj->clazz to NULL so anyone who gets too interested 331 * in the fake class will crash. 332 */ 333 DVM_OBJECT_INIT(&unlinkedClass->obj, NULL); 334 unlinkedClass->descriptor = "!unlinkedClass"; 335 dvmSetClassSerialNumber(unlinkedClass); 336 337 gDvm.unlinkedJavaLangClass = unlinkedClass; 338 339 /* 340 * Process the bootstrap class path. This means opening the specified 341 * DEX or Jar files and possibly running them through the optimizer. 342 */ 343 assert(gDvm.bootClassPath == NULL); 344 processClassPath(gDvm.bootClassPathStr, true); 345 346 if (gDvm.bootClassPath == NULL) 347 return false; 348 349 return true; 350} 351 352/* 353 * Clean up. 354 */ 355void dvmClassShutdown(void) 356{ 357 int i; 358 359 /* discard all system-loaded classes */ 360 dvmHashTableFree(gDvm.loadedClasses); 361 gDvm.loadedClasses = NULL; 362 363 /* discard primitive classes created for arrays */ 364 for (i = 0; i < PRIM_MAX; i++) 365 dvmFreeClassInnards(gDvm.primitiveClass[i]); 366 367 /* this closes DEX files, JAR files, etc. */ 368 freeCpeArray(gDvm.bootClassPath); 369 gDvm.bootClassPath = NULL; 370 371 dvmLinearAllocDestroy(NULL); 372 373 free(gDvm.initiatingLoaderList); 374} 375 376 377/* 378 * =========================================================================== 379 * Bootstrap class loader 380 * =========================================================================== 381 */ 382 383/* 384 * Dump the contents of a ClassPathEntry array. 385 */ 386static void dumpClassPath(const ClassPathEntry* cpe) 387{ 388 int idx = 0; 389 390 while (cpe->kind != kCpeLastEntry) { 391 const char* kindStr; 392 393 switch (cpe->kind) { 394 case kCpeDir: kindStr = "dir"; break; 395 case kCpeJar: kindStr = "jar"; break; 396 case kCpeDex: kindStr = "dex"; break; 397 default: kindStr = "???"; break; 398 } 399 400 LOGI(" %2d: type=%s %s %p\n", idx, kindStr, cpe->fileName, cpe->ptr); 401 if (CALC_CACHE_STATS && cpe->kind == kCpeJar) { 402 JarFile* pJarFile = (JarFile*) cpe->ptr; 403 DvmDex* pDvmDex = dvmGetJarFileDex(pJarFile); 404 dvmDumpAtomicCacheStats(pDvmDex->pInterfaceCache); 405 } 406 407 cpe++; 408 idx++; 409 } 410} 411 412/* 413 * Dump the contents of the bootstrap class path. 414 */ 415void dvmDumpBootClassPath(void) 416{ 417 dumpClassPath(gDvm.bootClassPath); 418} 419 420/* 421 * Returns "true" if the class path contains the specified path. 422 */ 423bool dvmClassPathContains(const ClassPathEntry* cpe, const char* path) 424{ 425 while (cpe->kind != kCpeLastEntry) { 426 if (strcmp(cpe->fileName, path) == 0) 427 return true; 428 429 cpe++; 430 } 431 return false; 432} 433 434/* 435 * Free an array of ClassPathEntry structs. 436 * 437 * We release the contents of each entry, then free the array itself. 438 */ 439static void freeCpeArray(ClassPathEntry* cpe) 440{ 441 ClassPathEntry* cpeStart = cpe; 442 443 if (cpe == NULL) 444 return; 445 446 while (cpe->kind != kCpeLastEntry) { 447 switch (cpe->kind) { 448 case kCpeJar: 449 /* free JarFile */ 450 dvmJarFileFree((JarFile*) cpe->ptr); 451 break; 452 case kCpeDex: 453 /* free RawDexFile */ 454 dvmRawDexFileFree((RawDexFile*) cpe->ptr); 455 break; 456 default: 457 /* e.g. kCpeDir */ 458 assert(cpe->ptr == NULL); 459 break; 460 } 461 462 free(cpe->fileName); 463 cpe++; 464 } 465 466 free(cpeStart); 467} 468 469/* 470 * Prepare a ClassPathEntry struct, which at this point only has a valid 471 * filename. We need to figure out what kind of file it is, and for 472 * everything other than directories we need to open it up and see 473 * what's inside. 474 */ 475static bool prepareCpe(ClassPathEntry* cpe, bool isBootstrap) 476{ 477 JarFile* pJarFile = NULL; 478 RawDexFile* pRawDexFile = NULL; 479 struct stat sb; 480 int cc; 481 482 cc = stat(cpe->fileName, &sb); 483 if (cc < 0) { 484 LOGW("Unable to stat classpath element '%s'\n", cpe->fileName); 485 return false; 486 } 487 if (S_ISDIR(sb.st_mode)) { 488 /* 489 * The directory will usually have .class files in subdirectories, 490 * which may be a few levels down. Doing a recursive scan and 491 * caching the results would help us avoid hitting the filesystem 492 * on misses. Whether or not this is of measureable benefit 493 * depends on a number of factors, but most likely it is not 494 * worth the effort (especially since most of our stuff will be 495 * in DEX or JAR). 496 */ 497 cpe->kind = kCpeDir; 498 assert(cpe->ptr == NULL); 499 return true; 500 } 501 502 if (dvmJarFileOpen(cpe->fileName, NULL, &pJarFile, isBootstrap) == 0) { 503 cpe->kind = kCpeJar; 504 cpe->ptr = pJarFile; 505 return true; 506 } 507 508 // TODO: do we still want to support "raw" DEX files in the classpath? 509 if (dvmRawDexFileOpen(cpe->fileName, NULL, &pRawDexFile, isBootstrap) == 0) 510 { 511 cpe->kind = kCpeDex; 512 cpe->ptr = pRawDexFile; 513 return true; 514 } 515 516 return false; 517} 518 519/* 520 * Convert a colon-separated list of directories, Zip files, and DEX files 521 * into an array of ClassPathEntry structs. 522 * 523 * If we're unable to load a bootstrap class path entry, we fail. This 524 * is necessary to preserve the dependencies implied by optimized DEX files 525 * (e.g. if the same class appears in multiple places). 526 * 527 * During normal startup we fail if there are no entries, because we won't 528 * get very far without the basic language support classes, but if we're 529 * optimizing a DEX file we allow it. 530 */ 531static ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap) 532{ 533 ClassPathEntry* cpe = NULL; 534 char* mangle; 535 char* cp; 536 const char* end; 537 int idx, count; 538 539 assert(pathStr != NULL); 540 541 mangle = strdup(pathStr); 542 543 /* 544 * Run through and essentially strtok() the string. Get a count of 545 * the #of elements while we're at it. 546 * 547 * If the path was constructed strangely (e.g. ":foo::bar:") this will 548 * over-allocate, which isn't ideal but is mostly harmless. 549 */ 550 count = 1; 551 for (cp = mangle; *cp != '\0'; cp++) { 552 if (*cp == ':') { /* separates two entries */ 553 count++; 554 *cp = '\0'; 555 } 556 } 557 end = cp; 558 559 /* 560 * Allocate storage. We over-alloc by one so we can set an "end" marker. 561 */ 562 cpe = (ClassPathEntry*) calloc(count+1, sizeof(ClassPathEntry)); 563 564 /* 565 * Set the global pointer so the DEX file dependency stuff can find it. 566 */ 567 gDvm.bootClassPath = cpe; 568 569 /* 570 * Go through a second time, pulling stuff out. 571 */ 572 cp = mangle; 573 idx = 0; 574 while (cp < end) { 575 if (*cp == '\0') { 576 /* leading, trailing, or doubled ':'; ignore it */ 577 } else { 578 ClassPathEntry tmp; 579 tmp.kind = kCpeUnknown; 580 tmp.fileName = strdup(cp); 581 tmp.ptr = NULL; 582 583 /* drop an end marker here so DEX loader can walk unfinished list */ 584 cpe[idx].kind = kCpeLastEntry; 585 cpe[idx].fileName = NULL; 586 cpe[idx].ptr = NULL; 587 588 if (!prepareCpe(&tmp, isBootstrap)) { 589 LOGD("Failed on '%s' (boot=%d)\n", tmp.fileName, isBootstrap); 590 /* drop from list and continue on */ 591 free(tmp.fileName); 592 593 if (isBootstrap || gDvm.optimizing) { 594 /* if boot path entry or we're optimizing, this is fatal */ 595 free(cpe); 596 cpe = NULL; 597 goto bail; 598 } 599 } else { 600 /* copy over, pointers and all */ 601 if (tmp.fileName[0] != '/') 602 LOGW("Non-absolute bootclasspath entry '%s'\n", 603 tmp.fileName); 604 cpe[idx] = tmp; 605 idx++; 606 } 607 } 608 609 cp += strlen(cp) +1; 610 } 611 assert(idx <= count); 612 if (idx == 0 && !gDvm.optimizing) { 613 LOGE("ERROR: no valid entries found in bootclasspath '%s'\n", pathStr); 614 free(cpe); 615 cpe = NULL; 616 goto bail; 617 } 618 619 LOGVV(" (filled %d of %d slots)\n", idx, count); 620 621 /* put end marker in over-alloc slot */ 622 cpe[idx].kind = kCpeLastEntry; 623 cpe[idx].fileName = NULL; 624 cpe[idx].ptr = NULL; 625 626 //dumpClassPath(cpe); 627 628bail: 629 free(mangle); 630 gDvm.bootClassPath = cpe; 631 return cpe; 632} 633 634/* 635 * Search the DEX files we loaded from the bootstrap class path for a DEX 636 * file that has the class with the matching descriptor. 637 * 638 * Returns the matching DEX file and DexClassDef entry if found, otherwise 639 * returns NULL. 640 */ 641static DvmDex* searchBootPathForClass(const char* descriptor, 642 const DexClassDef** ppClassDef) 643{ 644 const ClassPathEntry* cpe = gDvm.bootClassPath; 645 const DexClassDef* pFoundDef = NULL; 646 DvmDex* pFoundFile = NULL; 647 648 LOGVV("+++ class '%s' not yet loaded, scanning bootclasspath...\n", 649 descriptor); 650 651 while (cpe->kind != kCpeLastEntry) { 652 //LOGV("+++ checking '%s' (%d)\n", cpe->fileName, cpe->kind); 653 654 switch (cpe->kind) { 655 case kCpeDir: 656 LOGW("Directory entries ('%s') not supported in bootclasspath\n", 657 cpe->fileName); 658 break; 659 case kCpeJar: 660 { 661 JarFile* pJarFile = (JarFile*) cpe->ptr; 662 const DexClassDef* pClassDef; 663 DvmDex* pDvmDex; 664 665 pDvmDex = dvmGetJarFileDex(pJarFile); 666 pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor); 667 if (pClassDef != NULL) { 668 /* found */ 669 pFoundDef = pClassDef; 670 pFoundFile = pDvmDex; 671 goto found; 672 } 673 } 674 break; 675 case kCpeDex: 676 { 677 RawDexFile* pRawDexFile = (RawDexFile*) cpe->ptr; 678 const DexClassDef* pClassDef; 679 DvmDex* pDvmDex; 680 681 pDvmDex = dvmGetRawDexFileDex(pRawDexFile); 682 pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor); 683 if (pClassDef != NULL) { 684 /* found */ 685 pFoundDef = pClassDef; 686 pFoundFile = pDvmDex; 687 goto found; 688 } 689 } 690 break; 691 default: 692 LOGE("Unknown kind %d\n", cpe->kind); 693 assert(false); 694 break; 695 } 696 697 cpe++; 698 } 699 700 /* 701 * Special handling during verification + optimization. 702 * 703 * The DEX optimizer needs to load classes from the DEX file it's working 704 * on. Rather than trying to insert it into the bootstrap class path 705 * or synthesizing a class loader to manage it, we just make it available 706 * here. It logically comes after all existing entries in the bootstrap 707 * class path. 708 */ 709 if (gDvm.bootClassPathOptExtra != NULL) { 710 const DexClassDef* pClassDef; 711 712 pClassDef = 713 dexFindClass(gDvm.bootClassPathOptExtra->pDexFile, descriptor); 714 if (pClassDef != NULL) { 715 /* found */ 716 pFoundDef = pClassDef; 717 pFoundFile = gDvm.bootClassPathOptExtra; 718 } 719 } 720 721found: 722 *ppClassDef = pFoundDef; 723 return pFoundFile; 724} 725 726/* 727 * Set the "extra" DEX, which becomes a de facto member of the bootstrap 728 * class set. 729 */ 730void dvmSetBootPathExtraDex(DvmDex* pDvmDex) 731{ 732 gDvm.bootClassPathOptExtra = pDvmDex; 733} 734 735 736/* 737 * Return the #of entries in the bootstrap class path. 738 * 739 * (Used for ClassLoader.getResources().) 740 */ 741int dvmGetBootPathSize(void) 742{ 743 const ClassPathEntry* cpe = gDvm.bootClassPath; 744 745 while (cpe->kind != kCpeLastEntry) 746 cpe++; 747 748 return cpe - gDvm.bootClassPath; 749} 750 751/* 752 * Find a resource with the specified name in entry N of the boot class path. 753 * 754 * We return a newly-allocated String of one of these forms: 755 * file://path/name 756 * jar:file://path!/name 757 * Where "path" is the bootstrap class path entry and "name" is the string 758 * passed into this method. "path" needs to be an absolute path (starting 759 * with '/'); if it's not we'd need to "absolutify" it as part of forming 760 * the URL string. 761 */ 762StringObject* dvmGetBootPathResource(const char* name, int idx) 763{ 764 const int kUrlOverhead = 13; // worst case for Jar URL 765 const ClassPathEntry* cpe = gDvm.bootClassPath; 766 StringObject* urlObj = NULL; 767 768 LOGV("+++ searching for resource '%s' in %d(%s)\n", 769 name, idx, cpe[idx].fileName); 770 771 /* we could use direct array index, but I don't entirely trust "idx" */ 772 while (idx-- && cpe->kind != kCpeLastEntry) 773 cpe++; 774 if (cpe->kind == kCpeLastEntry) { 775 assert(false); 776 return NULL; 777 } 778 779 char urlBuf[strlen(name) + strlen(cpe->fileName) + kUrlOverhead +1]; 780 781 switch (cpe->kind) { 782 case kCpeDir: 783 sprintf(urlBuf, "file://%s/%s", cpe->fileName, name); 784 if (access(urlBuf+7, F_OK) != 0) 785 goto bail; 786 break; 787 case kCpeJar: 788 { 789 JarFile* pJarFile = (JarFile*) cpe->ptr; 790 if (dexZipFindEntry(&pJarFile->archive, name) == NULL) 791 goto bail; 792 sprintf(urlBuf, "jar:file://%s!/%s", cpe->fileName, name); 793 } 794 break; 795 case kCpeDex: 796 LOGV("No resources in DEX files\n"); 797 goto bail; 798 default: 799 assert(false); 800 goto bail; 801 } 802 803 LOGV("+++ using URL='%s'\n", urlBuf); 804 urlObj = dvmCreateStringFromCstr(urlBuf, ALLOC_DEFAULT); 805 806bail: 807 return urlObj; 808} 809 810 811/* 812 * =========================================================================== 813 * Class list management 814 * =========================================================================== 815 */ 816 817/* search for these criteria in the Class hash table */ 818typedef struct ClassMatchCriteria { 819 const char* descriptor; 820 Object* loader; 821} ClassMatchCriteria; 822 823#define kInitLoaderInc 4 /* must be power of 2 */ 824 825static InitiatingLoaderList *dvmGetInitiatingLoaderList(ClassObject* clazz) 826{ 827 assert(clazz->serialNumber > INITIAL_CLASS_SERIAL_NUMBER); 828 int classIndex = clazz->serialNumber-INITIAL_CLASS_SERIAL_NUMBER; 829 if (gDvm.initiatingLoaderList != NULL && 830 classIndex < ZYGOTE_CLASS_CUTOFF) { 831 return &(gDvm.initiatingLoaderList[classIndex]); 832 } else { 833 return &(clazz->initiatingLoaderList); 834 } 835} 836 837/* 838 * Determine if "loader" appears in clazz' initiating loader list. 839 * 840 * The class hash table lock must be held when calling here, since 841 * it's also used when updating a class' initiating loader list. 842 * 843 * TODO: switch to some sort of lock-free data structure so we don't have 844 * to grab the lock to do a lookup. Among other things, this would improve 845 * the speed of compareDescriptorClasses(). 846 */ 847bool dvmLoaderInInitiatingList(const ClassObject* clazz, const Object* loader) 848{ 849 /* 850 * The bootstrap class loader can't be just an initiating loader for 851 * anything (it's always the defining loader if the class is visible 852 * to it). We don't put defining loaders in the initiating list. 853 */ 854 if (loader == NULL) 855 return false; 856 857 /* 858 * Scan the list for a match. The list is expected to be short. 859 */ 860 /* Cast to remove the const from clazz, but use const loaderList */ 861 ClassObject* nonConstClazz = (ClassObject*) clazz; 862 const InitiatingLoaderList *loaderList = 863 dvmGetInitiatingLoaderList(nonConstClazz); 864 int i; 865 for (i = loaderList->initiatingLoaderCount-1; i >= 0; --i) { 866 if (loaderList->initiatingLoaders[i] == loader) { 867 //LOGI("+++ found initiating match %p in %s\n", 868 // loader, clazz->descriptor); 869 return true; 870 } 871 } 872 return false; 873} 874 875/* 876 * Add "loader" to clazz's initiating loader set, unless it's the defining 877 * class loader. 878 * 879 * In the common case this will be a short list, so we don't need to do 880 * anything too fancy here. 881 * 882 * This locks gDvm.loadedClasses for synchronization, so don't hold it 883 * when calling here. 884 */ 885void dvmAddInitiatingLoader(ClassObject* clazz, Object* loader) 886{ 887 if (loader != clazz->classLoader) { 888 assert(loader != NULL); 889 890 LOGVV("Adding %p to '%s' init list\n", loader, clazz->descriptor); 891 dvmHashTableLock(gDvm.loadedClasses); 892 893 /* 894 * Make sure nobody snuck in. The penalty for adding twice is 895 * pretty minor, and probably outweighs the O(n^2) hit for 896 * checking before every add, so we may not want to do this. 897 */ 898 //if (dvmLoaderInInitiatingList(clazz, loader)) { 899 // LOGW("WOW: simultaneous add of initiating class loader\n"); 900 // goto bail_unlock; 901 //} 902 903 /* 904 * The list never shrinks, so we just keep a count of the 905 * number of elements in it, and reallocate the buffer when 906 * we run off the end. 907 * 908 * The pointer is initially NULL, so we *do* want to call realloc 909 * when count==0. 910 */ 911 InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz); 912 if ((loaderList->initiatingLoaderCount & (kInitLoaderInc-1)) == 0) { 913 Object** newList; 914 915 newList = (Object**) realloc(loaderList->initiatingLoaders, 916 (loaderList->initiatingLoaderCount + kInitLoaderInc) 917 * sizeof(Object*)); 918 if (newList == NULL) { 919 /* this is mainly a cache, so it's not the EotW */ 920 assert(false); 921 goto bail_unlock; 922 } 923 loaderList->initiatingLoaders = newList; 924 925 //LOGI("Expanded init list to %d (%s)\n", 926 // loaderList->initiatingLoaderCount+kInitLoaderInc, 927 // clazz->descriptor); 928 } 929 loaderList->initiatingLoaders[loaderList->initiatingLoaderCount++] = 930 loader; 931 932bail_unlock: 933 dvmHashTableUnlock(gDvm.loadedClasses); 934 } 935} 936 937/* 938 * (This is a dvmHashTableLookup callback.) 939 * 940 * Entries in the class hash table are stored as { descriptor, d-loader } 941 * tuples. If the hashed class descriptor matches the requested descriptor, 942 * and the hashed defining class loader matches the requested class 943 * loader, we're good. If only the descriptor matches, we check to see if the 944 * loader is in the hashed class' initiating loader list. If so, we 945 * can return "true" immediately and skip some of the loadClass melodrama. 946 * 947 * The caller must lock the hash table before calling here. 948 * 949 * Returns 0 if a matching entry is found, nonzero otherwise. 950 */ 951static int hashcmpClassByCrit(const void* vclazz, const void* vcrit) 952{ 953 const ClassObject* clazz = (const ClassObject*) vclazz; 954 const ClassMatchCriteria* pCrit = (const ClassMatchCriteria*) vcrit; 955 bool match; 956 957 match = (strcmp(clazz->descriptor, pCrit->descriptor) == 0 && 958 (clazz->classLoader == pCrit->loader || 959 (pCrit->loader != NULL && 960 dvmLoaderInInitiatingList(clazz, pCrit->loader)) )); 961 //if (match) 962 // LOGI("+++ %s %p matches existing %s %p\n", 963 // pCrit->descriptor, pCrit->loader, 964 // clazz->descriptor, clazz->classLoader); 965 return !match; 966} 967 968/* 969 * Like hashcmpClassByCrit, but passing in a fully-formed ClassObject 970 * instead of a ClassMatchCriteria. 971 */ 972static int hashcmpClassByClass(const void* vclazz, const void* vaddclazz) 973{ 974 const ClassObject* clazz = (const ClassObject*) vclazz; 975 const ClassObject* addClazz = (const ClassObject*) vaddclazz; 976 bool match; 977 978 match = (strcmp(clazz->descriptor, addClazz->descriptor) == 0 && 979 (clazz->classLoader == addClazz->classLoader || 980 (addClazz->classLoader != NULL && 981 dvmLoaderInInitiatingList(clazz, addClazz->classLoader)) )); 982 return !match; 983} 984 985/* 986 * Search through the hash table to find an entry with a matching descriptor 987 * and an initiating class loader that matches "loader". 988 * 989 * The table entries are hashed on descriptor only, because they're unique 990 * on *defining* class loader, not *initiating* class loader. This isn't 991 * great, because it guarantees we will have to probe when multiple 992 * class loaders are used. 993 * 994 * Note this does NOT try to load a class; it just finds a class that 995 * has already been loaded. 996 * 997 * If "unprepOkay" is set, this will return classes that have been added 998 * to the hash table but are not yet fully loaded and linked. Otherwise, 999 * such classes are ignored. (The only place that should set "unprepOkay" 1000 * is findClassNoInit(), which will wait for the prep to finish.) 1001 * 1002 * Returns NULL if not found. 1003 */ 1004ClassObject* dvmLookupClass(const char* descriptor, Object* loader, 1005 bool unprepOkay) 1006{ 1007 ClassMatchCriteria crit; 1008 void* found; 1009 u4 hash; 1010 1011 crit.descriptor = descriptor; 1012 crit.loader = loader; 1013 hash = dvmComputeUtf8Hash(descriptor); 1014 1015 LOGVV("threadid=%d: dvmLookupClass searching for '%s' %p\n", 1016 dvmThreadSelf()->threadId, descriptor, loader); 1017 1018 dvmHashTableLock(gDvm.loadedClasses); 1019 found = dvmHashTableLookup(gDvm.loadedClasses, hash, &crit, 1020 hashcmpClassByCrit, false); 1021 dvmHashTableUnlock(gDvm.loadedClasses); 1022 1023 /* 1024 * The class has been added to the hash table but isn't ready for use. 1025 * We're going to act like we didn't see it, so that the caller will 1026 * go through the full "find class" path, which includes locking the 1027 * object and waiting until it's ready. We could do that lock/wait 1028 * here, but this is an extremely rare case, and it's simpler to have 1029 * the wait-for-class code centralized. 1030 */ 1031 if (found != NULL && !unprepOkay && !dvmIsClassLinked(found)) { 1032 LOGV("Ignoring not-yet-ready %s, using slow path\n", 1033 ((ClassObject*)found)->descriptor); 1034 found = NULL; 1035 } 1036 1037 return (ClassObject*) found; 1038} 1039 1040/* 1041 * Add a new class to the hash table. 1042 * 1043 * The class is considered "new" if it doesn't match on both the class 1044 * descriptor and the defining class loader. 1045 * 1046 * TODO: we should probably have separate hash tables for each 1047 * ClassLoader. This could speed up dvmLookupClass and 1048 * other common operations. It does imply a VM-visible data structure 1049 * for each ClassLoader object with loaded classes, which we don't 1050 * have yet. 1051 */ 1052bool dvmAddClassToHash(ClassObject* clazz) 1053{ 1054 void* found; 1055 u4 hash; 1056 1057 hash = dvmComputeUtf8Hash(clazz->descriptor); 1058 1059 dvmHashTableLock(gDvm.loadedClasses); 1060 found = dvmHashTableLookup(gDvm.loadedClasses, hash, clazz, 1061 hashcmpClassByClass, true); 1062 dvmHashTableUnlock(gDvm.loadedClasses); 1063 1064 LOGV("+++ dvmAddClassToHash '%s' %p (isnew=%d) --> %p\n", 1065 clazz->descriptor, clazz->classLoader, 1066 (found == (void*) clazz), clazz); 1067 1068 //dvmCheckClassTablePerf(); 1069 1070 /* can happen if two threads load the same class simultaneously */ 1071 return (found == (void*) clazz); 1072} 1073 1074#if 0 1075/* 1076 * Compute hash value for a class. 1077 */ 1078u4 hashcalcClass(const void* item) 1079{ 1080 return dvmComputeUtf8Hash(((const ClassObject*) item)->descriptor); 1081} 1082 1083/* 1084 * Check the performance of the "loadedClasses" hash table. 1085 */ 1086void dvmCheckClassTablePerf(void) 1087{ 1088 dvmHashTableLock(gDvm.loadedClasses); 1089 dvmHashTableProbeCount(gDvm.loadedClasses, hashcalcClass, 1090 hashcmpClassByClass); 1091 dvmHashTableUnlock(gDvm.loadedClasses); 1092} 1093#endif 1094 1095/* 1096 * Remove a class object from the hash table. 1097 */ 1098static void removeClassFromHash(ClassObject* clazz) 1099{ 1100 LOGV("+++ removeClassFromHash '%s'\n", clazz->descriptor); 1101 1102 u4 hash = dvmComputeUtf8Hash(clazz->descriptor); 1103 1104 dvmHashTableLock(gDvm.loadedClasses); 1105 if (!dvmHashTableRemove(gDvm.loadedClasses, hash, clazz)) 1106 LOGW("Hash table remove failed on class '%s'\n", clazz->descriptor); 1107 dvmHashTableUnlock(gDvm.loadedClasses); 1108} 1109 1110 1111/* 1112 * =========================================================================== 1113 * Class creation 1114 * =========================================================================== 1115 */ 1116 1117/* 1118 * Set clazz->serialNumber to the next available value. 1119 * 1120 * This usually happens *very* early in class creation, so don't expect 1121 * anything else in the class to be ready. 1122 */ 1123void dvmSetClassSerialNumber(ClassObject* clazz) 1124{ 1125 u4 oldValue, newValue; 1126 1127 assert(clazz->serialNumber == 0); 1128 1129 do { 1130 oldValue = gDvm.classSerialNumber; 1131 newValue = oldValue + 1; 1132 } while (!ATOMIC_CMP_SWAP(&gDvm.classSerialNumber, oldValue, newValue)); 1133 1134 clazz->serialNumber = (u4) oldValue; 1135} 1136 1137 1138/* 1139 * Find the named class (by descriptor), using the specified 1140 * initiating ClassLoader. 1141 * 1142 * The class will be loaded and initialized if it has not already been. 1143 * If necessary, the superclass will be loaded. 1144 * 1145 * If the class can't be found, returns NULL with an appropriate exception 1146 * raised. 1147 */ 1148ClassObject* dvmFindClass(const char* descriptor, Object* loader) 1149{ 1150 ClassObject* clazz; 1151 1152 clazz = dvmFindClassNoInit(descriptor, loader); 1153 if (clazz != NULL && clazz->status < CLASS_INITIALIZED) { 1154 /* initialize class */ 1155 if (!dvmInitClass(clazz)) { 1156 /* init failed; leave it in the list, marked as bad */ 1157 assert(dvmCheckException(dvmThreadSelf())); 1158 assert(clazz->status == CLASS_ERROR); 1159 return NULL; 1160 } 1161 } 1162 1163 return clazz; 1164} 1165 1166/* 1167 * Find the named class (by descriptor), using the specified 1168 * initiating ClassLoader. 1169 * 1170 * The class will be loaded if it has not already been, as will its 1171 * superclass. It will not be initialized. 1172 * 1173 * If the class can't be found, returns NULL with an appropriate exception 1174 * raised. 1175 */ 1176ClassObject* dvmFindClassNoInit(const char* descriptor, 1177 Object* loader) 1178{ 1179 assert(descriptor != NULL); 1180 //assert(loader != NULL); 1181 1182 LOGVV("FindClassNoInit '%s' %p\n", descriptor, loader); 1183 1184 if (*descriptor == '[') { 1185 /* 1186 * Array class. Find in table, generate if not found. 1187 */ 1188 return dvmFindArrayClass(descriptor, loader); 1189 } else { 1190 /* 1191 * Regular class. Find in table, load if not found. 1192 */ 1193 if (loader != NULL) { 1194 return findClassFromLoaderNoInit(descriptor, loader); 1195 } else { 1196 return dvmFindSystemClassNoInit(descriptor); 1197 } 1198 } 1199} 1200 1201/* 1202 * Load the named class (by descriptor) from the specified class 1203 * loader. This calls out to let the ClassLoader object do its thing. 1204 * 1205 * Returns with NULL and an exception raised on error. 1206 */ 1207static ClassObject* findClassFromLoaderNoInit(const char* descriptor, 1208 Object* loader) 1209{ 1210 //LOGI("##### findClassFromLoaderNoInit (%s,%p)\n", 1211 // descriptor, loader); 1212 1213 Thread* self = dvmThreadSelf(); 1214 ClassObject* clazz; 1215 1216 assert(loader != NULL); 1217 1218 /* 1219 * Do we already have it? 1220 * 1221 * The class loader code does the "is it already loaded" check as 1222 * well. However, this call is much faster than calling through 1223 * interpreted code. Doing this does mean that in the common case 1224 * (365 out of 420 calls booting the sim) we're doing the 1225 * lookup-by-descriptor twice. It appears this is still a win, so 1226 * I'm keeping it in. 1227 */ 1228 clazz = dvmLookupClass(descriptor, loader, false); 1229 if (clazz != NULL) { 1230 LOGVV("Already loaded: %s %p\n", descriptor, loader); 1231 return clazz; 1232 } else { 1233 LOGVV("Not already loaded: %s %p\n", descriptor, loader); 1234 } 1235 1236 char* dotName = NULL; 1237 StringObject* nameObj = NULL; 1238 Object* excep; 1239 Method* loadClass; 1240 1241 /* convert "Landroid/debug/Stuff;" to "android.debug.Stuff" */ 1242 dotName = dvmDescriptorToDot(descriptor); 1243 if (dotName == NULL) { 1244 dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL); 1245 goto bail; 1246 } 1247 nameObj = dvmCreateStringFromCstr(dotName, ALLOC_DEFAULT); 1248 if (nameObj == NULL) { 1249 assert(dvmCheckException(self)); 1250 goto bail; 1251 } 1252 1253 // TODO: cache the vtable offset 1254 loadClass = dvmFindVirtualMethodHierByDescriptor(loader->clazz, "loadClass", 1255 "(Ljava/lang/String;)Ljava/lang/Class;"); 1256 if (loadClass == NULL) { 1257 LOGW("Couldn't find loadClass in ClassLoader\n"); 1258 goto bail; 1259 } 1260 1261#ifdef WITH_PROFILER 1262 dvmMethodTraceClassPrepBegin(); 1263#endif 1264 1265 /* 1266 * Invoke loadClass(). This will probably result in a couple of 1267 * exceptions being thrown, because the ClassLoader.loadClass() 1268 * implementation eventually calls VMClassLoader.loadClass to see if 1269 * the bootstrap class loader can find it before doing its own load. 1270 */ 1271 LOGVV("--- Invoking loadClass(%s, %p)\n", dotName, loader); 1272 JValue result; 1273 dvmCallMethod(self, loadClass, loader, &result, nameObj); 1274 clazz = (ClassObject*) result.l; 1275 1276#ifdef WITH_PROFILER 1277 dvmMethodTraceClassPrepEnd(); 1278#endif 1279 1280 excep = dvmGetException(self); 1281 if (excep != NULL) { 1282#if DVM_SHOW_EXCEPTION >= 2 1283 LOGD("NOTE: loadClass '%s' %p threw exception %s\n", 1284 dotName, loader, excep->clazz->descriptor); 1285#endif 1286 dvmAddTrackedAlloc(excep, self); 1287 dvmClearException(self); 1288 dvmThrowChainedExceptionWithClassMessage( 1289 "Ljava/lang/NoClassDefFoundError;", descriptor, excep); 1290 dvmReleaseTrackedAlloc(excep, self); 1291 clazz = NULL; 1292 goto bail; 1293 } else { 1294 assert(clazz != NULL); 1295 } 1296 1297 dvmAddInitiatingLoader(clazz, loader); 1298 1299 LOGVV("--- Successfully loaded %s %p (thisldr=%p clazz=%p)\n", 1300 descriptor, clazz->classLoader, loader, clazz); 1301 1302bail: 1303 dvmReleaseTrackedAlloc((Object*)nameObj, NULL); 1304 free(dotName); 1305 return clazz; 1306} 1307 1308/* 1309 * Load the named class (by descriptor) from the specified DEX file. 1310 * Used by class loaders to instantiate a class object from a 1311 * VM-managed DEX. 1312 */ 1313ClassObject* dvmDefineClass(DvmDex* pDvmDex, const char* descriptor, 1314 Object* classLoader) 1315{ 1316 assert(pDvmDex != NULL); 1317 1318 return findClassNoInit(descriptor, classLoader, pDvmDex); 1319} 1320 1321 1322/* 1323 * Find the named class (by descriptor), scanning through the 1324 * bootclasspath if it hasn't already been loaded. 1325 * 1326 * "descriptor" looks like "Landroid/debug/Stuff;". 1327 * 1328 * Uses NULL as the defining class loader. 1329 */ 1330ClassObject* dvmFindSystemClass(const char* descriptor) 1331{ 1332 ClassObject* clazz; 1333 1334 clazz = dvmFindSystemClassNoInit(descriptor); 1335 if (clazz != NULL && clazz->status < CLASS_INITIALIZED) { 1336 /* initialize class */ 1337 if (!dvmInitClass(clazz)) { 1338 /* init failed; leave it in the list, marked as bad */ 1339 assert(dvmCheckException(dvmThreadSelf())); 1340 assert(clazz->status == CLASS_ERROR); 1341 return NULL; 1342 } 1343 } 1344 1345 return clazz; 1346} 1347 1348/* 1349 * Find the named class (by descriptor), searching for it in the 1350 * bootclasspath. 1351 * 1352 * On failure, this returns NULL with an exception raised. 1353 */ 1354ClassObject* dvmFindSystemClassNoInit(const char* descriptor) 1355{ 1356 return findClassNoInit(descriptor, NULL, NULL); 1357} 1358 1359/* 1360 * Find the named class (by descriptor). If it's not already loaded, 1361 * we load it and link it, but don't execute <clinit>. (The VM has 1362 * specific limitations on which events can cause initialization.) 1363 * 1364 * If "pDexFile" is NULL, we will search the bootclasspath for an entry. 1365 * 1366 * On failure, this returns NULL with an exception raised. 1367 * 1368 * TODO: we need to return an indication of whether we loaded the class or 1369 * used an existing definition. If somebody deliberately tries to load a 1370 * class twice in the same class loader, they should get a LinkageError, 1371 * but inadvertent simultaneous class references should "just work". 1372 */ 1373static ClassObject* findClassNoInit(const char* descriptor, Object* loader, 1374 DvmDex* pDvmDex) 1375{ 1376 Thread* self = dvmThreadSelf(); 1377 ClassObject* clazz; 1378#ifdef WITH_PROFILER 1379 bool profilerNotified = false; 1380#endif 1381 1382 if (loader != NULL) { 1383 LOGVV("#### findClassNoInit(%s,%p,%p)\n", descriptor, loader, 1384 pDvmDex->pDexFile); 1385 } 1386 1387 /* 1388 * We don't expect an exception to be raised at this point. The 1389 * exception handling code is good about managing this. This *can* 1390 * happen if a JNI lookup fails and the JNI code doesn't do any 1391 * error checking before doing another class lookup, so we may just 1392 * want to clear this and restore it on exit. If we don't, some kinds 1393 * of failures can't be detected without rearranging other stuff. 1394 * 1395 * Most often when we hit this situation it means that something is 1396 * broken in the VM or in JNI code, so I'm keeping it in place (and 1397 * making it an informative abort rather than an assert). 1398 */ 1399 if (dvmCheckException(self)) { 1400 LOGE("Class lookup %s attemped while exception %s pending\n", 1401 descriptor, dvmGetException(self)->clazz->descriptor); 1402 dvmDumpAllThreads(false); 1403 dvmAbort(); 1404 } 1405 1406 clazz = dvmLookupClass(descriptor, loader, true); 1407 if (clazz == NULL) { 1408 const DexClassDef* pClassDef; 1409 1410#ifdef WITH_PROFILER 1411 dvmMethodTraceClassPrepBegin(); 1412 profilerNotified = true; 1413#endif 1414 1415#if LOG_CLASS_LOADING 1416 u8 startTime = dvmGetThreadCpuTimeNsec(); 1417#endif 1418 1419 if (pDvmDex == NULL) { 1420 assert(loader == NULL); /* shouldn't be here otherwise */ 1421 pDvmDex = searchBootPathForClass(descriptor, &pClassDef); 1422 } else { 1423 pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor); 1424 } 1425 1426 if (pDvmDex == NULL || pClassDef == NULL) { 1427 dvmThrowExceptionWithClassMessage( 1428 "Ljava/lang/NoClassDefFoundError;", descriptor); 1429 goto bail; 1430 } 1431 1432 /* found a match, try to load it */ 1433 clazz = loadClassFromDex(pDvmDex, pClassDef, loader); 1434 if (dvmCheckException(self)) { 1435 /* class was found but had issues */ 1436 dvmReleaseTrackedAlloc((Object*) clazz, NULL); 1437 goto bail; 1438 } 1439 1440 /* 1441 * Lock the class while we link it so other threads must wait for us 1442 * to finish. Set the "initThreadId" so we can identify recursive 1443 * invocation. 1444 */ 1445 dvmLockObject(self, (Object*) clazz); 1446 clazz->initThreadId = self->threadId; 1447 1448 /* 1449 * Add to hash table so lookups succeed. 1450 * 1451 * [Are circular references possible when linking a class?] 1452 */ 1453 assert(clazz->classLoader == loader); 1454 if (!dvmAddClassToHash(clazz)) { 1455 /* 1456 * Another thread must have loaded the class after we 1457 * started but before we finished. Discard what we've 1458 * done and leave some hints for the GC. 1459 * 1460 * (Yes, this happens.) 1461 */ 1462 //LOGW("WOW: somebody loaded %s simultaneously\n", descriptor); 1463 clazz->initThreadId = 0; 1464 dvmUnlockObject(self, (Object*) clazz); 1465 1466 /* Let the GC free the class. 1467 */ 1468 assert(clazz->obj.clazz == gDvm.unlinkedJavaLangClass); 1469 dvmReleaseTrackedAlloc((Object*) clazz, NULL); 1470 1471 /* Grab the winning class. 1472 */ 1473 clazz = dvmLookupClass(descriptor, loader, true); 1474 assert(clazz != NULL); 1475 goto got_class; 1476 } 1477 dvmReleaseTrackedAlloc((Object*) clazz, NULL); 1478 1479#if LOG_CLASS_LOADING 1480 logClassLoadWithTime('>', clazz, startTime); 1481#endif 1482 /* 1483 * Prepare and resolve. 1484 */ 1485 if (!dvmLinkClass(clazz, false)) { 1486 assert(dvmCheckException(self)); 1487 1488 /* Make note of the error and clean up the class. 1489 */ 1490 removeClassFromHash(clazz); 1491 clazz->status = CLASS_ERROR; 1492 dvmFreeClassInnards(clazz); 1493 1494 /* Let any waiters know. 1495 */ 1496 clazz->initThreadId = 0; 1497 dvmObjectNotifyAll(self, (Object*) clazz); 1498 dvmUnlockObject(self, (Object*) clazz); 1499 1500#if LOG_CLASS_LOADING 1501 LOG(LOG_INFO, "DVMLINK FAILED FOR CLASS ", "%s in %s\n", 1502 clazz->descriptor, get_process_name()); 1503 1504 /* 1505 * TODO: It would probably be better to use a new type code here (instead of '<') to 1506 * indicate the failure. This change would require a matching change in the parser 1507 * and analysis code in frameworks/base/tools/preload. 1508 */ 1509 logClassLoad('<', clazz); 1510#endif 1511 clazz = NULL; 1512 if (gDvm.optimizing) { 1513 /* happens with "external" libs */ 1514 LOGV("Link of class '%s' failed\n", descriptor); 1515 } else { 1516 LOGW("Link of class '%s' failed\n", descriptor); 1517 } 1518 goto bail; 1519 } 1520 dvmObjectNotifyAll(self, (Object*) clazz); 1521 dvmUnlockObject(self, (Object*) clazz); 1522 1523 /* 1524 * Add class stats to global counters. 1525 * 1526 * TODO: these should probably be atomic ops. 1527 */ 1528 gDvm.numLoadedClasses++; 1529 gDvm.numDeclaredMethods += 1530 clazz->virtualMethodCount + clazz->directMethodCount; 1531 gDvm.numDeclaredInstFields += clazz->ifieldCount; 1532 gDvm.numDeclaredStaticFields += clazz->sfieldCount; 1533 1534 /* 1535 * Cache pointers to basic classes. We want to use these in 1536 * various places, and it's easiest to initialize them on first 1537 * use rather than trying to force them to initialize (startup 1538 * ordering makes it weird). 1539 */ 1540 if (gDvm.classJavaLangObject == NULL && 1541 strcmp(descriptor, "Ljava/lang/Object;") == 0) 1542 { 1543 /* It should be impossible to get here with anything 1544 * but the bootclasspath loader. 1545 */ 1546 assert(loader == NULL); 1547 gDvm.classJavaLangObject = clazz; 1548 } 1549 1550#if LOG_CLASS_LOADING 1551 logClassLoad('<', clazz); 1552#endif 1553 1554 } else { 1555got_class: 1556 if (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) { 1557 /* 1558 * We can race with other threads for class linking. We should 1559 * never get here recursively; doing so indicates that two 1560 * classes have circular dependencies. 1561 * 1562 * One exception: we force discovery of java.lang.Class in 1563 * dvmLinkClass(), and Class has Object as its superclass. So 1564 * if the first thing we ever load is Object, we will init 1565 * Object->Class->Object. The easiest way to avoid this is to 1566 * ensure that Object is never the first thing we look up, so 1567 * we get Foo->Class->Object instead. 1568 */ 1569 dvmLockObject(self, (Object*) clazz); 1570 if (!dvmIsClassLinked(clazz) && 1571 clazz->initThreadId == self->threadId) 1572 { 1573 LOGW("Recursive link on class %s\n", clazz->descriptor); 1574 dvmUnlockObject(self, (Object*) clazz); 1575 dvmThrowExceptionWithClassMessage( 1576 "Ljava/lang/ClassCircularityError;", clazz->descriptor); 1577 clazz = NULL; 1578 goto bail; 1579 } 1580 //LOGI("WAITING for '%s' (owner=%d)\n", 1581 // clazz->descriptor, clazz->initThreadId); 1582 while (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) { 1583 dvmObjectWait(self, (Object*) clazz, 0, 0, false); 1584 } 1585 dvmUnlockObject(self, (Object*) clazz); 1586 } 1587 if (clazz->status == CLASS_ERROR) { 1588 /* 1589 * Somebody else tried to load this and failed. We need to raise 1590 * an exception and report failure. 1591 */ 1592 throwEarlierClassFailure(clazz); 1593 clazz = NULL; 1594 goto bail; 1595 } 1596 } 1597 1598 /* check some invariants */ 1599 assert(dvmIsClassLinked(clazz)); 1600 assert(gDvm.classJavaLangClass != NULL); 1601 assert(clazz->obj.clazz == gDvm.classJavaLangClass); 1602 if (clazz != gDvm.classJavaLangObject) { 1603 if (clazz->super == NULL) { 1604 LOGE("Non-Object has no superclass (gDvm.classJavaLangObject=%p)\n", 1605 gDvm.classJavaLangObject); 1606 dvmAbort(); 1607 } 1608 } 1609 if (!dvmIsInterfaceClass(clazz)) { 1610 //LOGI("class=%s vtableCount=%d, virtualMeth=%d\n", 1611 // clazz->descriptor, clazz->vtableCount, 1612 // clazz->virtualMethodCount); 1613 assert(clazz->vtableCount >= clazz->virtualMethodCount); 1614 } 1615 1616 /* 1617 * Normally class objects are initialized before we instantiate them, 1618 * but we can't do that with java.lang.Class (chicken, meet egg). We 1619 * do it explicitly here. 1620 * 1621 * The verifier could call here to find Class while verifying Class, 1622 * so we need to check for CLASS_VERIFYING as well as !initialized. 1623 */ 1624 if (clazz == gDvm.classJavaLangClass && !dvmIsClassInitialized(clazz) && 1625 !(clazz->status == CLASS_VERIFYING)) 1626 { 1627 LOGV("+++ explicitly initializing %s\n", clazz->descriptor); 1628 dvmInitClass(clazz); 1629 } 1630 1631bail: 1632#ifdef WITH_PROFILER 1633 if (profilerNotified) 1634 dvmMethodTraceClassPrepEnd(); 1635#endif 1636 assert(clazz != NULL || dvmCheckException(self)); 1637 return clazz; 1638} 1639 1640/* 1641 * Helper for loadClassFromDex, which takes a DexClassDataHeader and 1642 * encoded data pointer in addition to the other arguments. 1643 */ 1644static ClassObject* loadClassFromDex0(DvmDex* pDvmDex, 1645 const DexClassDef* pClassDef, const DexClassDataHeader* pHeader, 1646 const u1* pEncodedData, Object* classLoader) 1647{ 1648 ClassObject* newClass = NULL; 1649 const DexFile* pDexFile; 1650 const char* descriptor; 1651 int i; 1652 1653 pDexFile = pDvmDex->pDexFile; 1654 descriptor = dexGetClassDescriptor(pDexFile, pClassDef); 1655 1656 /* 1657 * Make sure the aren't any "bonus" flags set, since we use them for 1658 * runtime state. 1659 */ 1660 if ((pClassDef->accessFlags & ~EXPECTED_FILE_FLAGS) != 0) { 1661 LOGW("Invalid file flags in class %s: %04x\n", 1662 descriptor, pClassDef->accessFlags); 1663 return NULL; 1664 } 1665 1666 /* 1667 * Allocate storage for the class object on the GC heap, so that other 1668 * objects can have references to it. We bypass the usual mechanism 1669 * (allocObject), because we don't have all the bits and pieces yet. 1670 * 1671 * Note that we assume that java.lang.Class does not override 1672 * finalize(). 1673 */ 1674 newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_DEFAULT); 1675 if (newClass == NULL) 1676 return NULL; 1677 1678 /* Until the class is loaded and linked, use a placeholder 1679 * obj->clazz value as a hint to the GC. We don't want 1680 * the GC trying to scan the object while it's full of Idx 1681 * values. Also, the real java.lang.Class may not exist 1682 * yet. 1683 */ 1684 DVM_OBJECT_INIT(&newClass->obj, gDvm.unlinkedJavaLangClass); 1685 1686 dvmSetClassSerialNumber(newClass); 1687 newClass->descriptor = descriptor; 1688 assert(newClass->descriptorAlloc == NULL); 1689 newClass->accessFlags = pClassDef->accessFlags; 1690 newClass->classLoader = classLoader; 1691 newClass->pDvmDex = pDvmDex; 1692 newClass->primitiveType = PRIM_NOT; 1693 1694 /* 1695 * Stuff the superclass index into the object pointer field. The linker 1696 * pulls it out and replaces it with a resolved ClassObject pointer. 1697 * I'm doing it this way (rather than having a dedicated superclassIdx 1698 * field) to save a few bytes of overhead per class. 1699 * 1700 * newClass->super is not traversed or freed by dvmFreeClassInnards, so 1701 * this is safe. 1702 */ 1703 assert(sizeof(u4) == sizeof(ClassObject*)); 1704 newClass->super = (ClassObject*) pClassDef->superclassIdx; 1705 1706 /* 1707 * Stuff class reference indices into the pointer fields. 1708 * 1709 * The elements of newClass->interfaces are not traversed or freed by 1710 * dvmFreeClassInnards, so this is GC-safe. 1711 */ 1712 const DexTypeList* pInterfacesList; 1713 pInterfacesList = dexGetInterfacesList(pDexFile, pClassDef); 1714 if (pInterfacesList != NULL) { 1715 newClass->interfaceCount = pInterfacesList->size; 1716 newClass->interfaces = (ClassObject**) dvmLinearAlloc(classLoader, 1717 newClass->interfaceCount * sizeof(ClassObject*)); 1718 1719 for (i = 0; i < newClass->interfaceCount; i++) { 1720 const DexTypeItem* pType = dexGetTypeItem(pInterfacesList, i); 1721 newClass->interfaces[i] = (ClassObject*)(u4) pType->typeIdx; 1722 } 1723 dvmLinearReadOnly(classLoader, newClass->interfaces); 1724 } 1725 1726 /* load field definitions */ 1727 1728 /* 1729 * TODO: consider over-allocating the class object and appending the 1730 * static field info onto the end. It's fixed-size and known at alloc 1731 * time. This would save a couple of native heap allocations, but it 1732 * would also make heap compaction more difficult because we pass Field 1733 * pointers around internally. 1734 */ 1735 1736 if (pHeader->staticFieldsSize != 0) { 1737 /* static fields stay on system heap; field data isn't "write once" */ 1738 int count = (int) pHeader->staticFieldsSize; 1739 u4 lastIndex = 0; 1740 DexField field; 1741 1742 newClass->sfieldCount = count; 1743 newClass->sfields = 1744 (StaticField*) calloc(count, sizeof(StaticField)); 1745 for (i = 0; i < count; i++) { 1746 dexReadClassDataField(&pEncodedData, &field, &lastIndex); 1747 loadSFieldFromDex(newClass, &field, &newClass->sfields[i]); 1748 } 1749 } 1750 1751 if (pHeader->instanceFieldsSize != 0) { 1752 int count = (int) pHeader->instanceFieldsSize; 1753 u4 lastIndex = 0; 1754 DexField field; 1755 1756 newClass->ifieldCount = count; 1757 newClass->ifields = (InstField*) dvmLinearAlloc(classLoader, 1758 count * sizeof(InstField)); 1759 for (i = 0; i < count; i++) { 1760 dexReadClassDataField(&pEncodedData, &field, &lastIndex); 1761 loadIFieldFromDex(newClass, &field, &newClass->ifields[i]); 1762 } 1763 dvmLinearReadOnly(classLoader, newClass->ifields); 1764 } 1765 1766 /* load method definitions */ 1767 1768 if (pHeader->directMethodsSize != 0) { 1769 int count = (int) pHeader->directMethodsSize; 1770 u4 lastIndex = 0; 1771 DexMethod method; 1772 1773 newClass->directMethodCount = count; 1774 newClass->directMethods = (Method*) dvmLinearAlloc(classLoader, 1775 count * sizeof(Method)); 1776 for (i = 0; i < count; i++) { 1777 dexReadClassDataMethod(&pEncodedData, &method, &lastIndex); 1778 loadMethodFromDex(newClass, &method, &newClass->directMethods[i]); 1779 } 1780 dvmLinearReadOnly(classLoader, newClass->directMethods); 1781 } 1782 1783 if (pHeader->virtualMethodsSize != 0) { 1784 int count = (int) pHeader->virtualMethodsSize; 1785 u4 lastIndex = 0; 1786 DexMethod method; 1787 1788 newClass->virtualMethodCount = count; 1789 newClass->virtualMethods = (Method*) dvmLinearAlloc(classLoader, 1790 count * sizeof(Method)); 1791 for (i = 0; i < count; i++) { 1792 dexReadClassDataMethod(&pEncodedData, &method, &lastIndex); 1793 loadMethodFromDex(newClass, &method, &newClass->virtualMethods[i]); 1794 } 1795 dvmLinearReadOnly(classLoader, newClass->virtualMethods); 1796 } 1797 1798 newClass->sourceFile = dexGetSourceFile(pDexFile, pClassDef); 1799 newClass->status = CLASS_LOADED; 1800 1801 /* caller must call dvmReleaseTrackedAlloc */ 1802 return newClass; 1803} 1804 1805/* 1806 * Try to load the indicated class from the specified DEX file. 1807 * 1808 * This is effectively loadClass()+defineClass() for a DexClassDef. The 1809 * loading was largely done when we crunched through the DEX. 1810 * 1811 * Returns NULL on failure. If we locate the class but encounter an error 1812 * while processing it, an appropriate exception is thrown. 1813 */ 1814static ClassObject* loadClassFromDex(DvmDex* pDvmDex, 1815 const DexClassDef* pClassDef, Object* classLoader) 1816{ 1817 ClassObject* result; 1818 DexClassDataHeader header; 1819 const u1* pEncodedData; 1820 const DexFile* pDexFile; 1821 1822 assert((pDvmDex != NULL) && (pClassDef != NULL)); 1823 pDexFile = pDvmDex->pDexFile; 1824 1825 if (gDvm.verboseClass) { 1826 LOGV("CLASS: loading '%s'...\n", 1827 dexGetClassDescriptor(pDexFile, pClassDef)); 1828 } 1829 1830 pEncodedData = dexGetClassData(pDexFile, pClassDef); 1831 1832 if (pEncodedData != NULL) { 1833 dexReadClassDataHeader(&pEncodedData, &header); 1834 } else { 1835 // Provide an all-zeroes header for the rest of the loading. 1836 memset(&header, 0, sizeof(header)); 1837 } 1838 1839 result = loadClassFromDex0(pDvmDex, pClassDef, &header, pEncodedData, 1840 classLoader); 1841 1842 if (gDvm.verboseClass && (result != NULL)) { 1843 LOGI("[Loaded %s from DEX %p (cl=%p)]\n", 1844 result->descriptor, pDvmDex, classLoader); 1845 } 1846 1847 return result; 1848} 1849 1850/* 1851 * Free anything in a ClassObject that was allocated on the system heap. 1852 * 1853 * The ClassObject itself is allocated on the GC heap, so we leave it for 1854 * the garbage collector. 1855 * 1856 * NOTE: this may be called with a partially-constructed object. 1857 * NOTE: there is no particular ordering imposed, so don't go poking at 1858 * superclasses. 1859 */ 1860void dvmFreeClassInnards(ClassObject* clazz) 1861{ 1862 void *tp; 1863 int i; 1864 1865 if (clazz == NULL) 1866 return; 1867 1868 assert(clazz->obj.clazz == gDvm.classJavaLangClass || 1869 clazz->obj.clazz == gDvm.unlinkedJavaLangClass); 1870 1871 /* Guarantee that dvmFreeClassInnards can be called on a given 1872 * class multiple times by clearing things out as we free them. 1873 * We don't make any attempt at real atomicity here; higher 1874 * levels need to make sure that no two threads can free the 1875 * same ClassObject at the same time. 1876 * 1877 * TODO: maybe just make it so the GC will never free the 1878 * innards of an already-freed class. 1879 * 1880 * TODO: this #define isn't MT-safe -- the compiler could rearrange it. 1881 */ 1882#define NULL_AND_FREE(p) \ 1883 do { \ 1884 if ((p) != NULL) { \ 1885 tp = (p); \ 1886 (p) = NULL; \ 1887 free(tp); \ 1888 } \ 1889 } while (0) 1890#define NULL_AND_LINEAR_FREE(p) \ 1891 do { \ 1892 if ((p) != NULL) { \ 1893 tp = (p); \ 1894 (p) = NULL; \ 1895 dvmLinearFree(clazz->classLoader, tp); \ 1896 } \ 1897 } while (0) 1898 1899 /* arrays just point at Object's vtable; don't free vtable in this case. 1900 * dvmIsArrayClass() checks clazz->descriptor, so we have to do this check 1901 * before freeing the name. 1902 */ 1903 clazz->vtableCount = -1; 1904 if (dvmIsArrayClass(clazz)) { 1905 clazz->vtable = NULL; 1906 } else { 1907 NULL_AND_LINEAR_FREE(clazz->vtable); 1908 } 1909 1910 clazz->descriptor = NULL; 1911 NULL_AND_FREE(clazz->descriptorAlloc); 1912 1913 if (clazz->directMethods != NULL) { 1914 Method *directMethods = clazz->directMethods; 1915 int directMethodCount = clazz->directMethodCount; 1916 clazz->directMethods = NULL; 1917 clazz->directMethodCount = -1; 1918 for (i = 0; i < directMethodCount; i++) { 1919 freeMethodInnards(&directMethods[i]); 1920 } 1921 dvmLinearFree(clazz->classLoader, directMethods); 1922 } 1923 if (clazz->virtualMethods != NULL) { 1924 Method *virtualMethods = clazz->virtualMethods; 1925 int virtualMethodCount = clazz->virtualMethodCount; 1926 clazz->virtualMethodCount = -1; 1927 clazz->virtualMethods = NULL; 1928 for (i = 0; i < virtualMethodCount; i++) { 1929 freeMethodInnards(&virtualMethods[i]); 1930 } 1931 dvmLinearFree(clazz->classLoader, virtualMethods); 1932 } 1933 1934 InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz); 1935 loaderList->initiatingLoaderCount = -1; 1936 NULL_AND_FREE(loaderList->initiatingLoaders); 1937 1938 clazz->interfaceCount = -1; 1939 NULL_AND_LINEAR_FREE(clazz->interfaces); 1940 1941 clazz->iftableCount = -1; 1942 NULL_AND_LINEAR_FREE(clazz->iftable); 1943 1944 clazz->ifviPoolCount = -1; 1945 NULL_AND_LINEAR_FREE(clazz->ifviPool); 1946 1947 clazz->sfieldCount = -1; 1948 NULL_AND_FREE(clazz->sfields); 1949 1950 clazz->ifieldCount = -1; 1951 NULL_AND_LINEAR_FREE(clazz->ifields); 1952 1953#undef NULL_AND_FREE 1954#undef NULL_AND_LINEAR_FREE 1955} 1956 1957/* 1958 * Free anything in a Method that was allocated on the system heap. 1959 */ 1960static void freeMethodInnards(Method* meth) 1961{ 1962#if 0 1963 free(meth->exceptions); 1964 free(meth->lines); 1965 free(meth->locals); 1966#else 1967 // TODO: call dvmFreeRegisterMap() if meth->registerMap was allocated 1968 // on the system heap 1969 UNUSED_PARAMETER(meth); 1970#endif 1971} 1972 1973/* 1974 * Clone a Method, making new copies of anything that will be freed up 1975 * by freeMethodInnards(). 1976 */ 1977static void cloneMethod(Method* dst, const Method* src) 1978{ 1979 memcpy(dst, src, sizeof(Method)); 1980#if 0 1981 /* for current usage, these are never set, so no need to implement copy */ 1982 assert(dst->exceptions == NULL); 1983 assert(dst->lines == NULL); 1984 assert(dst->locals == NULL); 1985#endif 1986} 1987 1988/* 1989 * Pull the interesting pieces out of a DexMethod. 1990 * 1991 * The DEX file isn't going anywhere, so we don't need to make copies of 1992 * the code area. 1993 */ 1994static void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod, 1995 Method* meth) 1996{ 1997 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 1998 const DexMethodId* pMethodId; 1999 const DexCode* pDexCode; 2000 2001 pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx); 2002 2003 meth->name = dexStringById(pDexFile, pMethodId->nameIdx); 2004 dexProtoSetFromMethodId(&meth->prototype, pDexFile, pMethodId); 2005 meth->shorty = dexProtoGetShorty(&meth->prototype); 2006 meth->accessFlags = pDexMethod->accessFlags; 2007 meth->clazz = clazz; 2008 meth->jniArgInfo = 0; 2009 2010 if (dvmCompareNameDescriptorAndMethod("finalize", "()V", meth) == 0) { 2011 SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE); 2012 } 2013 2014 pDexCode = dexGetCode(pDexFile, pDexMethod); 2015 if (pDexCode != NULL) { 2016 /* integer constants, copy over for faster access */ 2017 meth->registersSize = pDexCode->registersSize; 2018 meth->insSize = pDexCode->insSize; 2019 meth->outsSize = pDexCode->outsSize; 2020 2021 /* pointer to code area */ 2022 meth->insns = pDexCode->insns; 2023 } else { 2024 /* 2025 * We don't have a DexCode block, but we still want to know how 2026 * much space is needed for the arguments (so we don't have to 2027 * compute it later). We also take this opportunity to compute 2028 * JNI argument info. 2029 * 2030 * We do this for abstract methods as well, because we want to 2031 * be able to substitute our exception-throwing "stub" in. 2032 */ 2033 int argsSize = dvmComputeMethodArgsSize(meth); 2034 if (!dvmIsStaticMethod(meth)) 2035 argsSize++; 2036 meth->registersSize = meth->insSize = argsSize; 2037 assert(meth->outsSize == 0); 2038 assert(meth->insns == NULL); 2039 2040 if (dvmIsNativeMethod(meth)) { 2041 meth->nativeFunc = dvmResolveNativeMethod; 2042 meth->jniArgInfo = computeJniArgInfo(&meth->prototype); 2043 } 2044 } 2045} 2046 2047/* 2048 * jniArgInfo (32-bit int) layout: 2049 * SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH 2050 * 2051 * S - if set, do things the hard way (scan the signature) 2052 * R - return-type enumeration 2053 * H - target-specific hints 2054 * 2055 * This info is used at invocation time by dvmPlatformInvoke. In most 2056 * cases, the target-specific hints allow dvmPlatformInvoke to avoid 2057 * having to fully parse the signature. 2058 * 2059 * The return-type bits are always set, even if target-specific hint bits 2060 * are unavailable. 2061 */ 2062static int computeJniArgInfo(const DexProto* proto) 2063{ 2064 const char* sig = dexProtoGetShorty(proto); 2065 int returnType, padFlags, jniArgInfo; 2066 char sigByte; 2067 int stackOffset, padMask; 2068 u4 hints; 2069 2070 /* The first shorty character is the return type. */ 2071 switch (*(sig++)) { 2072 case 'V': 2073 returnType = DALVIK_JNI_RETURN_VOID; 2074 break; 2075 case 'F': 2076 returnType = DALVIK_JNI_RETURN_FLOAT; 2077 break; 2078 case 'D': 2079 returnType = DALVIK_JNI_RETURN_DOUBLE; 2080 break; 2081 case 'J': 2082 returnType = DALVIK_JNI_RETURN_S8; 2083 break; 2084 default: 2085 returnType = DALVIK_JNI_RETURN_S4; 2086 break; 2087 } 2088 2089 jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT; 2090 2091 hints = dvmPlatformInvokeHints(proto); 2092 2093 if (hints & DALVIK_JNI_NO_ARG_INFO) { 2094 jniArgInfo |= DALVIK_JNI_NO_ARG_INFO; 2095 } else { 2096 assert((hints & DALVIK_JNI_RETURN_MASK) == 0); 2097 jniArgInfo |= hints; 2098 } 2099 2100 return jniArgInfo; 2101} 2102 2103/* 2104 * Load information about a static field. 2105 * 2106 * This also "prepares" static fields by initializing them 2107 * to their "standard default values". 2108 */ 2109static void loadSFieldFromDex(ClassObject* clazz, 2110 const DexField* pDexSField, StaticField* sfield) 2111{ 2112 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 2113 const DexFieldId* pFieldId; 2114 2115 pFieldId = dexGetFieldId(pDexFile, pDexSField->fieldIdx); 2116 2117 sfield->field.clazz = clazz; 2118 sfield->field.name = dexStringById(pDexFile, pFieldId->nameIdx); 2119 sfield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx); 2120 sfield->field.accessFlags = pDexSField->accessFlags; 2121 2122 /* Static object field values are set to "standard default values" 2123 * (null or 0) until the class is initialized. We delay loading 2124 * constant values from the class until that time. 2125 */ 2126 //sfield->value.j = 0; 2127 assert(sfield->value.j == 0LL); // cleared earlier with calloc 2128 2129#ifdef PROFILE_FIELD_ACCESS 2130 sfield->field.gets = sfield->field.puts = 0; 2131#endif 2132} 2133 2134/* 2135 * Load information about an instance field. 2136 */ 2137static void loadIFieldFromDex(ClassObject* clazz, 2138 const DexField* pDexIField, InstField* ifield) 2139{ 2140 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 2141 const DexFieldId* pFieldId; 2142 2143 pFieldId = dexGetFieldId(pDexFile, pDexIField->fieldIdx); 2144 2145 ifield->field.clazz = clazz; 2146 ifield->field.name = dexStringById(pDexFile, pFieldId->nameIdx); 2147 ifield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx); 2148 ifield->field.accessFlags = pDexIField->accessFlags; 2149#ifndef NDEBUG 2150 assert(ifield->byteOffset == 0); // cleared earlier with calloc 2151 ifield->byteOffset = -1; // make it obvious if we fail to set later 2152#endif 2153 2154#ifdef PROFILE_FIELD_ACCESS 2155 ifield->field.gets = ifield->field.puts = 0; 2156#endif 2157} 2158 2159/* 2160 * Cache java.lang.ref.Reference fields and methods. 2161 */ 2162static bool precacheReferenceOffsets(ClassObject* clazz) 2163{ 2164 Method *meth; 2165 int i; 2166 2167 /* We trick the GC object scanner by not counting 2168 * java.lang.ref.Reference.referent as an object 2169 * field. It will get explicitly scanned as part 2170 * of the reference-walking process. 2171 * 2172 * Find the object field named "referent" and put it 2173 * just after the list of object reference fields. 2174 */ 2175 dvmLinearReadWrite(clazz->classLoader, clazz->ifields); 2176 for (i = 0; i < clazz->ifieldRefCount; i++) { 2177 InstField *pField = &clazz->ifields[i]; 2178 if (strcmp(pField->field.name, "referent") == 0) { 2179 int targetIndex; 2180 2181 /* Swap this field with the last object field. 2182 */ 2183 targetIndex = clazz->ifieldRefCount - 1; 2184 if (i != targetIndex) { 2185 InstField *swapField = &clazz->ifields[targetIndex]; 2186 InstField tmpField; 2187 int tmpByteOffset; 2188 2189 /* It's not currently strictly necessary 2190 * for the fields to be in byteOffset order, 2191 * but it's more predictable that way. 2192 */ 2193 tmpByteOffset = swapField->byteOffset; 2194 swapField->byteOffset = pField->byteOffset; 2195 pField->byteOffset = tmpByteOffset; 2196 2197 tmpField = *swapField; 2198 *swapField = *pField; 2199 *pField = tmpField; 2200 } 2201 2202 /* One fewer object field (wink wink). 2203 */ 2204 clazz->ifieldRefCount--; 2205 i--; /* don't trip "didn't find it" test if field was last */ 2206 break; 2207 } 2208 } 2209 dvmLinearReadOnly(clazz->classLoader, clazz->ifields); 2210 if (i == clazz->ifieldRefCount) { 2211 LOGE("Unable to reorder 'referent' in %s\n", clazz->descriptor); 2212 return false; 2213 } 2214 2215 /* Cache pretty much everything about Reference so that 2216 * we don't need to call interpreted code when clearing/enqueueing 2217 * references. This is fragile, so we'll be paranoid. 2218 */ 2219 gDvm.classJavaLangRefReference = clazz; 2220 2221 gDvm.offJavaLangRefReference_referent = 2222 dvmFindFieldOffset(gDvm.classJavaLangRefReference, 2223 "referent", "Ljava/lang/Object;"); 2224 assert(gDvm.offJavaLangRefReference_referent >= 0); 2225 2226 gDvm.offJavaLangRefReference_queue = 2227 dvmFindFieldOffset(gDvm.classJavaLangRefReference, 2228 "queue", "Ljava/lang/ref/ReferenceQueue;"); 2229 assert(gDvm.offJavaLangRefReference_queue >= 0); 2230 2231 gDvm.offJavaLangRefReference_queueNext = 2232 dvmFindFieldOffset(gDvm.classJavaLangRefReference, 2233 "queueNext", "Ljava/lang/ref/Reference;"); 2234 assert(gDvm.offJavaLangRefReference_queueNext >= 0); 2235 2236 gDvm.offJavaLangRefReference_vmData = 2237 dvmFindFieldOffset(gDvm.classJavaLangRefReference, 2238 "vmData", "I"); 2239 assert(gDvm.offJavaLangRefReference_vmData >= 0); 2240 2241#if FANCY_REFERENCE_SUBCLASS 2242 meth = dvmFindVirtualMethodByDescriptor(clazz, "clear", "()V"); 2243 assert(meth != NULL); 2244 gDvm.voffJavaLangRefReference_clear = meth->methodIndex; 2245 2246 meth = dvmFindVirtualMethodByDescriptor(clazz, "enqueue", "()Z"); 2247 assert(meth != NULL); 2248 gDvm.voffJavaLangRefReference_enqueue = meth->methodIndex; 2249#else 2250 /* enqueueInternal() is private and thus a direct method. */ 2251 meth = dvmFindDirectMethodByDescriptor(clazz, "enqueueInternal", "()Z"); 2252 assert(meth != NULL); 2253 gDvm.methJavaLangRefReference_enqueueInternal = meth; 2254#endif 2255 2256 return true; 2257} 2258 2259 2260/* 2261 * Set the bitmap of reference offsets, refOffsets, from the ifields 2262 * list. 2263 */ 2264static void computeRefOffsets(ClassObject* clazz) 2265{ 2266 if (clazz->super != NULL) { 2267 clazz->refOffsets = clazz->super->refOffsets; 2268 } else { 2269 clazz->refOffsets = 0; 2270 } 2271 /* 2272 * If our superclass overflowed, we don't stand a chance. 2273 */ 2274 if (clazz->refOffsets != CLASS_WALK_SUPER) { 2275 InstField *f; 2276 int i; 2277 2278 /* All of the fields that contain object references 2279 * are guaranteed to be at the beginning of the ifields list. 2280 */ 2281 f = clazz->ifields; 2282 const int ifieldRefCount = clazz->ifieldRefCount; 2283 for (i = 0; i < ifieldRefCount; i++) { 2284 /* 2285 * Note that, per the comment on struct InstField, 2286 * f->byteOffset is the offset from the beginning of 2287 * obj, not the offset into obj->instanceData. 2288 */ 2289 assert(f->byteOffset >= CLASS_SMALLEST_OFFSET); 2290 assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0); 2291 if (CLASS_CAN_ENCODE_OFFSET(f->byteOffset)) { 2292 u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset); 2293 assert(newBit != 0); 2294 clazz->refOffsets |= newBit; 2295 } else { 2296 clazz->refOffsets = CLASS_WALK_SUPER; 2297 break; 2298 } 2299 f++; 2300 } 2301 } 2302} 2303 2304 2305/* 2306 * Link (prepare and resolve). Verification is deferred until later. 2307 * 2308 * This converts symbolic references into pointers. It's independent of 2309 * the source file format. 2310 * 2311 * If "classesResolved" is false, we assume that superclassIdx and 2312 * interfaces[] are holding class reference indices rather than pointers. 2313 * The class references will be resolved during link. (This is done when 2314 * loading from DEX to avoid having to create additional storage to pass 2315 * the indices around.) 2316 * 2317 * Returns "false" with an exception pending on failure. 2318 */ 2319bool dvmLinkClass(ClassObject* clazz, bool classesResolved) 2320{ 2321 u4 superclassIdx = 0; 2322 bool okay = false; 2323 bool resolve_okay; 2324 int numInterfacesResolved = 0; 2325 int i; 2326 2327 if (gDvm.verboseClass) 2328 LOGV("CLASS: linking '%s'...\n", clazz->descriptor); 2329 2330 /* "Resolve" the class. 2331 * 2332 * At this point, clazz's reference fields contain Dex 2333 * file indices instead of direct object references. 2334 * We need to translate those indices into real references, 2335 * while making sure that the GC doesn't sweep any of 2336 * the referenced objects. 2337 * 2338 * The GC will avoid scanning this object as long as 2339 * clazz->obj.clazz is gDvm.unlinkedJavaLangClass. 2340 * Once clazz is ready, we'll replace clazz->obj.clazz 2341 * with gDvm.classJavaLangClass to let the GC know 2342 * to look at it. 2343 */ 2344 assert(clazz->obj.clazz == gDvm.unlinkedJavaLangClass); 2345 2346 /* It's important that we take care of java.lang.Class 2347 * first. If we were to do this after looking up the 2348 * superclass (below), Class wouldn't be ready when 2349 * java.lang.Object needed it. 2350 * 2351 * Note that we don't set clazz->obj.clazz yet. 2352 */ 2353 if (gDvm.classJavaLangClass == NULL) { 2354 if (clazz->classLoader == NULL && 2355 strcmp(clazz->descriptor, "Ljava/lang/Class;") == 0) 2356 { 2357 gDvm.classJavaLangClass = clazz; 2358 } else { 2359 gDvm.classJavaLangClass = 2360 dvmFindSystemClassNoInit("Ljava/lang/Class;"); 2361 if (gDvm.classJavaLangClass == NULL) { 2362 /* should have thrown one */ 2363 assert(dvmCheckException(dvmThreadSelf())); 2364 goto bail; 2365 } 2366 } 2367 } 2368 assert(gDvm.classJavaLangClass != NULL); 2369 2370 /* 2371 * Resolve all Dex indices so we can hand the ClassObject 2372 * over to the GC. If we fail at any point, we need to remove 2373 * any tracked references to avoid leaking memory. 2374 */ 2375 2376 /* 2377 * All classes have a direct superclass, except for java/lang/Object. 2378 */ 2379 if (!classesResolved) { 2380 superclassIdx = (u4) clazz->super; /* unpack temp store */ 2381 clazz->super = NULL; 2382 } 2383 if (strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0) { 2384 assert(!classesResolved); 2385 if (superclassIdx != kDexNoIndex) { 2386 /* TODO: is this invariant true for all java/lang/Objects, 2387 * regardless of the class loader? For now, assume it is. 2388 */ 2389 dvmThrowException("Ljava/lang/ClassFormatError;", 2390 "java.lang.Object has a superclass"); 2391 goto bail; 2392 } 2393 2394 /* Don't finalize objects whose classes use the 2395 * default (empty) Object.finalize(). 2396 */ 2397 CLEAR_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE); 2398 } else { 2399 if (!classesResolved) { 2400 if (superclassIdx == kDexNoIndex) { 2401 dvmThrowException("Ljava/lang/LinkageError;", 2402 "no superclass defined"); 2403 goto bail; 2404 } 2405 clazz->super = dvmResolveClass(clazz, superclassIdx, false); 2406 if (clazz->super == NULL) { 2407 assert(dvmCheckException(dvmThreadSelf())); 2408 if (gDvm.optimizing) { 2409 /* happens with "external" libs */ 2410 LOGV("Unable to resolve superclass of %s (%d)\n", 2411 clazz->descriptor, superclassIdx); 2412 } else { 2413 LOGW("Unable to resolve superclass of %s (%d)\n", 2414 clazz->descriptor, superclassIdx); 2415 } 2416 goto bail; 2417 } 2418 } 2419 /* verify */ 2420 if (dvmIsFinalClass(clazz->super)) { 2421 LOGW("Superclass of '%s' is final '%s'\n", 2422 clazz->descriptor, clazz->super->descriptor); 2423 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;", 2424 "superclass is final"); 2425 goto bail; 2426 } else if (dvmIsInterfaceClass(clazz->super)) { 2427 LOGW("Superclass of '%s' is interface '%s'\n", 2428 clazz->descriptor, clazz->super->descriptor); 2429 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;", 2430 "superclass is an interface"); 2431 goto bail; 2432 } else if (!dvmCheckClassAccess(clazz, clazz->super)) { 2433 LOGW("Superclass of '%s' (%s) is not accessible\n", 2434 clazz->descriptor, clazz->super->descriptor); 2435 dvmThrowException("Ljava/lang/IllegalAccessError;", 2436 "superclass not accessible"); 2437 goto bail; 2438 } 2439 2440 /* Don't let the GC reclaim the superclass. 2441 * TODO: shouldn't be needed; remove when things stabilize 2442 */ 2443 dvmAddTrackedAlloc((Object *)clazz->super, NULL); 2444 2445 /* Inherit finalizability from the superclass. If this 2446 * class also overrides finalize(), its CLASS_ISFINALIZABLE 2447 * bit will already be set. 2448 */ 2449 if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISFINALIZABLE)) { 2450 SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE); 2451 } 2452 2453 /* See if this class descends from java.lang.Reference 2454 * and set the class flags appropriately. 2455 */ 2456 if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISREFERENCE)) { 2457 u4 superRefFlags; 2458 2459 /* We've already determined the reference type of this 2460 * inheritance chain. Inherit reference-ness from the superclass. 2461 */ 2462 superRefFlags = GET_CLASS_FLAG_GROUP(clazz->super, 2463 CLASS_ISREFERENCE | 2464 CLASS_ISWEAKREFERENCE | 2465 CLASS_ISPHANTOMREFERENCE); 2466 SET_CLASS_FLAG(clazz, superRefFlags); 2467 } else if (clazz->classLoader == NULL && 2468 clazz->super->classLoader == NULL && 2469 strcmp(clazz->super->descriptor, 2470 "Ljava/lang/ref/Reference;") == 0) 2471 { 2472 u4 refFlags; 2473 2474 /* This class extends Reference, which means it should 2475 * be one of the magic Soft/Weak/PhantomReference classes. 2476 */ 2477 refFlags = CLASS_ISREFERENCE; 2478 if (strcmp(clazz->descriptor, 2479 "Ljava/lang/ref/SoftReference;") == 0) 2480 { 2481 /* Only CLASS_ISREFERENCE is set for soft references. 2482 */ 2483 } else if (strcmp(clazz->descriptor, 2484 "Ljava/lang/ref/WeakReference;") == 0) 2485 { 2486 refFlags |= CLASS_ISWEAKREFERENCE; 2487 } else if (strcmp(clazz->descriptor, 2488 "Ljava/lang/ref/PhantomReference;") == 0) 2489 { 2490 refFlags |= CLASS_ISPHANTOMREFERENCE; 2491 } else { 2492 /* No-one else is allowed to inherit directly 2493 * from Reference. 2494 */ 2495//xxx is this the right exception? better than an assertion. 2496 dvmThrowException("Ljava/lang/LinkageError;", 2497 "illegal inheritance from Reference"); 2498 goto bail; 2499 } 2500 2501 /* The class should not have any reference bits set yet. 2502 */ 2503 assert(GET_CLASS_FLAG_GROUP(clazz, 2504 CLASS_ISREFERENCE | 2505 CLASS_ISWEAKREFERENCE | 2506 CLASS_ISPHANTOMREFERENCE) == 0); 2507 2508 SET_CLASS_FLAG(clazz, refFlags); 2509 } 2510 } 2511 2512 if (!classesResolved && clazz->interfaceCount > 0) { 2513 /* 2514 * Resolve the interfaces implemented directly by this class. We 2515 * stuffed the class index into the interface pointer slot. 2516 */ 2517 dvmLinearReadWrite(clazz->classLoader, clazz->interfaces); 2518 for (i = 0; i < clazz->interfaceCount; i++) { 2519 u4 interfaceIdx; 2520 2521 interfaceIdx = (u4) clazz->interfaces[i]; /* unpack temp store */ 2522 assert(interfaceIdx != kDexNoIndex); 2523 2524 clazz->interfaces[i] = dvmResolveClass(clazz, interfaceIdx, false); 2525 if (clazz->interfaces[i] == NULL) { 2526 const DexFile* pDexFile = clazz->pDvmDex->pDexFile; 2527 2528 assert(dvmCheckException(dvmThreadSelf())); 2529 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces); 2530 2531 const char* classDescriptor; 2532 classDescriptor = dexStringByTypeIdx(pDexFile, interfaceIdx); 2533 if (gDvm.optimizing) { 2534 /* happens with "external" libs */ 2535 LOGV("Failed resolving %s interface %d '%s'\n", 2536 clazz->descriptor, interfaceIdx, classDescriptor); 2537 } else { 2538 LOGI("Failed resolving %s interface %d '%s'\n", 2539 clazz->descriptor, interfaceIdx, classDescriptor); 2540 } 2541 goto bail_during_resolve; 2542 } 2543 2544 /* are we allowed to implement this interface? */ 2545 if (!dvmCheckClassAccess(clazz, clazz->interfaces[i])) { 2546 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces); 2547 LOGW("Interface '%s' is not accessible to '%s'\n", 2548 clazz->interfaces[i]->descriptor, clazz->descriptor); 2549 dvmThrowException("Ljava/lang/IllegalAccessError;", 2550 "interface not accessible"); 2551 goto bail_during_resolve; 2552 } 2553 2554 /* Don't let the GC reclaim the interface class. 2555 * TODO: shouldn't be needed; remove when things stabilize 2556 */ 2557 dvmAddTrackedAlloc((Object *)clazz->interfaces[i], NULL); 2558 numInterfacesResolved++; 2559 2560 LOGVV("+++ found interface '%s'\n", 2561 clazz->interfaces[i]->descriptor); 2562 } 2563 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces); 2564 } 2565 2566 /* 2567 * The ClassObject is now in a GC-able state. We let the GC 2568 * realize this by punching in the real class type, which is 2569 * always java.lang.Class. 2570 * 2571 * After this line, clazz will be fair game for the GC. 2572 * Every field that the GC will look at must now be valid: 2573 * - clazz->super 2574 * - class->classLoader 2575 * - clazz->sfields 2576 * - clazz->interfaces 2577 */ 2578 clazz->obj.clazz = gDvm.classJavaLangClass; 2579 2580 if (false) { 2581bail_during_resolve: 2582 resolve_okay = false; 2583 } else { 2584 resolve_okay = true; 2585 } 2586 2587 /* 2588 * Now that the GC can scan the ClassObject, we can let 2589 * go of the explicit references we were holding onto. 2590 * 2591 * Either that or we failed, in which case we need to 2592 * release the references so we don't leak memory. 2593 */ 2594 if (clazz->super != NULL) { 2595 dvmReleaseTrackedAlloc((Object *)clazz->super, NULL); 2596 } 2597 for (i = 0; i < numInterfacesResolved; i++) { 2598 dvmReleaseTrackedAlloc((Object *)clazz->interfaces[i], NULL); 2599 } 2600 2601 if (!resolve_okay) { 2602 //LOGW("resolve_okay is false\n"); 2603 goto bail; 2604 } 2605 2606 /* 2607 * Populate vtable. 2608 */ 2609 if (dvmIsInterfaceClass(clazz)) { 2610 /* no vtable; just set the method indices */ 2611 int count = clazz->virtualMethodCount; 2612 2613 if (count != (u2) count) { 2614 LOGE("Too many methods (%d) in interface '%s'\n", count, 2615 clazz->descriptor); 2616 goto bail; 2617 } 2618 2619 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods); 2620 2621 for (i = 0; i < count; i++) 2622 clazz->virtualMethods[i].methodIndex = (u2) i; 2623 2624 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods); 2625 } else { 2626 if (!createVtable(clazz)) { 2627 LOGW("failed creating vtable\n"); 2628 goto bail; 2629 } 2630 } 2631 2632 /* 2633 * Populate interface method tables. Can alter the vtable. 2634 */ 2635 if (!createIftable(clazz)) 2636 goto bail; 2637 2638 /* 2639 * Insert special-purpose "stub" method implementations. 2640 */ 2641 if (!insertMethodStubs(clazz)) 2642 goto bail; 2643 2644 /* 2645 * Compute instance field offsets and, hence, the size of the object. 2646 */ 2647 if (!computeFieldOffsets(clazz)) 2648 goto bail; 2649 2650 /* 2651 * Cache fields and methods from java/lang/ref/Reference and 2652 * java/lang/Class. This has to happen after computeFieldOffsets(). 2653 */ 2654 if (clazz->classLoader == NULL) { 2655 if (strcmp(clazz->descriptor, "Ljava/lang/ref/Reference;") == 0) { 2656 if (!precacheReferenceOffsets(clazz)) { 2657 LOGE("failed pre-caching Reference offsets\n"); 2658 dvmThrowException("Ljava/lang/InternalError;", NULL); 2659 goto bail; 2660 } 2661 } else if (clazz == gDvm.classJavaLangClass) { 2662 gDvm.offJavaLangClass_pd = dvmFindFieldOffset(clazz, "pd", 2663 "Ljava/security/ProtectionDomain;"); 2664 if (gDvm.offJavaLangClass_pd <= 0) { 2665 LOGE("ERROR: unable to find 'pd' field in Class\n"); 2666 dvmAbort(); /* we're not going to get much farther */ 2667 //goto bail; 2668 } 2669 } 2670 } 2671 2672 /* 2673 * Compact the offsets the GC has to examine into a bitmap, if 2674 * possible. (This has to happen after Reference.referent is 2675 * massaged in precacheReferenceOffsets.) 2676 */ 2677 computeRefOffsets(clazz); 2678 2679 /* 2680 * Done! 2681 */ 2682 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED)) 2683 clazz->status = CLASS_VERIFIED; 2684 else 2685 clazz->status = CLASS_RESOLVED; 2686 okay = true; 2687 if (gDvm.verboseClass) 2688 LOGV("CLASS: linked '%s'\n", clazz->descriptor); 2689 2690 /* 2691 * We send CLASS_PREPARE events to the debugger from here. The 2692 * definition of "preparation" is creating the static fields for a 2693 * class and initializing them to the standard default values, but not 2694 * executing any code (that comes later, during "initialization"). 2695 * 2696 * We did the static prep in loadSFieldFromDex() while loading the class. 2697 * 2698 * The class has been prepared and resolved but possibly not yet verified 2699 * at this point. 2700 */ 2701 if (gDvm.debuggerActive) { 2702 dvmDbgPostClassPrepare(clazz); 2703 } 2704 2705bail: 2706 if (!okay) { 2707 clazz->status = CLASS_ERROR; 2708 if (!dvmCheckException(dvmThreadSelf())) { 2709 dvmThrowException("Ljava/lang/VirtualMachineError;", NULL); 2710 } 2711 } 2712 return okay; 2713} 2714 2715/* 2716 * Create the virtual method table. 2717 * 2718 * The top part of the table is a copy of the table from our superclass, 2719 * with our local methods overriding theirs. The bottom part of the table 2720 * has any new methods we defined. 2721 */ 2722static bool createVtable(ClassObject* clazz) 2723{ 2724 bool result = false; 2725 int maxCount; 2726 int i; 2727 2728 if (clazz->super != NULL) { 2729 //LOGI("SUPER METHODS %d %s->%s\n", clazz->super->vtableCount, 2730 // clazz->descriptor, clazz->super->descriptor); 2731 } 2732 2733 /* the virtual methods we define, plus the superclass vtable size */ 2734 maxCount = clazz->virtualMethodCount; 2735 if (clazz->super != NULL) { 2736 maxCount += clazz->super->vtableCount; 2737 } else { 2738 /* TODO: is this invariant true for all java/lang/Objects, 2739 * regardless of the class loader? For now, assume it is. 2740 */ 2741 assert(strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0); 2742 } 2743 //LOGD("+++ max vmethods for '%s' is %d\n", clazz->descriptor, maxCount); 2744 2745 /* 2746 * Over-allocate the table, then realloc it down if necessary. So 2747 * long as we don't allocate anything in between we won't cause 2748 * fragmentation, and reducing the size should be unlikely to cause 2749 * a buffer copy. 2750 */ 2751 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods); 2752 clazz->vtable = (Method**) dvmLinearAlloc(clazz->classLoader, 2753 sizeof(Method*) * maxCount); 2754 if (clazz->vtable == NULL) 2755 goto bail; 2756 2757 if (clazz->super != NULL) { 2758 int actualCount; 2759 2760 memcpy(clazz->vtable, clazz->super->vtable, 2761 sizeof(*(clazz->vtable)) * clazz->super->vtableCount); 2762 actualCount = clazz->super->vtableCount; 2763 2764 /* 2765 * See if any of our virtual methods override the superclass. 2766 */ 2767 for (i = 0; i < clazz->virtualMethodCount; i++) { 2768 Method* localMeth = &clazz->virtualMethods[i]; 2769 int si; 2770 2771 for (si = 0; si < clazz->super->vtableCount; si++) { 2772 Method* superMeth = clazz->vtable[si]; 2773 2774 if (dvmCompareMethodNamesAndProtos(localMeth, superMeth) == 0) 2775 { 2776 /* verify */ 2777 if (dvmIsFinalMethod(superMeth)) { 2778 LOGW("Method %s.%s overrides final %s.%s\n", 2779 localMeth->clazz->descriptor, localMeth->name, 2780 superMeth->clazz->descriptor, superMeth->name); 2781 goto bail; 2782 } 2783 clazz->vtable[si] = localMeth; 2784 localMeth->methodIndex = (u2) si; 2785 //LOGV("+++ override %s.%s (slot %d)\n", 2786 // clazz->descriptor, localMeth->name, si); 2787 break; 2788 } 2789 } 2790 2791 if (si == clazz->super->vtableCount) { 2792 /* not an override, add to end */ 2793 clazz->vtable[actualCount] = localMeth; 2794 localMeth->methodIndex = (u2) actualCount; 2795 actualCount++; 2796 2797 //LOGV("+++ add method %s.%s\n", 2798 // clazz->descriptor, localMeth->name); 2799 } 2800 } 2801 2802 if (actualCount != (u2) actualCount) { 2803 LOGE("Too many methods (%d) in class '%s'\n", actualCount, 2804 clazz->descriptor); 2805 goto bail; 2806 } 2807 2808 assert(actualCount <= maxCount); 2809 2810 if (actualCount < maxCount) { 2811 assert(clazz->vtable != NULL); 2812 dvmLinearReadOnly(clazz->classLoader, clazz->vtable); 2813 clazz->vtable = dvmLinearRealloc(clazz->classLoader, clazz->vtable, 2814 sizeof(*(clazz->vtable)) * actualCount); 2815 if (clazz->vtable == NULL) { 2816 LOGE("vtable realloc failed\n"); 2817 goto bail; 2818 } else { 2819 LOGVV("+++ reduced vtable from %d to %d\n", 2820 maxCount, actualCount); 2821 } 2822 } 2823 2824 clazz->vtableCount = actualCount; 2825 } else { 2826 /* java/lang/Object case */ 2827 int count = clazz->virtualMethodCount; 2828 if (count != (u2) count) { 2829 LOGE("Too many methods (%d) in base class '%s'\n", count, 2830 clazz->descriptor); 2831 goto bail; 2832 } 2833 2834 for (i = 0; i < count; i++) { 2835 clazz->vtable[i] = &clazz->virtualMethods[i]; 2836 clazz->virtualMethods[i].methodIndex = (u2) i; 2837 } 2838 clazz->vtableCount = clazz->virtualMethodCount; 2839 } 2840 2841 result = true; 2842 2843bail: 2844 dvmLinearReadOnly(clazz->classLoader, clazz->vtable); 2845 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods); 2846 return result; 2847} 2848 2849/* 2850 * Create and populate "iftable". 2851 * 2852 * The set of interfaces we support is the combination of the interfaces 2853 * we implement directly and those implemented by our superclass. Each 2854 * interface can have one or more "superinterfaces", which we must also 2855 * support. For speed we flatten the tree out. 2856 * 2857 * We might be able to speed this up when there are lots of interfaces 2858 * by merge-sorting the class pointers and binary-searching when removing 2859 * duplicates. We could also drop the duplicate removal -- it's only 2860 * there to reduce the memory footprint. 2861 * 2862 * Because of "Miranda methods", this may reallocate clazz->virtualMethods. 2863 * 2864 * Returns "true" on success. 2865 */ 2866static bool createIftable(ClassObject* clazz) 2867{ 2868 bool result = false; 2869 bool zapIftable = false; 2870 bool zapVtable = false; 2871 bool zapIfvipool = false; 2872 int ifCount, superIfCount, idx; 2873 int i; 2874 2875 if (clazz->super != NULL) 2876 superIfCount = clazz->super->iftableCount; 2877 else 2878 superIfCount = 0; 2879 2880 ifCount = superIfCount; 2881 ifCount += clazz->interfaceCount; 2882 for (i = 0; i < clazz->interfaceCount; i++) 2883 ifCount += clazz->interfaces[i]->iftableCount; 2884 2885 LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d\n", 2886 clazz->descriptor, ifCount - superIfCount, superIfCount, ifCount); 2887 2888 if (ifCount == 0) { 2889 assert(clazz->iftableCount == 0); 2890 assert(clazz->iftable == NULL); 2891 result = true; 2892 goto bail; 2893 } 2894 2895 /* 2896 * Create a table with enough space for all interfaces, and copy the 2897 * superclass' table in. 2898 */ 2899 clazz->iftable = (InterfaceEntry*) dvmLinearAlloc(clazz->classLoader, 2900 sizeof(InterfaceEntry) * ifCount); 2901 zapIftable = true; 2902 memset(clazz->iftable, 0x00, sizeof(InterfaceEntry) * ifCount); 2903 if (superIfCount != 0) { 2904 memcpy(clazz->iftable, clazz->super->iftable, 2905 sizeof(InterfaceEntry) * superIfCount); 2906 } 2907 2908 /* 2909 * Create a flattened interface hierarchy of our immediate interfaces. 2910 */ 2911 idx = superIfCount; 2912 2913 for (i = 0; i < clazz->interfaceCount; i++) { 2914 ClassObject* interf; 2915 int j; 2916 2917 interf = clazz->interfaces[i]; 2918 assert(interf != NULL); 2919 2920 /* make sure this is still an interface class */ 2921 if (!dvmIsInterfaceClass(interf)) { 2922 LOGW("Class '%s' implements non-interface '%s'\n", 2923 clazz->descriptor, interf->descriptor); 2924 dvmThrowExceptionWithClassMessage( 2925 "Ljava/lang/IncompatibleClassChangeError;", 2926 clazz->descriptor); 2927 goto bail; 2928 } 2929 2930 /* add entry for this interface */ 2931 clazz->iftable[idx++].clazz = interf; 2932 2933 /* add entries for the interface's superinterfaces */ 2934 for (j = 0; j < interf->iftableCount; j++) { 2935 clazz->iftable[idx++].clazz = interf->iftable[j].clazz; 2936 } 2937 } 2938 2939 assert(idx == ifCount); 2940 2941 if (false) { 2942 /* 2943 * Remove anything redundant from our recent additions. Note we have 2944 * to traverse the recent adds when looking for duplicates, because 2945 * it's possible the recent additions are self-redundant. This 2946 * reduces the memory footprint of classes with lots of inherited 2947 * interfaces. 2948 * 2949 * (I don't know if this will cause problems later on when we're trying 2950 * to find a static field. It looks like the proper search order is 2951 * (1) current class, (2) interfaces implemented by current class, 2952 * (3) repeat with superclass. A field implemented by an interface 2953 * and by a superclass might come out wrong if the superclass also 2954 * implements the interface. The javac compiler will reject the 2955 * situation as ambiguous, so the concern is somewhat artificial.) 2956 * 2957 * UPDATE: this makes ReferenceType.Interfaces difficult to implement, 2958 * because it wants to return just the interfaces declared to be 2959 * implemented directly by the class. I'm excluding this code for now. 2960 */ 2961 for (i = superIfCount; i < ifCount; i++) { 2962 int j; 2963 2964 for (j = 0; j < ifCount; j++) { 2965 if (i == j) 2966 continue; 2967 if (clazz->iftable[i].clazz == clazz->iftable[j].clazz) { 2968 LOGVV("INTF: redundant interface %s in %s\n", 2969 clazz->iftable[i].clazz->descriptor, 2970 clazz->descriptor); 2971 2972 if (i != ifCount-1) 2973 memmove(&clazz->iftable[i], &clazz->iftable[i+1], 2974 (ifCount - i -1) * sizeof(InterfaceEntry)); 2975 ifCount--; 2976 i--; // adjust for i++ above 2977 break; 2978 } 2979 } 2980 } 2981 LOGVV("INTF: class '%s' nodupes=%d\n", clazz->descriptor, ifCount); 2982 } // if (false) 2983 2984 clazz->iftableCount = ifCount; 2985 2986 /* 2987 * If we're an interface, we don't need the vtable pointers, so 2988 * we're done. If this class doesn't implement an interface that our 2989 * superclass doesn't have, then we again have nothing to do. 2990 */ 2991 if (dvmIsInterfaceClass(clazz) || superIfCount == ifCount) { 2992 //dvmDumpClass(clazz, kDumpClassFullDetail); 2993 result = true; 2994 goto bail; 2995 } 2996 2997 /* 2998 * When we're handling invokeinterface, we probably have an object 2999 * whose type is an interface class rather than a concrete class. We 3000 * need to convert the method reference into a vtable index. So, for 3001 * every entry in "iftable", we create a list of vtable indices. 3002 * 3003 * Because our vtable encompasses the superclass vtable, we can use 3004 * the vtable indices from our superclass for all of the interfaces 3005 * that weren't directly implemented by us. 3006 * 3007 * Each entry in "iftable" has a pointer to the start of its set of 3008 * vtable offsets. The iftable entries in the superclass point to 3009 * storage allocated in the superclass, and the iftable entries added 3010 * for this class point to storage allocated in this class. "iftable" 3011 * is flat for fast access in a class and all of its subclasses, but 3012 * "ifviPool" is only created for the topmost implementor. 3013 */ 3014 int poolSize = 0; 3015 for (i = superIfCount; i < ifCount; i++) { 3016 /* 3017 * Note it's valid for an interface to have no methods (e.g. 3018 * java/io/Serializable). 3019 */ 3020 LOGVV("INTF: pool: %d from %s\n", 3021 clazz->iftable[i].clazz->virtualMethodCount, 3022 clazz->iftable[i].clazz->descriptor); 3023 poolSize += clazz->iftable[i].clazz->virtualMethodCount; 3024 } 3025 3026 if (poolSize == 0) { 3027 LOGVV("INTF: didn't find any new interfaces with methods\n"); 3028 result = true; 3029 goto bail; 3030 } 3031 3032 clazz->ifviPoolCount = poolSize; 3033 clazz->ifviPool = (int*) dvmLinearAlloc(clazz->classLoader, 3034 poolSize * sizeof(int*)); 3035 zapIfvipool = true; 3036 3037 /* 3038 * Fill in the vtable offsets for the interfaces that weren't part of 3039 * our superclass. 3040 */ 3041 int poolOffset = 0; 3042 Method** mirandaList = NULL; 3043 int mirandaCount = 0, mirandaAlloc = 0; 3044 3045 for (i = superIfCount; i < ifCount; i++) { 3046 ClassObject* interface; 3047 int methIdx; 3048 3049 clazz->iftable[i].methodIndexArray = clazz->ifviPool + poolOffset; 3050 interface = clazz->iftable[i].clazz; 3051 poolOffset += interface->virtualMethodCount; // end here 3052 3053 /* 3054 * For each method listed in the interface's method list, find the 3055 * matching method in our class's method list. We want to favor the 3056 * subclass over the superclass, which just requires walking 3057 * back from the end of the vtable. (This only matters if the 3058 * superclass defines a private method and this class redefines 3059 * it -- otherwise it would use the same vtable slot. In Dalvik 3060 * those don't end up in the virtual method table, so it shouldn't 3061 * matter which direction we go. We walk it backward anyway.) 3062 * 3063 * 3064 * Suppose we have the following arrangement: 3065 * public interface MyInterface 3066 * public boolean inInterface(); 3067 * public abstract class MirandaAbstract implements MirandaInterface 3068 * //public abstract boolean inInterface(); // not declared! 3069 * public boolean inAbstract() { stuff } // in vtable 3070 * public class MirandClass extends MirandaAbstract 3071 * public boolean inInterface() { stuff } 3072 * public boolean inAbstract() { stuff } // in vtable 3073 * 3074 * The javac compiler happily compiles MirandaAbstract even though 3075 * it doesn't declare all methods from its interface. When we try 3076 * to set up a vtable for MirandaAbstract, we find that we don't 3077 * have an slot for inInterface. To prevent this, we synthesize 3078 * abstract method declarations in MirandaAbstract. 3079 * 3080 * We have to expand vtable and update some things that point at it, 3081 * so we accumulate the method list and do it all at once below. 3082 */ 3083 for (methIdx = 0; methIdx < interface->virtualMethodCount; methIdx++) { 3084 Method* imeth = &interface->virtualMethods[methIdx]; 3085 int j; 3086 3087 IF_LOGVV() { 3088 char* desc = dexProtoCopyMethodDescriptor(&imeth->prototype); 3089 LOGVV("INTF: matching '%s' '%s'\n", imeth->name, desc); 3090 free(desc); 3091 } 3092 3093 for (j = clazz->vtableCount-1; j >= 0; j--) { 3094 if (dvmCompareMethodNamesAndProtos(imeth, clazz->vtable[j]) 3095 == 0) 3096 { 3097 LOGVV("INTF: matched at %d\n", j); 3098 if (!dvmIsPublicMethod(clazz->vtable[j])) { 3099 LOGW("Implementation of %s.%s is not public\n", 3100 clazz->descriptor, clazz->vtable[j]->name); 3101 dvmThrowException("Ljava/lang/IllegalAccessError;", 3102 "interface implementation not public"); 3103 goto bail; 3104 } 3105 clazz->iftable[i].methodIndexArray[methIdx] = j; 3106 break; 3107 } 3108 } 3109 if (j < 0) { 3110 IF_LOGV() { 3111 char* desc = 3112 dexProtoCopyMethodDescriptor(&imeth->prototype); 3113 LOGV("No match for '%s' '%s' in '%s' (creating miranda)\n", 3114 imeth->name, desc, clazz->descriptor); 3115 free(desc); 3116 } 3117 //dvmThrowException("Ljava/lang/RuntimeException;", "Miranda!"); 3118 //return false; 3119 3120 if (mirandaCount == mirandaAlloc) { 3121 mirandaAlloc += 8; 3122 if (mirandaList == NULL) { 3123 mirandaList = dvmLinearAlloc(clazz->classLoader, 3124 mirandaAlloc * sizeof(Method*)); 3125 } else { 3126 dvmLinearReadOnly(clazz->classLoader, mirandaList); 3127 mirandaList = dvmLinearRealloc(clazz->classLoader, 3128 mirandaList, mirandaAlloc * sizeof(Method*)); 3129 } 3130 assert(mirandaList != NULL); // mem failed + we leaked 3131 } 3132 3133 /* 3134 * These may be redundant (e.g. method with same name and 3135 * signature declared in two interfaces implemented by the 3136 * same abstract class). We can squeeze the duplicates 3137 * out here. 3138 */ 3139 int mir; 3140 for (mir = 0; mir < mirandaCount; mir++) { 3141 if (dvmCompareMethodNamesAndProtos( 3142 mirandaList[mir], imeth) == 0) 3143 { 3144 IF_LOGVV() { 3145 char* desc = dexProtoCopyMethodDescriptor( 3146 &imeth->prototype); 3147 LOGVV("MIRANDA dupe: %s and %s %s%s\n", 3148 mirandaList[mir]->clazz->descriptor, 3149 imeth->clazz->descriptor, 3150 imeth->name, desc); 3151 free(desc); 3152 } 3153 break; 3154 } 3155 } 3156 3157 /* point the iftable at a phantom slot index */ 3158 clazz->iftable[i].methodIndexArray[methIdx] = 3159 clazz->vtableCount + mir; 3160 LOGVV("MIRANDA: %s points at slot %d\n", 3161 imeth->name, clazz->vtableCount + mir); 3162 3163 /* if non-duplicate among Mirandas, add to Miranda list */ 3164 if (mir == mirandaCount) { 3165 //LOGV("MIRANDA: holding '%s' in slot %d\n", 3166 // imeth->name, mir); 3167 mirandaList[mirandaCount++] = imeth; 3168 } 3169 } 3170 } 3171 } 3172 3173 if (mirandaCount != 0) { 3174 Method* newVirtualMethods; 3175 Method* meth; 3176 int oldMethodCount, oldVtableCount; 3177 3178 for (i = 0; i < mirandaCount; i++) { 3179 LOGVV("MIRANDA %d: %s.%s\n", i, 3180 mirandaList[i]->clazz->descriptor, mirandaList[i]->name); 3181 } 3182 3183 /* 3184 * We found methods in one or more interfaces for which we do not 3185 * have vtable entries. We have to expand our virtualMethods 3186 * table (which might be empty) to hold some new entries. 3187 */ 3188 if (clazz->virtualMethods == NULL) { 3189 newVirtualMethods = (Method*) dvmLinearAlloc(clazz->classLoader, 3190 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount)); 3191 } else { 3192 //dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods); 3193 newVirtualMethods = (Method*) dvmLinearRealloc(clazz->classLoader, 3194 clazz->virtualMethods, 3195 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount)); 3196 } 3197 if (newVirtualMethods != clazz->virtualMethods) { 3198 /* 3199 * Table was moved in memory. We have to run through the 3200 * vtable and fix the pointers. The vtable entries might be 3201 * pointing at superclasses, so we flip it around: run through 3202 * all locally-defined virtual methods, and fix their entries 3203 * in the vtable. (This would get really messy if sub-classes 3204 * had already been loaded.) 3205 * 3206 * Reminder: clazz->virtualMethods and clazz->virtualMethodCount 3207 * hold the virtual methods declared by this class. The 3208 * method's methodIndex is the vtable index, and is the same 3209 * for all sub-classes (and all super classes in which it is 3210 * defined). We're messing with these because the Miranda 3211 * stuff makes it look like the class actually has an abstract 3212 * method declaration in it. 3213 */ 3214 LOGVV("MIRANDA fixing vtable pointers\n"); 3215 dvmLinearReadWrite(clazz->classLoader, clazz->vtable); 3216 Method* meth = newVirtualMethods; 3217 for (i = 0; i < clazz->virtualMethodCount; i++, meth++) 3218 clazz->vtable[meth->methodIndex] = meth; 3219 dvmLinearReadOnly(clazz->classLoader, clazz->vtable); 3220 } 3221 3222 oldMethodCount = clazz->virtualMethodCount; 3223 clazz->virtualMethods = newVirtualMethods; 3224 clazz->virtualMethodCount += mirandaCount; 3225 3226 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods); 3227 3228 /* 3229 * We also have to expand the vtable. 3230 */ 3231 assert(clazz->vtable != NULL); 3232 clazz->vtable = (Method**) dvmLinearRealloc(clazz->classLoader, 3233 clazz->vtable, 3234 sizeof(Method*) * (clazz->vtableCount + mirandaCount)); 3235 if (clazz->vtable == NULL) { 3236 assert(false); 3237 goto bail; 3238 } 3239 zapVtable = true; 3240 3241 oldVtableCount = clazz->vtableCount; 3242 clazz->vtableCount += mirandaCount; 3243 3244 /* 3245 * Now we need to create the fake methods. We clone the abstract 3246 * method definition from the interface and then replace a few 3247 * things. 3248 */ 3249 meth = clazz->virtualMethods + oldMethodCount; 3250 for (i = 0; i < mirandaCount; i++, meth++) { 3251 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods); 3252 cloneMethod(meth, mirandaList[i]); 3253 meth->clazz = clazz; 3254 meth->accessFlags |= ACC_MIRANDA; 3255 meth->methodIndex = (u2) (oldVtableCount + i); 3256 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods); 3257 3258 /* point the new vtable entry at the new method */ 3259 clazz->vtable[oldVtableCount + i] = meth; 3260 } 3261 3262 dvmLinearReadOnly(clazz->classLoader, mirandaList); 3263 dvmLinearFree(clazz->classLoader, mirandaList); 3264 3265 } 3266 3267 /* 3268 * TODO? 3269 * Sort the interfaces by number of declared methods. All we really 3270 * want is to get the interfaces with zero methods at the end of the 3271 * list, so that when we walk through the list during invoke-interface 3272 * we don't examine interfaces that can't possibly be useful. 3273 * 3274 * The set will usually be small, so a simple insertion sort works. 3275 * 3276 * We have to be careful not to change the order of two interfaces 3277 * that define the same method. (Not a problem if we only move the 3278 * zero-method interfaces to the end.) 3279 * 3280 * PROBLEM: 3281 * If we do this, we will no longer be able to identify super vs. 3282 * current class interfaces by comparing clazz->super->iftableCount. This 3283 * breaks anything that only wants to find interfaces declared directly 3284 * by the class (dvmFindStaticFieldHier, ReferenceType.Interfaces, 3285 * dvmDbgOutputAllInterfaces, etc). Need to provide a workaround. 3286 * 3287 * We can sort just the interfaces implemented directly by this class, 3288 * but that doesn't seem like it would provide much of an advantage. I'm 3289 * not sure this is worthwhile. 3290 * 3291 * (This has been made largely obsolete by the interface cache mechanism.) 3292 */ 3293 3294 //dvmDumpClass(clazz); 3295 3296 result = true; 3297 3298bail: 3299 if (zapIftable) 3300 dvmLinearReadOnly(clazz->classLoader, clazz->iftable); 3301 if (zapVtable) 3302 dvmLinearReadOnly(clazz->classLoader, clazz->vtable); 3303 if (zapIfvipool) 3304 dvmLinearReadOnly(clazz->classLoader, clazz->ifviPool); 3305 return result; 3306} 3307 3308 3309/* 3310 * Provide "stub" implementations for methods without them. 3311 * 3312 * Currently we provide an implementation for all abstract methods that 3313 * throws an AbstractMethodError exception. This allows us to avoid an 3314 * explicit check for abstract methods in every virtual call. 3315 * 3316 * NOTE: for Miranda methods, the method declaration is a clone of what 3317 * was found in the interface class. That copy may already have had the 3318 * function pointer filled in, so don't be surprised if it's not NULL. 3319 * 3320 * NOTE: this sets the "native" flag, giving us an "abstract native" method, 3321 * which is nonsensical. Need to make sure that this doesn't escape the 3322 * VM. We can either mask it out in reflection calls, or copy "native" 3323 * into the high 16 bits of accessFlags and check that internally. 3324 */ 3325static bool insertMethodStubs(ClassObject* clazz) 3326{ 3327 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods); 3328 3329 Method* meth; 3330 int i; 3331 3332 meth = clazz->virtualMethods; 3333 for (i = 0; i < clazz->virtualMethodCount; i++, meth++) { 3334 if (dvmIsAbstractMethod(meth)) { 3335 assert(meth->insns == NULL); 3336 assert(meth->nativeFunc == NULL || 3337 meth->nativeFunc == (DalvikBridgeFunc)dvmAbstractMethodStub); 3338 3339 meth->accessFlags |= ACC_NATIVE; 3340 meth->nativeFunc = (DalvikBridgeFunc) dvmAbstractMethodStub; 3341 } 3342 } 3343 3344 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods); 3345 return true; 3346} 3347 3348 3349/* 3350 * Swap two instance fields. 3351 */ 3352static inline void swapField(InstField* pOne, InstField* pTwo) 3353{ 3354 InstField swap; 3355 3356 LOGVV(" --- swap '%s' and '%s'\n", pOne->field.name, pTwo->field.name); 3357 swap = *pOne; 3358 *pOne = *pTwo; 3359 *pTwo = swap; 3360} 3361 3362/* 3363 * Assign instance fields to u4 slots. 3364 * 3365 * The top portion of the instance field area is occupied by the superclass 3366 * fields, the bottom by the fields for this class. 3367 * 3368 * "long" and "double" fields occupy two adjacent slots. On some 3369 * architectures, 64-bit quantities must be 64-bit aligned, so we need to 3370 * arrange fields (or introduce padding) to ensure this. We assume the 3371 * fields of the topmost superclass (i.e. Object) are 64-bit aligned, so 3372 * we can just ensure that the offset is "even". To avoid wasting space, 3373 * we want to move non-reference 32-bit fields into gaps rather than 3374 * creating pad words. 3375 * 3376 * In the worst case we will waste 4 bytes, but because objects are 3377 * allocated on >= 64-bit boundaries, those bytes may well be wasted anyway 3378 * (assuming this is the most-derived class). 3379 * 3380 * Pad words are not represented in the field table, so the field table 3381 * itself does not change size. 3382 * 3383 * The number of field slots determines the size of the object, so we 3384 * set that here too. 3385 * 3386 * This function feels a little more complicated than I'd like, but it 3387 * has the property of moving the smallest possible set of fields, which 3388 * should reduce the time required to load a class. 3389 * 3390 * NOTE: reference fields *must* come first, or precacheReferenceOffsets() 3391 * will break. 3392 */ 3393static bool computeFieldOffsets(ClassObject* clazz) 3394{ 3395 int fieldOffset; 3396 int i, j; 3397 3398 dvmLinearReadWrite(clazz->classLoader, clazz->ifields); 3399 3400 if (clazz->super != NULL) 3401 fieldOffset = clazz->super->objectSize; 3402 else 3403 fieldOffset = offsetof(DataObject, instanceData); 3404 3405 LOGVV("--- computeFieldOffsets '%s'\n", clazz->descriptor); 3406 3407 //LOGI("OFFSETS fieldCount=%d\n", clazz->ifieldCount); 3408 //LOGI("dataobj, instance: %d\n", offsetof(DataObject, instanceData)); 3409 //LOGI("classobj, access: %d\n", offsetof(ClassObject, accessFlags)); 3410 //LOGI("super=%p, fieldOffset=%d\n", clazz->super, fieldOffset); 3411 3412 /* 3413 * Start by moving all reference fields to the front. 3414 */ 3415 clazz->ifieldRefCount = 0; 3416 j = clazz->ifieldCount - 1; 3417 for (i = 0; i < clazz->ifieldCount; i++) { 3418 InstField* pField = &clazz->ifields[i]; 3419 char c = pField->field.signature[0]; 3420 3421 if (c != '[' && c != 'L') { 3422 /* This isn't a reference field; see if any reference fields 3423 * follow this one. If so, we'll move it to this position. 3424 * (quicksort-style partitioning) 3425 */ 3426 while (j > i) { 3427 InstField* refField = &clazz->ifields[j--]; 3428 char rc = refField->field.signature[0]; 3429 3430 if (rc == '[' || rc == 'L') { 3431 /* Here's a reference field that follows at least one 3432 * non-reference field. Swap it with the current field. 3433 * (When this returns, "pField" points to the reference 3434 * field, and "refField" points to the non-ref field.) 3435 */ 3436 swapField(pField, refField); 3437 3438 /* Fix the signature. 3439 */ 3440 c = rc; 3441 3442 clazz->ifieldRefCount++; 3443 break; 3444 } 3445 } 3446 /* We may or may not have swapped a field. 3447 */ 3448 } else { 3449 /* This is a reference field. 3450 */ 3451 clazz->ifieldRefCount++; 3452 } 3453 3454 /* 3455 * If we've hit the end of the reference fields, break. 3456 */ 3457 if (c != '[' && c != 'L') 3458 break; 3459 3460 pField->byteOffset = fieldOffset; 3461 fieldOffset += sizeof(u4); 3462 LOGVV(" --- offset1 '%s'=%d\n", pField->field.name,pField->byteOffset); 3463 } 3464 3465 /* 3466 * Now we want to pack all of the double-wide fields together. If we're 3467 * not aligned, though, we want to shuffle one 32-bit field into place. 3468 * If we can't find one, we'll have to pad it. 3469 */ 3470 if (i != clazz->ifieldCount && (fieldOffset & 0x04) != 0) { 3471 LOGVV(" +++ not aligned\n"); 3472 3473 InstField* pField = &clazz->ifields[i]; 3474 char c = pField->field.signature[0]; 3475 3476 if (c != 'J' && c != 'D') { 3477 /* 3478 * The field that comes next is 32-bit, so just advance past it. 3479 */ 3480 assert(c != '[' && c != 'L'); 3481 pField->byteOffset = fieldOffset; 3482 fieldOffset += sizeof(u4); 3483 i++; 3484 LOGVV(" --- offset2 '%s'=%d\n", 3485 pField->field.name, pField->byteOffset); 3486 } else { 3487 /* 3488 * Next field is 64-bit, so search for a 32-bit field we can 3489 * swap into it. 3490 */ 3491 bool found = false; 3492 j = clazz->ifieldCount - 1; 3493 while (j > i) { 3494 InstField* singleField = &clazz->ifields[j--]; 3495 char rc = singleField->field.signature[0]; 3496 3497 if (rc != 'J' && rc != 'D') { 3498 swapField(pField, singleField); 3499 //c = rc; 3500 LOGVV(" +++ swapped '%s' for alignment\n", 3501 pField->field.name); 3502 pField->byteOffset = fieldOffset; 3503 fieldOffset += sizeof(u4); 3504 LOGVV(" --- offset3 '%s'=%d\n", 3505 pField->field.name, pField->byteOffset); 3506 found = true; 3507 i++; 3508 break; 3509 } 3510 } 3511 if (!found) { 3512 LOGV(" +++ inserting pad field in '%s'\n", clazz->descriptor); 3513 fieldOffset += sizeof(u4); 3514 } 3515 } 3516 } 3517 3518 /* 3519 * Alignment is good, shuffle any double-wide fields forward, and 3520 * finish assigning field offsets to all fields. 3521 */ 3522 assert(i == clazz->ifieldCount || (fieldOffset & 0x04) == 0); 3523 j = clazz->ifieldCount - 1; 3524 for ( ; i < clazz->ifieldCount; i++) { 3525 InstField* pField = &clazz->ifields[i]; 3526 char c = pField->field.signature[0]; 3527 3528 if (c != 'D' && c != 'J') { 3529 /* This isn't a double-wide field; see if any double fields 3530 * follow this one. If so, we'll move it to this position. 3531 * (quicksort-style partitioning) 3532 */ 3533 while (j > i) { 3534 InstField* doubleField = &clazz->ifields[j--]; 3535 char rc = doubleField->field.signature[0]; 3536 3537 if (rc == 'D' || rc == 'J') { 3538 /* Here's a double-wide field that follows at least one 3539 * non-double field. Swap it with the current field. 3540 * (When this returns, "pField" points to the reference 3541 * field, and "doubleField" points to the non-double field.) 3542 */ 3543 swapField(pField, doubleField); 3544 c = rc; 3545 3546 break; 3547 } 3548 } 3549 /* We may or may not have swapped a field. 3550 */ 3551 } else { 3552 /* This is a double-wide field, leave it be. 3553 */ 3554 } 3555 3556 pField->byteOffset = fieldOffset; 3557 LOGVV(" --- offset4 '%s'=%d\n", pField->field.name,pField->byteOffset); 3558 fieldOffset += sizeof(u4); 3559 if (c == 'J' || c == 'D') 3560 fieldOffset += sizeof(u4); 3561 } 3562 3563#ifndef NDEBUG 3564 /* Make sure that all reference fields appear before 3565 * non-reference fields, and all double-wide fields are aligned. 3566 */ 3567 j = 0; // seen non-ref 3568 for (i = 0; i < clazz->ifieldCount; i++) { 3569 InstField *pField = &clazz->ifields[i]; 3570 char c = pField->field.signature[0]; 3571 3572 if (c == 'D' || c == 'J') { 3573 assert((pField->byteOffset & 0x07) == 0); 3574 } 3575 3576 if (c != '[' && c != 'L') { 3577 if (!j) { 3578 assert(i == clazz->ifieldRefCount); 3579 j = 1; 3580 } 3581 } else if (j) { 3582 assert(false); 3583 } 3584 } 3585 if (!j) { 3586 assert(clazz->ifieldRefCount == clazz->ifieldCount); 3587 } 3588#endif 3589 3590 /* 3591 * We map a C struct directly on top of java/lang/Class objects. Make 3592 * sure we left enough room for the instance fields. 3593 */ 3594 assert(clazz != gDvm.classJavaLangClass || (size_t)fieldOffset < 3595 offsetof(ClassObject, instanceData) + sizeof(clazz->instanceData)); 3596 3597 clazz->objectSize = fieldOffset; 3598 3599 dvmLinearReadOnly(clazz->classLoader, clazz->ifields); 3600 return true; 3601} 3602 3603/* 3604 * Throw the VM-spec-mandated error when an exception is thrown during 3605 * class initialization. 3606 * 3607 * The safest way to do this is to call the ExceptionInInitializerError 3608 * constructor that takes a Throwable. 3609 * 3610 * [Do we want to wrap it if the original is an Error rather than 3611 * an Exception?] 3612 */ 3613static void throwClinitError(void) 3614{ 3615 Thread* self = dvmThreadSelf(); 3616 Object* exception; 3617 Object* eiie; 3618 3619 exception = dvmGetException(self); 3620 dvmAddTrackedAlloc(exception, self); 3621 dvmClearException(self); 3622 3623 if (gDvm.classJavaLangExceptionInInitializerError == NULL) { 3624 /* 3625 * Always resolves to same thing -- no race condition. 3626 */ 3627 gDvm.classJavaLangExceptionInInitializerError = 3628 dvmFindSystemClass( 3629 "Ljava/lang/ExceptionInInitializerError;"); 3630 if (gDvm.classJavaLangExceptionInInitializerError == NULL) { 3631 LOGE("Unable to prep java/lang/ExceptionInInitializerError\n"); 3632 goto fail; 3633 } 3634 3635 gDvm.methJavaLangExceptionInInitializerError_init = 3636 dvmFindDirectMethodByDescriptor(gDvm.classJavaLangExceptionInInitializerError, 3637 "<init>", "(Ljava/lang/Throwable;)V"); 3638 if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) { 3639 LOGE("Unable to prep java/lang/ExceptionInInitializerError\n"); 3640 goto fail; 3641 } 3642 } 3643 3644 eiie = dvmAllocObject(gDvm.classJavaLangExceptionInInitializerError, 3645 ALLOC_DEFAULT); 3646 if (eiie == NULL) 3647 goto fail; 3648 3649 /* 3650 * Construct the new object, and replace the exception with it. 3651 */ 3652 JValue unused; 3653 dvmCallMethod(self, gDvm.methJavaLangExceptionInInitializerError_init, 3654 eiie, &unused, exception); 3655 dvmSetException(self, eiie); 3656 dvmReleaseTrackedAlloc(eiie, NULL); 3657 dvmReleaseTrackedAlloc(exception, self); 3658 return; 3659 3660fail: /* restore original exception */ 3661 dvmSetException(self, exception); 3662 dvmReleaseTrackedAlloc(exception, self); 3663 return; 3664} 3665 3666/* 3667 * The class failed to initialize on a previous attempt, so we want to throw 3668 * a NoClassDefFoundError (v2 2.17.5). The exception to this rule is if we 3669 * failed in verification, in which case v2 5.4.1 says we need to re-throw 3670 * the previous error. 3671 */ 3672static void throwEarlierClassFailure(ClassObject* clazz) 3673{ 3674 LOGI("Rejecting re-init on previously-failed class %s v=%p\n", 3675 clazz->descriptor, clazz->verifyErrorClass); 3676 3677 if (clazz->verifyErrorClass == NULL) { 3678 dvmThrowExceptionWithClassMessage("Ljava/lang/NoClassDefFoundError;", 3679 clazz->descriptor); 3680 } else { 3681 dvmThrowExceptionByClassWithClassMessage(clazz->verifyErrorClass, 3682 clazz->descriptor); 3683 } 3684} 3685 3686/* 3687 * Initialize any static fields whose values are stored in 3688 * the DEX file. This must be done during class initialization. 3689 */ 3690static void initSFields(ClassObject* clazz) 3691{ 3692 Thread* self = dvmThreadSelf(); /* for dvmReleaseTrackedAlloc() */ 3693 DexFile* pDexFile; 3694 const DexClassDef* pClassDef; 3695 const DexEncodedArray* pValueList; 3696 EncodedArrayIterator iterator; 3697 int i; 3698 3699 if (clazz->sfieldCount == 0) { 3700 return; 3701 } 3702 if (clazz->pDvmDex == NULL) { 3703 /* generated class; any static fields should already be set up */ 3704 LOGV("Not initializing static fields in %s\n", clazz->descriptor); 3705 return; 3706 } 3707 pDexFile = clazz->pDvmDex->pDexFile; 3708 3709 pClassDef = dexFindClass(pDexFile, clazz->descriptor); 3710 assert(pClassDef != NULL); 3711 3712 pValueList = dexGetStaticValuesList(pDexFile, pClassDef); 3713 if (pValueList == NULL) { 3714 return; 3715 } 3716 3717 dvmEncodedArrayIteratorInitialize(&iterator, pValueList, clazz); 3718 3719 /* 3720 * Iterate over the initial values array, setting the corresponding 3721 * static field for each array element. 3722 */ 3723 3724 for (i = 0; dvmEncodedArrayIteratorHasNext(&iterator); i++) { 3725 AnnotationValue value; 3726 bool parsed = dvmEncodedArrayIteratorGetNext(&iterator, &value); 3727 StaticField* sfield = &clazz->sfields[i]; 3728 const char* descriptor = sfield->field.signature; 3729 bool needRelease = false; 3730 3731 if (! parsed) { 3732 /* 3733 * TODO: Eventually verification should attempt to ensure 3734 * that this can't happen at least due to a data integrity 3735 * problem. 3736 */ 3737 LOGE("Static initializer parse failed for %s at index %d", 3738 clazz->descriptor, i); 3739 dvmAbort(); 3740 } 3741 3742 /* Verify that the value we got was of a valid type. */ 3743 3744 switch (descriptor[0]) { 3745 case 'Z': parsed = (value.type == kDexAnnotationBoolean); break; 3746 case 'B': parsed = (value.type == kDexAnnotationByte); break; 3747 case 'C': parsed = (value.type == kDexAnnotationChar); break; 3748 case 'S': parsed = (value.type == kDexAnnotationShort); break; 3749 case 'I': parsed = (value.type == kDexAnnotationInt); break; 3750 case 'J': parsed = (value.type == kDexAnnotationLong); break; 3751 case 'F': parsed = (value.type == kDexAnnotationFloat); break; 3752 case 'D': parsed = (value.type == kDexAnnotationDouble); break; 3753 case '[': parsed = (value.type == kDexAnnotationNull); break; 3754 case 'L': { 3755 switch (value.type) { 3756 case kDexAnnotationNull: { 3757 /* No need for further tests. */ 3758 break; 3759 } 3760 case kDexAnnotationString: { 3761 parsed = 3762 (strcmp(descriptor, "Ljava/lang/String;") == 0); 3763 needRelease = true; 3764 break; 3765 } 3766 case kDexAnnotationType: { 3767 parsed = 3768 (strcmp(descriptor, "Ljava/lang/Class;") == 0); 3769 needRelease = true; 3770 break; 3771 } 3772 default: { 3773 parsed = false; 3774 break; 3775 } 3776 } 3777 break; 3778 } 3779 default: { 3780 parsed = false; 3781 break; 3782 } 3783 } 3784 3785 if (parsed) { 3786 /* 3787 * All's well, so store the value. Note: This always 3788 * stores the full width of a JValue, even though most of 3789 * the time only the first word is needed. 3790 */ 3791 sfield->value = value.value; 3792 if (needRelease) { 3793 dvmReleaseTrackedAlloc(value.value.l, self); 3794 } 3795 } else { 3796 /* 3797 * Something up above had a problem. TODO: See comment 3798 * above the switch about verfication. 3799 */ 3800 LOGE("Bogus static initialization: value type %d in field type " 3801 "%s for %s at index %d", 3802 value.type, descriptor, clazz->descriptor, i); 3803 dvmAbort(); 3804 } 3805 } 3806} 3807 3808 3809/* 3810 * Determine whether "descriptor" yields the same class object in the 3811 * context of clazz1 and clazz2. 3812 * 3813 * The caller must hold gDvm.loadedClasses. 3814 * 3815 * Returns "true" if they match. 3816 */ 3817static bool compareDescriptorClasses(const char* descriptor, 3818 const ClassObject* clazz1, const ClassObject* clazz2) 3819{ 3820 ClassObject* result1; 3821 ClassObject* result2; 3822 3823 /* 3824 * Do the first lookup by name. 3825 */ 3826 result1 = dvmFindClassNoInit(descriptor, clazz1->classLoader); 3827 3828 /* 3829 * We can skip a second lookup by name if the second class loader is 3830 * in the initiating loader list of the class object we retrieved. 3831 * (This means that somebody already did a lookup of this class through 3832 * the second loader, and it resolved to the same class.) If it's not 3833 * there, we may simply not have had an opportunity to add it yet, so 3834 * we do the full lookup. 3835 * 3836 * The initiating loader test should catch the majority of cases 3837 * (in particular, the zillions of references to String/Object). 3838 * 3839 * Unfortunately we're still stuck grabbing a mutex to do the lookup. 3840 * 3841 * For this to work, the superclass/interface should be the first 3842 * argument, so that way if it's from the bootstrap loader this test 3843 * will work. (The bootstrap loader, by definition, never shows up 3844 * as the initiating loader of a class defined by some other loader.) 3845 */ 3846 dvmHashTableLock(gDvm.loadedClasses); 3847 bool isInit = dvmLoaderInInitiatingList(result1, clazz2->classLoader); 3848 dvmHashTableUnlock(gDvm.loadedClasses); 3849 3850 if (isInit) { 3851 //printf("%s(obj=%p) / %s(cl=%p): initiating\n", 3852 // result1->descriptor, result1, 3853 // clazz2->descriptor, clazz2->classLoader); 3854 return true; 3855 } else { 3856 //printf("%s(obj=%p) / %s(cl=%p): RAW\n", 3857 // result1->descriptor, result1, 3858 // clazz2->descriptor, clazz2->classLoader); 3859 result2 = dvmFindClassNoInit(descriptor, clazz2->classLoader); 3860 } 3861 3862 if (result1 == NULL || result2 == NULL) { 3863 dvmClearException(dvmThreadSelf()); 3864 if (result1 == result2) { 3865 /* 3866 * Neither class loader could find this class. Apparently it 3867 * doesn't exist. 3868 * 3869 * We can either throw some sort of exception now, or just 3870 * assume that it'll fail later when something actually tries 3871 * to use the class. For strict handling we should throw now, 3872 * because a "tricky" class loader could start returning 3873 * something later, and a pair of "tricky" loaders could set 3874 * us up for confusion. 3875 * 3876 * I'm not sure if we're allowed to complain about nonexistent 3877 * classes in method signatures during class init, so for now 3878 * this will just return "true" and let nature take its course. 3879 */ 3880 return true; 3881 } else { 3882 /* only one was found, so clearly they're not the same */ 3883 return false; 3884 } 3885 } 3886 3887 return result1 == result2; 3888} 3889 3890/* 3891 * For every component in the method descriptor, resolve the class in the 3892 * context of the two classes and compare the results. 3893 * 3894 * For best results, the "superclass" class should be first. 3895 * 3896 * Returns "true" if the classes match, "false" otherwise. 3897 */ 3898static bool checkMethodDescriptorClasses(const Method* meth, 3899 const ClassObject* clazz1, const ClassObject* clazz2) 3900{ 3901 DexParameterIterator iterator; 3902 const char* descriptor; 3903 3904 /* walk through the list of parameters */ 3905 dexParameterIteratorInit(&iterator, &meth->prototype); 3906 while (true) { 3907 descriptor = dexParameterIteratorNextDescriptor(&iterator); 3908 3909 if (descriptor == NULL) 3910 break; 3911 3912 if (descriptor[0] == 'L' || descriptor[0] == '[') { 3913 /* non-primitive type */ 3914 if (!compareDescriptorClasses(descriptor, clazz1, clazz2)) 3915 return false; 3916 } 3917 } 3918 3919 /* check the return type */ 3920 descriptor = dexProtoGetReturnType(&meth->prototype); 3921 if (descriptor[0] == 'L' || descriptor[0] == '[') { 3922 if (!compareDescriptorClasses(descriptor, clazz1, clazz2)) 3923 return false; 3924 } 3925 return true; 3926} 3927 3928/* 3929 * Validate the descriptors in the superclass and interfaces. 3930 * 3931 * What we need to do is ensure that the classes named in the method 3932 * descriptors in our ancestors and ourselves resolve to the same class 3933 * objects. The only time this matters is when the classes come from 3934 * different class loaders, and the resolver might come up with a 3935 * different answer for the same class name depending on context. 3936 * 3937 * We don't need to check to see if an interface's methods match with 3938 * its superinterface's methods, because you can't instantiate an 3939 * interface and do something inappropriate with it. If interface I1 3940 * extends I2 and is implemented by C, and I1 and I2 are in separate 3941 * class loaders and have conflicting views of other classes, we will 3942 * catch the conflict when we process C. Anything that implements I1 is 3943 * doomed to failure, but we don't need to catch that while processing I1. 3944 * 3945 * On failure, throws an exception and returns "false". 3946 */ 3947static bool validateSuperDescriptors(const ClassObject* clazz) 3948{ 3949 int i; 3950 3951 if (dvmIsInterfaceClass(clazz)) 3952 return true; 3953 3954 /* 3955 * Start with the superclass-declared methods. 3956 */ 3957 if (clazz->super != NULL && 3958 clazz->classLoader != clazz->super->classLoader) 3959 { 3960 /* 3961 * Walk through every method declared in the superclass, and 3962 * compare resolved descriptor components. We pull the Method 3963 * structs out of the vtable. It doesn't matter whether we get 3964 * the struct from the parent or child, since we just need the 3965 * UTF-8 descriptor, which must match. 3966 * 3967 * We need to do this even for the stuff inherited from Object, 3968 * because it's possible that the new class loader has redefined 3969 * a basic class like String. 3970 */ 3971 const Method* meth; 3972 3973 //printf("Checking %s %p vs %s %p\n", 3974 // clazz->descriptor, clazz->classLoader, 3975 // clazz->super->descriptor, clazz->super->classLoader); 3976 for (i = clazz->super->vtableCount - 1; i >= 0; i--) { 3977 meth = clazz->vtable[i]; 3978 if (!checkMethodDescriptorClasses(meth, clazz->super, clazz)) { 3979 LOGW("Method mismatch: %s in %s (cl=%p) and super %s (cl=%p)\n", 3980 meth->name, clazz->descriptor, clazz->classLoader, 3981 clazz->super->descriptor, clazz->super->classLoader); 3982 dvmThrowException("Ljava/lang/LinkageError;", 3983 "Classes resolve differently in superclass"); 3984 return false; 3985 } 3986 } 3987 } 3988 3989 /* 3990 * Check all interfaces we implement. 3991 */ 3992 for (i = 0; i < clazz->iftableCount; i++) { 3993 const InterfaceEntry* iftable = &clazz->iftable[i]; 3994 3995 if (clazz->classLoader != iftable->clazz->classLoader) { 3996 const ClassObject* iface = iftable->clazz; 3997 int j; 3998 3999 for (j = 0; j < iface->virtualMethodCount; j++) { 4000 const Method* meth; 4001 int vtableIndex; 4002 4003 vtableIndex = iftable->methodIndexArray[j]; 4004 meth = clazz->vtable[vtableIndex]; 4005 4006 if (!checkMethodDescriptorClasses(meth, iface, clazz)) { 4007 LOGW("Method mismatch: %s in %s (cl=%p) and " 4008 "iface %s (cl=%p)\n", 4009 meth->name, clazz->descriptor, clazz->classLoader, 4010 iface->descriptor, iface->classLoader); 4011 dvmThrowException("Ljava/lang/LinkageError;", 4012 "Classes resolve differently in interface"); 4013 return false; 4014 } 4015 } 4016 } 4017 } 4018 4019 return true; 4020} 4021 4022/* 4023 * Returns true if the class is being initialized by us (which means that 4024 * calling dvmInitClass will return immediately after fiddling with locks). 4025 * 4026 * There isn't a race here, because either clazz->initThreadId won't match 4027 * us, or it will and it was set in the same thread. 4028 */ 4029bool dvmIsClassInitializing(const ClassObject* clazz) 4030{ 4031 return (clazz->status == CLASS_INITIALIZING && 4032 clazz->initThreadId == dvmThreadSelf()->threadId); 4033} 4034 4035/* 4036 * If a class has not been initialized, do so by executing the code in 4037 * <clinit>. The sequence is described in the VM spec v2 2.17.5. 4038 * 4039 * It is possible for multiple threads to arrive here simultaneously, so 4040 * we need to lock the class while we check stuff. We know that no 4041 * interpreted code has access to the class yet, so we can use the class's 4042 * monitor lock. 4043 * 4044 * We will often be called recursively, e.g. when the <clinit> code resolves 4045 * one of its fields, the field resolution will try to initialize the class. 4046 * 4047 * This can get very interesting if a class has a static field initialized 4048 * to a new instance of itself. <clinit> will end up calling <init> on 4049 * the members it is initializing, which is fine unless it uses the contents 4050 * of static fields to initialize instance fields. This will leave the 4051 * static-referenced objects in a partially initialized state. This is 4052 * reasonably rare and can sometimes be cured with proper field ordering. 4053 * 4054 * On failure, returns "false" with an exception raised. 4055 * 4056 * ----- 4057 * 4058 * It is possible to cause a deadlock by having a situation like this: 4059 * class A { static { sleep(10000); new B(); } } 4060 * class B { static { sleep(10000); new A(); } } 4061 * new Thread() { public void run() { new A(); } }.start(); 4062 * new Thread() { public void run() { new B(); } }.start(); 4063 * This appears to be expected under the spec. 4064 * 4065 * The interesting question is what to do if somebody calls Thread.interrupt() 4066 * on one of the deadlocked threads. According to the VM spec, they're both 4067 * sitting in "wait". Should the interrupt code quietly raise the 4068 * "interrupted" flag, or should the "wait" return immediately with an 4069 * exception raised? 4070 * 4071 * This gets a little murky. The VM spec says we call "wait", and the 4072 * spec for Thread.interrupt says Object.wait is interruptible. So it 4073 * seems that, if we get unlucky and interrupt class initialization, we 4074 * are expected to throw (which gets converted to ExceptionInInitializerError 4075 * since InterruptedException is checked). 4076 * 4077 * There are a couple of problems here. First, all threads are expected to 4078 * present a consistent view of class initialization, so we can't have it 4079 * fail in one thread and succeed in another. Second, once a class fails 4080 * to initialize, it must *always* fail. This means that a stray interrupt() 4081 * call could render a class unusable for the lifetime of the VM. 4082 * 4083 * In most cases -- the deadlock example above being a counter-example -- 4084 * the interrupting thread can't tell whether the target thread handled 4085 * the initialization itself or had to wait while another thread did the 4086 * work. Refusing to interrupt class initialization is, in most cases, 4087 * not something that a program can reliably detect. 4088 * 4089 * On the assumption that interrupting class initialization is highly 4090 * undesirable in most circumstances, and that failing to do so does not 4091 * deviate from the spec in a meaningful way, we don't allow class init 4092 * to be interrupted by Thread.interrupt(). 4093 */ 4094bool dvmInitClass(ClassObject* clazz) 4095{ 4096#if LOG_CLASS_LOADING 4097 bool initializedByUs = false; 4098#endif 4099 4100 Thread* self = dvmThreadSelf(); 4101 const Method* method; 4102 4103 dvmLockObject(self, (Object*) clazz); 4104 assert(dvmIsClassLinked(clazz) || clazz->status == CLASS_ERROR); 4105 4106 /* 4107 * If the class hasn't been verified yet, do so now. 4108 */ 4109 if (clazz->status < CLASS_VERIFIED) { 4110 /* 4111 * If we're in an "erroneous" state, throw an exception and bail. 4112 */ 4113 if (clazz->status == CLASS_ERROR) { 4114 throwEarlierClassFailure(clazz); 4115 goto bail_unlock; 4116 } 4117 4118 assert(clazz->status == CLASS_RESOLVED); 4119 assert(!IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED)); 4120 4121 if (gDvm.classVerifyMode == VERIFY_MODE_NONE || 4122 (gDvm.classVerifyMode == VERIFY_MODE_REMOTE && 4123 clazz->classLoader == NULL)) 4124 { 4125 LOGV("+++ not verifying class %s (cl=%p)\n", 4126 clazz->descriptor, clazz->classLoader); 4127 goto noverify; 4128 } 4129 4130 if (!gDvm.optimizing) 4131 LOGV("+++ late verify on %s\n", clazz->descriptor); 4132 4133 /* 4134 * We're not supposed to optimize an unverified class, but during 4135 * development this mode was useful. We can't verify an optimized 4136 * class because the optimization process discards information. 4137 */ 4138 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) { 4139 LOGW("Class '%s' was optimized without verification; " 4140 "not verifying now\n", 4141 clazz->descriptor); 4142 LOGW(" ('rm /data/dalvik-cache/*' and restart to fix this)"); 4143 goto verify_failed; 4144 } 4145 4146 clazz->status = CLASS_VERIFYING; 4147 if (!dvmVerifyClass(clazz, VERIFY_DEFAULT)) { 4148verify_failed: 4149 dvmThrowExceptionWithClassMessage("Ljava/lang/VerifyError;", 4150 clazz->descriptor); 4151 clazz->verifyErrorClass = dvmGetException(self)->clazz; 4152 clazz->status = CLASS_ERROR; 4153 goto bail_unlock; 4154 } 4155 4156 clazz->status = CLASS_VERIFIED; 4157 } 4158noverify: 4159 4160 if (clazz->status == CLASS_INITIALIZED) 4161 goto bail_unlock; 4162 4163 while (clazz->status == CLASS_INITIALIZING) { 4164 /* we caught somebody else in the act; was it us? */ 4165 if (clazz->initThreadId == self->threadId) { 4166 //LOGV("HEY: found a recursive <clinit>\n"); 4167 goto bail_unlock; 4168 } 4169 4170 if (dvmCheckException(self)) { 4171 LOGW("GLITCH: exception pending at start of class init\n"); 4172 dvmAbort(); 4173 } 4174 4175 /* 4176 * Wait for the other thread to finish initialization. We pass 4177 * "false" for the "interruptShouldThrow" arg so it doesn't throw 4178 * an exception on interrupt. 4179 */ 4180 dvmObjectWait(self, (Object*) clazz, 0, 0, false); 4181 4182 /* 4183 * When we wake up, repeat the test for init-in-progress. If there's 4184 * an exception pending (only possible if "interruptShouldThrow" 4185 * was set), bail out. 4186 */ 4187 if (dvmCheckException(self)) { 4188 LOGI("Class init of '%s' failing with wait() exception\n", 4189 clazz->descriptor); 4190 /* 4191 * TODO: this is bogus, because it means the two threads have a 4192 * different idea of the class status. We need to flag the 4193 * class as bad and ensure that the initializer thread respects 4194 * our notice. If we get lucky and wake up after the class has 4195 * finished initialization but before being woken, we have to 4196 * swallow the exception, perhaps raising thread->interrupted 4197 * to preserve semantics. 4198 * 4199 * Since we're not currently allowing interrupts, this should 4200 * never happen and we don't need to fix this. 4201 */ 4202 assert(false); 4203 throwClinitError(); 4204 clazz->status = CLASS_ERROR; 4205 goto bail_unlock; 4206 } 4207 if (clazz->status == CLASS_INITIALIZING) { 4208 LOGI("Waiting again for class init\n"); 4209 continue; 4210 } 4211 assert(clazz->status == CLASS_INITIALIZED || 4212 clazz->status == CLASS_ERROR); 4213 if (clazz->status == CLASS_ERROR) { 4214 /* 4215 * The caller wants an exception, but it was thrown in a 4216 * different thread. Synthesize one here. 4217 */ 4218 dvmThrowException("Ljava/lang/UnsatisfiedLinkError;", 4219 "(<clinit> failed, see exception in other thread)"); 4220 } 4221 goto bail_unlock; 4222 } 4223 4224 /* see if we failed previously */ 4225 if (clazz->status == CLASS_ERROR) { 4226 // might be wise to unlock before throwing; depends on which class 4227 // it is that we have locked 4228 dvmUnlockObject(self, (Object*) clazz); 4229 throwEarlierClassFailure(clazz); 4230 return false; 4231 } 4232 4233 /* 4234 * We're ready to go, and have exclusive access to the class. 4235 * 4236 * Before we start initialization, we need to do one extra bit of 4237 * validation: make sure that the methods declared here match up 4238 * with our superclass and interfaces. We know that the UTF-8 4239 * descriptors match, but classes from different class loaders can 4240 * have the same name. 4241 * 4242 * We do this now, rather than at load/link time, for the same reason 4243 * that we defer verification. 4244 * 4245 * It's unfortunate that we need to do this at all, but we risk 4246 * mixing reference types with identical names (see Dalvik test 068). 4247 */ 4248 if (!validateSuperDescriptors(clazz)) { 4249 assert(dvmCheckException(self)); 4250 clazz->status = CLASS_ERROR; 4251 goto bail_unlock; 4252 } 4253 4254 /* 4255 * Let's initialize this thing. 4256 * 4257 * We unlock the object so that other threads can politely sleep on 4258 * our mutex with Object.wait(), instead of hanging or spinning trying 4259 * to grab our mutex. 4260 */ 4261 assert(clazz->status < CLASS_INITIALIZING); 4262 4263#if LOG_CLASS_LOADING 4264 // We started initializing. 4265 logClassLoad('+', clazz); 4266 initializedByUs = true; 4267#endif 4268 4269 clazz->status = CLASS_INITIALIZING; 4270 clazz->initThreadId = self->threadId; 4271 dvmUnlockObject(self, (Object*) clazz); 4272 4273 /* init our superclass */ 4274 if (clazz->super != NULL && clazz->super->status != CLASS_INITIALIZED) { 4275 assert(!dvmIsInterfaceClass(clazz)); 4276 if (!dvmInitClass(clazz->super)) { 4277 assert(dvmCheckException(self)); 4278 clazz->status = CLASS_ERROR; 4279 /* wake up anybody who started waiting while we were unlocked */ 4280 dvmLockObject(self, (Object*) clazz); 4281 goto bail_notify; 4282 } 4283 } 4284 4285 /* Initialize any static fields whose values are 4286 * stored in the Dex file. This should include all of the 4287 * simple "final static" fields, which are required to 4288 * be initialized first. (vmspec 2 sec 2.17.5 item 8) 4289 * More-complicated final static fields should be set 4290 * at the beginning of <clinit>; all we can do is trust 4291 * that the compiler did the right thing. 4292 */ 4293 initSFields(clazz); 4294 4295 /* Execute any static initialization code. 4296 */ 4297 method = dvmFindDirectMethodByDescriptor(clazz, "<clinit>", "()V"); 4298 if (method == NULL) { 4299 LOGVV("No <clinit> found for %s\n", clazz->descriptor); 4300 } else { 4301 LOGVV("Invoking %s.<clinit>\n", clazz->descriptor); 4302 JValue unused; 4303 dvmCallMethod(self, method, NULL, &unused); 4304 } 4305 4306 if (dvmCheckException(self)) { 4307 /* 4308 * We've had an exception thrown during static initialization. We 4309 * need to throw an ExceptionInInitializerError, but we want to 4310 * tuck the original exception into the "cause" field. 4311 */ 4312 LOGW("Exception %s thrown during %s.<clinit>\n", 4313 (dvmGetException(self)->clazz)->descriptor, clazz->descriptor); 4314 throwClinitError(); 4315 //LOGW("+++ replaced\n"); 4316 4317 dvmLockObject(self, (Object*) clazz); 4318 clazz->status = CLASS_ERROR; 4319 } else { 4320 /* success! */ 4321 dvmLockObject(self, (Object*) clazz); 4322 clazz->status = CLASS_INITIALIZED; 4323 LOGVV("Initialized class: %s\n", clazz->descriptor); 4324 } 4325 4326bail_notify: 4327 /* 4328 * Notify anybody waiting on the object. 4329 */ 4330 dvmObjectNotifyAll(self, (Object*) clazz); 4331 4332bail_unlock: 4333 4334#if LOG_CLASS_LOADING 4335 if (initializedByUs) { 4336 // We finished initializing. 4337 logClassLoad('-', clazz); 4338 } 4339#endif 4340 4341 dvmUnlockObject(self, (Object*) clazz); 4342 4343 return (clazz->status != CLASS_ERROR); 4344} 4345 4346/* 4347 * Replace method->nativeFunc and method->insns with new values. This is 4348 * performed on resolution of a native method. 4349 */ 4350void dvmSetNativeFunc(const Method* method, DalvikBridgeFunc func, 4351 const u2* insns) 4352{ 4353 ClassObject* clazz = method->clazz; 4354 4355 /* just open up both; easier that way */ 4356 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods); 4357 dvmLinearReadWrite(clazz->classLoader, clazz->directMethods); 4358 4359 ((Method*)method)->nativeFunc = func; 4360 ((Method*)method)->insns = insns; 4361 4362 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods); 4363 dvmLinearReadOnly(clazz->classLoader, clazz->directMethods); 4364} 4365 4366/* 4367 * Add a RegisterMap to a Method. This is done when we verify the class 4368 * and compute the register maps at class initialization time, which means 4369 * that "pMap" is on the heap and should be freed when the Method is 4370 * discarded. 4371 */ 4372void dvmSetRegisterMap(Method* method, const RegisterMap* pMap) 4373{ 4374 ClassObject* clazz = method->clazz; 4375 4376 if (method->registerMap != NULL) { 4377 LOGW("WARNING: registerMap already set for %s.%s\n", 4378 method->clazz->descriptor, method->name); 4379 /* keep going */ 4380 } 4381 4382 /* might be virtual or direct */ 4383 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods); 4384 dvmLinearReadWrite(clazz->classLoader, clazz->directMethods); 4385 4386 method->registerMap = pMap; 4387 4388 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods); 4389 dvmLinearReadOnly(clazz->classLoader, clazz->directMethods); 4390} 4391 4392/* 4393 * dvmHashForeach callback. A nonzero return value causes foreach to 4394 * bail out. 4395 */ 4396static int findClassCallback(void* vclazz, void* arg) 4397{ 4398 ClassObject* clazz = vclazz; 4399 const char* descriptor = (const char*) arg; 4400 4401 if (strcmp(clazz->descriptor, descriptor) == 0) 4402 return (int) clazz; 4403 return 0; 4404} 4405 4406/* 4407 * Find a loaded class by descriptor. Returns the first one found. 4408 * Because there can be more than one if class loaders are involved, 4409 * this is not an especially good API. (Currently only used by the 4410 * debugger and "checking" JNI.) 4411 * 4412 * "descriptor" should have the form "Ljava/lang/Class;" or 4413 * "[Ljava/lang/Class;", i.e. a descriptor and not an internal-form 4414 * class name. 4415 */ 4416ClassObject* dvmFindLoadedClass(const char* descriptor) 4417{ 4418 int result; 4419 4420 dvmHashTableLock(gDvm.loadedClasses); 4421 result = dvmHashForeach(gDvm.loadedClasses, findClassCallback, 4422 (void*) descriptor); 4423 dvmHashTableUnlock(gDvm.loadedClasses); 4424 4425 return (ClassObject*) result; 4426} 4427 4428/* 4429 * Retrieve the system (a/k/a application) class loader. 4430 */ 4431Object* dvmGetSystemClassLoader(void) 4432{ 4433 ClassObject* clazz; 4434 Method* getSysMeth; 4435 Object* loader; 4436 4437 clazz = dvmFindSystemClass("Ljava/lang/ClassLoader;"); 4438 if (clazz == NULL) 4439 return NULL; 4440 4441 getSysMeth = dvmFindDirectMethodByDescriptor(clazz, "getSystemClassLoader", 4442 "()Ljava/lang/ClassLoader;"); 4443 if (getSysMeth == NULL) 4444 return NULL; 4445 4446 JValue result; 4447 dvmCallMethod(dvmThreadSelf(), getSysMeth, NULL, &result); 4448 loader = (Object*)result.l; 4449 return loader; 4450} 4451 4452 4453/* 4454 * This is a dvmHashForeach callback. 4455 */ 4456static int dumpClass(void* vclazz, void* varg) 4457{ 4458 const ClassObject* clazz = (const ClassObject*) vclazz; 4459 const ClassObject* super; 4460 int flags = (int) varg; 4461 char* desc; 4462 int i; 4463 4464 if (clazz == NULL) { 4465 LOGI("dumpClass: ignoring request to dump null class\n"); 4466 return 0; 4467 } 4468 4469 if ((flags & kDumpClassFullDetail) == 0) { 4470 bool showInit = (flags & kDumpClassInitialized) != 0; 4471 bool showLoader = (flags & kDumpClassClassLoader) != 0; 4472 const char* initStr; 4473 4474 initStr = dvmIsClassInitialized(clazz) ? "true" : "false"; 4475 4476 if (showInit && showLoader) 4477 LOGI("%s %p %s\n", clazz->descriptor, clazz->classLoader, initStr); 4478 else if (showInit) 4479 LOGI("%s %s\n", clazz->descriptor, initStr); 4480 else if (showLoader) 4481 LOGI("%s %p\n", clazz->descriptor, clazz->classLoader); 4482 else 4483 LOGI("%s\n", clazz->descriptor); 4484 4485 return 0; 4486 } 4487 4488 /* clazz->super briefly holds the superclass index during class prep */ 4489 if ((u4)clazz->super > 0x10000 && (u4) clazz->super != (u4)-1) 4490 super = clazz->super; 4491 else 4492 super = NULL; 4493 4494 LOGI("----- %s '%s' cl=%p ser=0x%08x -----\n", 4495 dvmIsInterfaceClass(clazz) ? "interface" : "class", 4496 clazz->descriptor, clazz->classLoader, clazz->serialNumber); 4497 LOGI(" objectSize=%d (%d from super)\n", (int) clazz->objectSize, 4498 super != NULL ? (int) super->objectSize : -1); 4499 LOGI(" access=0x%04x.%04x\n", clazz->accessFlags >> 16, 4500 clazz->accessFlags & JAVA_FLAGS_MASK); 4501 if (super != NULL) 4502 LOGI(" super='%s' (cl=%p)\n", super->descriptor, super->classLoader); 4503 if (dvmIsArrayClass(clazz)) { 4504 LOGI(" dimensions=%d elementClass=%s\n", 4505 clazz->arrayDim, clazz->elementClass->descriptor); 4506 } 4507 if (clazz->iftableCount > 0) { 4508 LOGI(" interfaces (%d):\n", clazz->iftableCount); 4509 for (i = 0; i < clazz->iftableCount; i++) { 4510 InterfaceEntry* ent = &clazz->iftable[i]; 4511 int j; 4512 4513 LOGI(" %2d: %s (cl=%p)\n", 4514 i, ent->clazz->descriptor, ent->clazz->classLoader); 4515 4516 /* enable when needed */ 4517 if (false && ent->methodIndexArray != NULL) { 4518 for (j = 0; j < ent->clazz->virtualMethodCount; j++) 4519 LOGI(" %2d: %d %s %s\n", 4520 j, ent->methodIndexArray[j], 4521 ent->clazz->virtualMethods[j].name, 4522 clazz->vtable[ent->methodIndexArray[j]]->name); 4523 } 4524 } 4525 } 4526 if (!dvmIsInterfaceClass(clazz)) { 4527 LOGI(" vtable (%d entries, %d in super):\n", clazz->vtableCount, 4528 super != NULL ? super->vtableCount : 0); 4529 for (i = 0; i < clazz->vtableCount; i++) { 4530 desc = dexProtoCopyMethodDescriptor(&clazz->vtable[i]->prototype); 4531 LOGI(" %s%2d: %p %20s %s\n", 4532 (i != clazz->vtable[i]->methodIndex) ? "*** " : "", 4533 (u4) clazz->vtable[i]->methodIndex, clazz->vtable[i], 4534 clazz->vtable[i]->name, desc); 4535 free(desc); 4536 } 4537 LOGI(" direct methods (%d entries):\n", clazz->directMethodCount); 4538 for (i = 0; i < clazz->directMethodCount; i++) { 4539 desc = dexProtoCopyMethodDescriptor( 4540 &clazz->directMethods[i].prototype); 4541 LOGI(" %2d: %20s %s\n", i, clazz->directMethods[i].name, 4542 desc); 4543 free(desc); 4544 } 4545 } else { 4546 LOGI(" interface methods (%d):\n", clazz->virtualMethodCount); 4547 for (i = 0; i < clazz->virtualMethodCount; i++) { 4548 desc = dexProtoCopyMethodDescriptor( 4549 &clazz->virtualMethods[i].prototype); 4550 LOGI(" %2d: %2d %20s %s\n", i, 4551 (u4) clazz->virtualMethods[i].methodIndex, 4552 clazz->virtualMethods[i].name, 4553 desc); 4554 free(desc); 4555 } 4556 } 4557 if (clazz->sfieldCount > 0) { 4558 LOGI(" static fields (%d entries):\n", clazz->sfieldCount); 4559 for (i = 0; i < clazz->sfieldCount; i++) { 4560 LOGI(" %2d: %20s %s\n", i, clazz->sfields[i].field.name, 4561 clazz->sfields[i].field.signature); 4562 } 4563 } 4564 if (clazz->ifieldCount > 0) { 4565 LOGI(" instance fields (%d entries):\n", clazz->ifieldCount); 4566 for (i = 0; i < clazz->ifieldCount; i++) { 4567 LOGI(" %2d: %20s %s\n", i, clazz->ifields[i].field.name, 4568 clazz->ifields[i].field.signature); 4569 } 4570 } 4571 return 0; 4572} 4573 4574/* 4575 * Dump the contents of a single class. 4576 * 4577 * Pass kDumpClassFullDetail into "flags" to get lots of detail. 4578 */ 4579void dvmDumpClass(const ClassObject* clazz, int flags) 4580{ 4581 dumpClass((void*) clazz, (void*) flags); 4582} 4583 4584/* 4585 * Dump the contents of all classes. 4586 */ 4587void dvmDumpAllClasses(int flags) 4588{ 4589 dvmHashTableLock(gDvm.loadedClasses); 4590 dvmHashForeach(gDvm.loadedClasses, dumpClass, (void*) flags); 4591 dvmHashTableUnlock(gDvm.loadedClasses); 4592} 4593 4594/* 4595 * Get the number of loaded classes 4596 */ 4597int dvmGetNumLoadedClasses() 4598{ 4599 int count; 4600 dvmHashTableLock(gDvm.loadedClasses); 4601 count = dvmHashTableNumEntries(gDvm.loadedClasses); 4602 dvmHashTableUnlock(gDvm.loadedClasses); 4603 return count; 4604} 4605 4606/* 4607 * Write some statistics to the log file. 4608 */ 4609void dvmDumpLoaderStats(const char* msg) 4610{ 4611 LOGV("VM stats (%s): cls=%d/%d meth=%d ifld=%d sfld=%d linear=%d\n", 4612 msg, gDvm.numLoadedClasses, dvmHashTableNumEntries(gDvm.loadedClasses), 4613 gDvm.numDeclaredMethods, gDvm.numDeclaredInstFields, 4614 gDvm.numDeclaredStaticFields, gDvm.pBootLoaderAlloc->curOffset); 4615#ifdef COUNT_PRECISE_METHODS 4616 LOGI("GC precise methods: %d\n", 4617 dvmPointerSetGetCount(gDvm.preciseMethods)); 4618#endif 4619} 4620 4621#ifdef PROFILE_FIELD_ACCESS 4622/* 4623 * Dump the field access counts for all fields in this method. 4624 */ 4625static int dumpAccessCounts(void* vclazz, void* varg) 4626{ 4627 const ClassObject* clazz = (const ClassObject*) vclazz; 4628 int i; 4629 4630 for (i = 0; i < clazz->ifieldCount; i++) { 4631 Field* field = &clazz->ifields[i].field; 4632 4633 if (field->gets != 0) 4634 printf("GI %d %s.%s\n", field->gets, 4635 field->clazz->descriptor, field->name); 4636 if (field->puts != 0) 4637 printf("PI %d %s.%s\n", field->puts, 4638 field->clazz->descriptor, field->name); 4639 } 4640 for (i = 0; i < clazz->sfieldCount; i++) { 4641 Field* field = &clazz->sfields[i].field; 4642 4643 if (field->gets != 0) 4644 printf("GS %d %s.%s\n", field->gets, 4645 field->clazz->descriptor, field->name); 4646 if (field->puts != 0) 4647 printf("PS %d %s.%s\n", field->puts, 4648 field->clazz->descriptor, field->name); 4649 } 4650 4651 return 0; 4652} 4653 4654/* 4655 * Dump the field access counts for all loaded classes. 4656 */ 4657void dvmDumpFieldAccessCounts(void) 4658{ 4659 dvmHashTableLock(gDvm.loadedClasses); 4660 dvmHashForeach(gDvm.loadedClasses, dumpAccessCounts, NULL); 4661 dvmHashTableUnlock(gDvm.loadedClasses); 4662} 4663#endif 4664 4665 4666/* 4667 * Mark all classes associated with the built-in loader. 4668 */ 4669static int markClassObject(void *clazz, void *arg) 4670{ 4671 UNUSED_PARAMETER(arg); 4672 4673 dvmMarkObjectNonNull((Object *)clazz); 4674 return 0; 4675} 4676 4677/* 4678 * The garbage collector calls this to mark the class objects for all 4679 * loaded classes. 4680 */ 4681void dvmGcScanRootClassLoader() 4682{ 4683 /* dvmClassStartup() may not have been called before the first GC. 4684 */ 4685 if (gDvm.loadedClasses != NULL) { 4686 dvmHashTableLock(gDvm.loadedClasses); 4687 dvmHashForeach(gDvm.loadedClasses, markClassObject, NULL); 4688 dvmHashTableUnlock(gDvm.loadedClasses); 4689 } 4690} 4691 4692 4693/* 4694 * =========================================================================== 4695 * Method Prototypes and Descriptors 4696 * =========================================================================== 4697 */ 4698 4699/* 4700 * Compare the two method names and prototypes, a la strcmp(). The 4701 * name is considered the "major" order and the prototype the "minor" 4702 * order. The prototypes are compared as if by dvmCompareMethodProtos(). 4703 */ 4704int dvmCompareMethodNamesAndProtos(const Method* method1, 4705 const Method* method2) 4706{ 4707 int result = strcmp(method1->name, method2->name); 4708 4709 if (result != 0) { 4710 return result; 4711 } 4712 4713 return dvmCompareMethodProtos(method1, method2); 4714} 4715 4716/* 4717 * Compare the two method names and prototypes, a la strcmp(), ignoring 4718 * the return value. The name is considered the "major" order and the 4719 * prototype the "minor" order. The prototypes are compared as if by 4720 * dvmCompareMethodArgProtos(). 4721 */ 4722int dvmCompareMethodNamesAndParameterProtos(const Method* method1, 4723 const Method* method2) 4724{ 4725 int result = strcmp(method1->name, method2->name); 4726 4727 if (result != 0) { 4728 return result; 4729 } 4730 4731 return dvmCompareMethodParameterProtos(method1, method2); 4732} 4733 4734/* 4735 * Compare a (name, prototype) pair with the (name, prototype) of 4736 * a method, a la strcmp(). The name is considered the "major" order and 4737 * the prototype the "minor" order. The descriptor and prototype are 4738 * compared as if by dvmCompareDescriptorAndMethodProto(). 4739 */ 4740int dvmCompareNameProtoAndMethod(const char* name, 4741 const DexProto* proto, const Method* method) 4742{ 4743 int result = strcmp(name, method->name); 4744 4745 if (result != 0) { 4746 return result; 4747 } 4748 4749 return dexProtoCompare(proto, &method->prototype); 4750} 4751 4752/* 4753 * Compare a (name, method descriptor) pair with the (name, prototype) of 4754 * a method, a la strcmp(). The name is considered the "major" order and 4755 * the prototype the "minor" order. The descriptor and prototype are 4756 * compared as if by dvmCompareDescriptorAndMethodProto(). 4757 */ 4758int dvmCompareNameDescriptorAndMethod(const char* name, 4759 const char* descriptor, const Method* method) 4760{ 4761 int result = strcmp(name, method->name); 4762 4763 if (result != 0) { 4764 return result; 4765 } 4766 4767 return dvmCompareDescriptorAndMethodProto(descriptor, method); 4768} 4769