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