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