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