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