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