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