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