blob: db0ce7bc396670b9ecf0e2ca34b9640b2b419510 [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);
804 urlObj = dvmCreateStringFromCstr(urlBuf, ALLOC_DEFAULT);
805
806bail:
807 return urlObj;
808}
809
810
811/*
812 * ===========================================================================
813 * Class list management
814 * ===========================================================================
815 */
816
817/* search for these criteria in the Class hash table */
818typedef struct ClassMatchCriteria {
819 const char* descriptor;
820 Object* loader;
821} ClassMatchCriteria;
822
823#define kInitLoaderInc 4 /* must be power of 2 */
824
Barry 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;
1132 } while (!ATOMIC_CMP_SWAP(&gDvm.classSerialNumber, oldValue, newValue));
1133
1134 clazz->serialNumber = (u4) oldValue;
1135}
1136
1137
1138/*
1139 * Find the named class (by descriptor), using the specified
1140 * initiating ClassLoader.
1141 *
1142 * The class will be loaded and initialized if it has not already been.
1143 * If necessary, the superclass will be loaded.
1144 *
1145 * If the class can't be found, returns NULL with an appropriate exception
1146 * raised.
1147 */
1148ClassObject* dvmFindClass(const char* descriptor, Object* loader)
1149{
1150 ClassObject* clazz;
1151
1152 clazz = dvmFindClassNoInit(descriptor, loader);
1153 if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1154 /* initialize class */
1155 if (!dvmInitClass(clazz)) {
1156 /* init failed; leave it in the list, marked as bad */
1157 assert(dvmCheckException(dvmThreadSelf()));
1158 assert(clazz->status == CLASS_ERROR);
1159 return NULL;
1160 }
1161 }
1162
1163 return clazz;
1164}
1165
1166/*
1167 * Find the named class (by descriptor), using the specified
1168 * initiating ClassLoader.
1169 *
1170 * The class will be loaded if it has not already been, as will its
1171 * superclass. It will not be initialized.
1172 *
1173 * If the class can't be found, returns NULL with an appropriate exception
1174 * raised.
1175 */
1176ClassObject* dvmFindClassNoInit(const char* descriptor,
1177 Object* loader)
1178{
1179 assert(descriptor != NULL);
1180 //assert(loader != NULL);
1181
1182 LOGVV("FindClassNoInit '%s' %p\n", descriptor, loader);
1183
1184 if (*descriptor == '[') {
1185 /*
1186 * Array class. Find in table, generate if not found.
1187 */
1188 return dvmFindArrayClass(descriptor, loader);
1189 } else {
1190 /*
1191 * Regular class. Find in table, load if not found.
1192 */
1193 if (loader != NULL) {
1194 return findClassFromLoaderNoInit(descriptor, loader);
1195 } else {
1196 return dvmFindSystemClassNoInit(descriptor);
1197 }
1198 }
1199}
1200
1201/*
1202 * Load the named class (by descriptor) from the specified class
1203 * loader. This calls out to let the ClassLoader object do its thing.
1204 *
1205 * Returns with NULL and an exception raised on error.
1206 */
1207static ClassObject* findClassFromLoaderNoInit(const char* descriptor,
1208 Object* loader)
1209{
1210 //LOGI("##### findClassFromLoaderNoInit (%s,%p)\n",
1211 // descriptor, loader);
1212
1213 Thread* self = dvmThreadSelf();
1214 ClassObject* clazz;
1215
1216 assert(loader != NULL);
1217
1218 /*
1219 * Do we already have it?
1220 *
1221 * The class loader code does the "is it already loaded" check as
1222 * well. However, this call is much faster than calling through
1223 * interpreted code. Doing this does mean that in the common case
1224 * (365 out of 420 calls booting the sim) we're doing the
1225 * lookup-by-descriptor twice. It appears this is still a win, so
1226 * I'm keeping it in.
1227 */
1228 clazz = dvmLookupClass(descriptor, loader, false);
1229 if (clazz != NULL) {
1230 LOGVV("Already loaded: %s %p\n", descriptor, loader);
1231 return clazz;
1232 } else {
1233 LOGVV("Not already loaded: %s %p\n", descriptor, loader);
1234 }
1235
1236 char* dotName = NULL;
1237 StringObject* nameObj = NULL;
1238 Object* excep;
1239 Method* loadClass;
1240
1241 /* convert "Landroid/debug/Stuff;" to "android.debug.Stuff" */
1242 dotName = dvmDescriptorToDot(descriptor);
1243 if (dotName == NULL) {
1244 dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL);
1245 goto bail;
1246 }
1247 nameObj = dvmCreateStringFromCstr(dotName, ALLOC_DEFAULT);
1248 if (nameObj == NULL) {
1249 assert(dvmCheckException(self));
1250 goto bail;
1251 }
1252
1253 // TODO: cache the vtable offset
1254 loadClass = dvmFindVirtualMethodHierByDescriptor(loader->clazz, "loadClass",
1255 "(Ljava/lang/String;)Ljava/lang/Class;");
1256 if (loadClass == NULL) {
1257 LOGW("Couldn't find loadClass in ClassLoader\n");
1258 goto bail;
1259 }
1260
1261#ifdef WITH_PROFILER
1262 dvmMethodTraceClassPrepBegin();
1263#endif
1264
1265 /*
1266 * Invoke loadClass(). This will probably result in a couple of
1267 * exceptions being thrown, because the ClassLoader.loadClass()
1268 * implementation eventually calls VMClassLoader.loadClass to see if
1269 * the bootstrap class loader can find it before doing its own load.
1270 */
1271 LOGVV("--- Invoking loadClass(%s, %p)\n", dotName, loader);
1272 JValue result;
1273 dvmCallMethod(self, loadClass, loader, &result, nameObj);
1274 clazz = (ClassObject*) result.l;
1275
1276#ifdef WITH_PROFILER
1277 dvmMethodTraceClassPrepEnd();
1278#endif
1279
1280 excep = dvmGetException(self);
1281 if (excep != NULL) {
1282#if DVM_SHOW_EXCEPTION >= 2
1283 LOGD("NOTE: loadClass '%s' %p threw exception %s\n",
1284 dotName, loader, excep->clazz->descriptor);
1285#endif
1286 dvmAddTrackedAlloc(excep, self);
1287 dvmClearException(self);
1288 dvmThrowChainedExceptionWithClassMessage(
1289 "Ljava/lang/NoClassDefFoundError;", descriptor, excep);
1290 dvmReleaseTrackedAlloc(excep, self);
1291 clazz = NULL;
1292 goto bail;
1293 } else {
1294 assert(clazz != NULL);
1295 }
1296
1297 dvmAddInitiatingLoader(clazz, loader);
1298
1299 LOGVV("--- Successfully loaded %s %p (thisldr=%p clazz=%p)\n",
1300 descriptor, clazz->classLoader, loader, clazz);
1301
1302bail:
1303 dvmReleaseTrackedAlloc((Object*)nameObj, NULL);
1304 free(dotName);
1305 return clazz;
1306}
1307
1308/*
1309 * Load the named class (by descriptor) from the specified DEX file.
1310 * Used by class loaders to instantiate a class object from a
1311 * VM-managed DEX.
1312 */
1313ClassObject* dvmDefineClass(DvmDex* pDvmDex, const char* descriptor,
1314 Object* classLoader)
1315{
1316 assert(pDvmDex != NULL);
1317
1318 return findClassNoInit(descriptor, classLoader, pDvmDex);
1319}
1320
1321
1322/*
1323 * Find the named class (by descriptor), scanning through the
1324 * bootclasspath if it hasn't already been loaded.
1325 *
1326 * "descriptor" looks like "Landroid/debug/Stuff;".
1327 *
1328 * Uses NULL as the defining class loader.
1329 */
1330ClassObject* dvmFindSystemClass(const char* descriptor)
1331{
1332 ClassObject* clazz;
1333
1334 clazz = dvmFindSystemClassNoInit(descriptor);
1335 if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1336 /* initialize class */
1337 if (!dvmInitClass(clazz)) {
1338 /* init failed; leave it in the list, marked as bad */
1339 assert(dvmCheckException(dvmThreadSelf()));
1340 assert(clazz->status == CLASS_ERROR);
1341 return NULL;
1342 }
1343 }
1344
1345 return clazz;
1346}
1347
1348/*
1349 * Find the named class (by descriptor), searching for it in the
1350 * bootclasspath.
1351 *
1352 * On failure, this returns NULL with an exception raised.
1353 */
1354ClassObject* dvmFindSystemClassNoInit(const char* descriptor)
1355{
1356 return findClassNoInit(descriptor, NULL, NULL);
1357}
1358
1359/*
1360 * Find the named class (by descriptor). If it's not already loaded,
1361 * we load it and link it, but don't execute <clinit>. (The VM has
1362 * specific limitations on which events can cause initialization.)
1363 *
1364 * If "pDexFile" is NULL, we will search the bootclasspath for an entry.
1365 *
1366 * On failure, this returns NULL with an exception raised.
1367 *
1368 * TODO: we need to return an indication of whether we loaded the class or
1369 * used an existing definition. If somebody deliberately tries to load a
1370 * class twice in the same class loader, they should get a LinkageError,
1371 * but inadvertent simultaneous class references should "just work".
1372 */
1373static ClassObject* findClassNoInit(const char* descriptor, Object* loader,
1374 DvmDex* pDvmDex)
1375{
1376 Thread* self = dvmThreadSelf();
1377 ClassObject* clazz;
1378#ifdef WITH_PROFILER
1379 bool profilerNotified = false;
1380#endif
1381
1382 if (loader != NULL) {
1383 LOGVV("#### findClassNoInit(%s,%p,%p)\n", descriptor, loader,
1384 pDvmDex->pDexFile);
1385 }
1386
1387 /*
1388 * We don't expect an exception to be raised at this point. The
1389 * exception handling code is good about managing this. This *can*
1390 * happen if a JNI lookup fails and the JNI code doesn't do any
1391 * error checking before doing another class lookup, so we may just
1392 * want to clear this and restore it on exit. If we don't, some kinds
1393 * of failures can't be detected without rearranging other stuff.
1394 *
1395 * Most often when we hit this situation it means that something is
1396 * broken in the VM or in JNI code, so I'm keeping it in place (and
1397 * making it an informative abort rather than an assert).
1398 */
1399 if (dvmCheckException(self)) {
Andy McFadden504e9f42009-09-15 20:01:40 -07001400 LOGE("Class lookup %s attempted while exception %s pending\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001401 descriptor, dvmGetException(self)->clazz->descriptor);
1402 dvmDumpAllThreads(false);
1403 dvmAbort();
1404 }
1405
1406 clazz = dvmLookupClass(descriptor, loader, true);
1407 if (clazz == NULL) {
1408 const DexClassDef* pClassDef;
1409
1410#ifdef WITH_PROFILER
1411 dvmMethodTraceClassPrepBegin();
1412 profilerNotified = true;
1413#endif
1414
1415#if LOG_CLASS_LOADING
1416 u8 startTime = dvmGetThreadCpuTimeNsec();
1417#endif
1418
1419 if (pDvmDex == NULL) {
1420 assert(loader == NULL); /* shouldn't be here otherwise */
1421 pDvmDex = searchBootPathForClass(descriptor, &pClassDef);
1422 } else {
1423 pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
1424 }
1425
1426 if (pDvmDex == NULL || pClassDef == NULL) {
Andy McFadden7fc3ce82009-07-14 15:57:23 -07001427 if (gDvm.noClassDefFoundErrorObj != NULL) {
1428 /* usual case -- use prefabricated object */
1429 dvmSetException(self, gDvm.noClassDefFoundErrorObj);
1430 } else {
1431 /* dexopt case -- can't guarantee prefab (core.jar) */
1432 dvmThrowExceptionWithClassMessage(
1433 "Ljava/lang/NoClassDefFoundError;", descriptor);
1434 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001435 goto bail;
1436 }
1437
1438 /* found a match, try to load it */
1439 clazz = loadClassFromDex(pDvmDex, pClassDef, loader);
1440 if (dvmCheckException(self)) {
1441 /* class was found but had issues */
1442 dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1443 goto bail;
1444 }
1445
1446 /*
1447 * Lock the class while we link it so other threads must wait for us
1448 * to finish. Set the "initThreadId" so we can identify recursive
1449 * invocation.
1450 */
1451 dvmLockObject(self, (Object*) clazz);
1452 clazz->initThreadId = self->threadId;
1453
1454 /*
1455 * Add to hash table so lookups succeed.
1456 *
1457 * [Are circular references possible when linking a class?]
1458 */
1459 assert(clazz->classLoader == loader);
1460 if (!dvmAddClassToHash(clazz)) {
1461 /*
1462 * Another thread must have loaded the class after we
1463 * started but before we finished. Discard what we've
1464 * done and leave some hints for the GC.
1465 *
1466 * (Yes, this happens.)
1467 */
1468 //LOGW("WOW: somebody loaded %s simultaneously\n", descriptor);
1469 clazz->initThreadId = 0;
1470 dvmUnlockObject(self, (Object*) clazz);
1471
1472 /* Let the GC free the class.
1473 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001474 dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1475
1476 /* Grab the winning class.
1477 */
1478 clazz = dvmLookupClass(descriptor, loader, true);
1479 assert(clazz != NULL);
1480 goto got_class;
1481 }
1482 dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1483
1484#if LOG_CLASS_LOADING
1485 logClassLoadWithTime('>', clazz, startTime);
1486#endif
1487 /*
1488 * Prepare and resolve.
1489 */
Barry Hayesc49db852010-05-14 13:43:34 -07001490 if (!dvmLinkClass(clazz)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001491 assert(dvmCheckException(self));
1492
1493 /* Make note of the error and clean up the class.
1494 */
1495 removeClassFromHash(clazz);
1496 clazz->status = CLASS_ERROR;
1497 dvmFreeClassInnards(clazz);
1498
1499 /* Let any waiters know.
1500 */
1501 clazz->initThreadId = 0;
1502 dvmObjectNotifyAll(self, (Object*) clazz);
1503 dvmUnlockObject(self, (Object*) clazz);
1504
1505#if LOG_CLASS_LOADING
1506 LOG(LOG_INFO, "DVMLINK FAILED FOR CLASS ", "%s in %s\n",
1507 clazz->descriptor, get_process_name());
1508
1509 /*
1510 * TODO: It would probably be better to use a new type code here (instead of '<') to
1511 * indicate the failure. This change would require a matching change in the parser
1512 * and analysis code in frameworks/base/tools/preload.
1513 */
1514 logClassLoad('<', clazz);
1515#endif
1516 clazz = NULL;
1517 if (gDvm.optimizing) {
1518 /* happens with "external" libs */
1519 LOGV("Link of class '%s' failed\n", descriptor);
1520 } else {
1521 LOGW("Link of class '%s' failed\n", descriptor);
1522 }
1523 goto bail;
1524 }
1525 dvmObjectNotifyAll(self, (Object*) clazz);
1526 dvmUnlockObject(self, (Object*) clazz);
1527
1528 /*
1529 * Add class stats to global counters.
1530 *
1531 * TODO: these should probably be atomic ops.
1532 */
1533 gDvm.numLoadedClasses++;
1534 gDvm.numDeclaredMethods +=
1535 clazz->virtualMethodCount + clazz->directMethodCount;
1536 gDvm.numDeclaredInstFields += clazz->ifieldCount;
1537 gDvm.numDeclaredStaticFields += clazz->sfieldCount;
1538
1539 /*
1540 * Cache pointers to basic classes. We want to use these in
1541 * various places, and it's easiest to initialize them on first
1542 * use rather than trying to force them to initialize (startup
1543 * ordering makes it weird).
1544 */
1545 if (gDvm.classJavaLangObject == NULL &&
1546 strcmp(descriptor, "Ljava/lang/Object;") == 0)
1547 {
1548 /* It should be impossible to get here with anything
1549 * but the bootclasspath loader.
1550 */
1551 assert(loader == NULL);
1552 gDvm.classJavaLangObject = clazz;
1553 }
1554
1555#if LOG_CLASS_LOADING
1556 logClassLoad('<', clazz);
1557#endif
1558
1559 } else {
1560got_class:
1561 if (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1562 /*
1563 * We can race with other threads for class linking. We should
1564 * never get here recursively; doing so indicates that two
1565 * classes have circular dependencies.
1566 *
1567 * One exception: we force discovery of java.lang.Class in
1568 * dvmLinkClass(), and Class has Object as its superclass. So
1569 * if the first thing we ever load is Object, we will init
1570 * Object->Class->Object. The easiest way to avoid this is to
1571 * ensure that Object is never the first thing we look up, so
1572 * we get Foo->Class->Object instead.
1573 */
1574 dvmLockObject(self, (Object*) clazz);
1575 if (!dvmIsClassLinked(clazz) &&
1576 clazz->initThreadId == self->threadId)
1577 {
1578 LOGW("Recursive link on class %s\n", clazz->descriptor);
1579 dvmUnlockObject(self, (Object*) clazz);
1580 dvmThrowExceptionWithClassMessage(
1581 "Ljava/lang/ClassCircularityError;", clazz->descriptor);
1582 clazz = NULL;
1583 goto bail;
1584 }
1585 //LOGI("WAITING for '%s' (owner=%d)\n",
1586 // clazz->descriptor, clazz->initThreadId);
1587 while (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1588 dvmObjectWait(self, (Object*) clazz, 0, 0, false);
1589 }
1590 dvmUnlockObject(self, (Object*) clazz);
1591 }
1592 if (clazz->status == CLASS_ERROR) {
1593 /*
1594 * Somebody else tried to load this and failed. We need to raise
1595 * an exception and report failure.
1596 */
1597 throwEarlierClassFailure(clazz);
1598 clazz = NULL;
1599 goto bail;
1600 }
1601 }
1602
1603 /* check some invariants */
1604 assert(dvmIsClassLinked(clazz));
1605 assert(gDvm.classJavaLangClass != NULL);
1606 assert(clazz->obj.clazz == gDvm.classJavaLangClass);
1607 if (clazz != gDvm.classJavaLangObject) {
1608 if (clazz->super == NULL) {
1609 LOGE("Non-Object has no superclass (gDvm.classJavaLangObject=%p)\n",
1610 gDvm.classJavaLangObject);
1611 dvmAbort();
1612 }
1613 }
1614 if (!dvmIsInterfaceClass(clazz)) {
1615 //LOGI("class=%s vtableCount=%d, virtualMeth=%d\n",
1616 // clazz->descriptor, clazz->vtableCount,
1617 // clazz->virtualMethodCount);
1618 assert(clazz->vtableCount >= clazz->virtualMethodCount);
1619 }
1620
1621 /*
1622 * Normally class objects are initialized before we instantiate them,
1623 * but we can't do that with java.lang.Class (chicken, meet egg). We
1624 * do it explicitly here.
1625 *
1626 * The verifier could call here to find Class while verifying Class,
1627 * so we need to check for CLASS_VERIFYING as well as !initialized.
1628 */
1629 if (clazz == gDvm.classJavaLangClass && !dvmIsClassInitialized(clazz) &&
1630 !(clazz->status == CLASS_VERIFYING))
1631 {
1632 LOGV("+++ explicitly initializing %s\n", clazz->descriptor);
1633 dvmInitClass(clazz);
1634 }
1635
1636bail:
1637#ifdef WITH_PROFILER
1638 if (profilerNotified)
1639 dvmMethodTraceClassPrepEnd();
1640#endif
1641 assert(clazz != NULL || dvmCheckException(self));
1642 return clazz;
1643}
1644
1645/*
1646 * Helper for loadClassFromDex, which takes a DexClassDataHeader and
1647 * encoded data pointer in addition to the other arguments.
1648 */
1649static ClassObject* loadClassFromDex0(DvmDex* pDvmDex,
1650 const DexClassDef* pClassDef, const DexClassDataHeader* pHeader,
1651 const u1* pEncodedData, Object* classLoader)
1652{
1653 ClassObject* newClass = NULL;
1654 const DexFile* pDexFile;
1655 const char* descriptor;
1656 int i;
1657
1658 pDexFile = pDvmDex->pDexFile;
1659 descriptor = dexGetClassDescriptor(pDexFile, pClassDef);
1660
1661 /*
1662 * Make sure the aren't any "bonus" flags set, since we use them for
1663 * runtime state.
1664 */
1665 if ((pClassDef->accessFlags & ~EXPECTED_FILE_FLAGS) != 0) {
1666 LOGW("Invalid file flags in class %s: %04x\n",
1667 descriptor, pClassDef->accessFlags);
1668 return NULL;
1669 }
1670
1671 /*
1672 * Allocate storage for the class object on the GC heap, so that other
1673 * objects can have references to it. We bypass the usual mechanism
1674 * (allocObject), because we don't have all the bits and pieces yet.
1675 *
1676 * Note that we assume that java.lang.Class does not override
1677 * finalize().
1678 */
Barry Hayesc49db852010-05-14 13:43:34 -07001679 /* TODO: Can there be fewer special checks in the usual path? */
1680 assert(descriptor != NULL);
1681 if (classLoader == NULL &&
1682 strcmp(descriptor, "Ljava/lang/Class;") == 0) {
1683 assert(gDvm.classJavaLangClass != NULL);
1684 newClass = gDvm.classJavaLangClass;
1685 } else {
1686 size_t size = classObjectSize(pHeader->staticFieldsSize);
1687 newClass = (ClassObject*) dvmMalloc(size, ALLOC_DEFAULT);
1688 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001689 if (newClass == NULL)
1690 return NULL;
1691
Barry Hayesc49db852010-05-14 13:43:34 -07001692 DVM_OBJECT_INIT(&newClass->obj, gDvm.classJavaLangClass);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001693 dvmSetClassSerialNumber(newClass);
1694 newClass->descriptor = descriptor;
1695 assert(newClass->descriptorAlloc == NULL);
1696 newClass->accessFlags = pClassDef->accessFlags;
1697 newClass->classLoader = classLoader;
1698 newClass->pDvmDex = pDvmDex;
1699 newClass->primitiveType = PRIM_NOT;
Barry Hayesc49db852010-05-14 13:43:34 -07001700 newClass->status = CLASS_IDX;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001701
1702 /*
1703 * Stuff the superclass index into the object pointer field. The linker
1704 * pulls it out and replaces it with a resolved ClassObject pointer.
1705 * I'm doing it this way (rather than having a dedicated superclassIdx
1706 * field) to save a few bytes of overhead per class.
1707 *
1708 * newClass->super is not traversed or freed by dvmFreeClassInnards, so
1709 * this is safe.
1710 */
Barry Hayesc49db852010-05-14 13:43:34 -07001711 assert(sizeof(u4) == sizeof(ClassObject*)); /* 32-bit check */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001712 newClass->super = (ClassObject*) pClassDef->superclassIdx;
1713
1714 /*
1715 * Stuff class reference indices into the pointer fields.
1716 *
1717 * The elements of newClass->interfaces are not traversed or freed by
1718 * dvmFreeClassInnards, so this is GC-safe.
1719 */
1720 const DexTypeList* pInterfacesList;
1721 pInterfacesList = dexGetInterfacesList(pDexFile, pClassDef);
1722 if (pInterfacesList != NULL) {
1723 newClass->interfaceCount = pInterfacesList->size;
1724 newClass->interfaces = (ClassObject**) dvmLinearAlloc(classLoader,
1725 newClass->interfaceCount * sizeof(ClassObject*));
1726
1727 for (i = 0; i < newClass->interfaceCount; i++) {
1728 const DexTypeItem* pType = dexGetTypeItem(pInterfacesList, i);
1729 newClass->interfaces[i] = (ClassObject*)(u4) pType->typeIdx;
1730 }
1731 dvmLinearReadOnly(classLoader, newClass->interfaces);
1732 }
1733
1734 /* load field definitions */
1735
1736 /*
Barry Hayes03aa70a2010-03-01 15:49:41 -08001737 * Over-allocate the class object and append static field info
1738 * onto the end. It's fixed-size and known at alloc time. This
1739 * seems to increase zygote sharing. Heap compaction will have to
1740 * be careful if it ever tries to move ClassObject instances,
1741 * because we pass Field pointers around internally. But at least
1742 * now these Field pointers are in the object heap.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001743 */
1744
1745 if (pHeader->staticFieldsSize != 0) {
1746 /* static fields stay on system heap; field data isn't "write once" */
1747 int count = (int) pHeader->staticFieldsSize;
1748 u4 lastIndex = 0;
1749 DexField field;
1750
1751 newClass->sfieldCount = count;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001752 for (i = 0; i < count; i++) {
1753 dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1754 loadSFieldFromDex(newClass, &field, &newClass->sfields[i]);
1755 }
1756 }
1757
1758 if (pHeader->instanceFieldsSize != 0) {
1759 int count = (int) pHeader->instanceFieldsSize;
1760 u4 lastIndex = 0;
1761 DexField field;
1762
1763 newClass->ifieldCount = count;
1764 newClass->ifields = (InstField*) dvmLinearAlloc(classLoader,
1765 count * sizeof(InstField));
1766 for (i = 0; i < count; i++) {
1767 dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1768 loadIFieldFromDex(newClass, &field, &newClass->ifields[i]);
1769 }
1770 dvmLinearReadOnly(classLoader, newClass->ifields);
1771 }
1772
The Android Open Source Project99409882009-03-18 22:20:24 -07001773 /*
1774 * Load method definitions. We do this in two batches, direct then
1775 * virtual.
1776 *
1777 * If register maps have already been generated for this class, and
1778 * precise GC is enabled, we pull out pointers to them. We know that
1779 * they were streamed to the DEX file in the same order in which the
1780 * methods appear.
1781 *
1782 * If the class wasn't pre-verified, the maps will be generated when
1783 * the class is verified during class initialization.
1784 */
1785 u4 classDefIdx = dexGetIndexForClassDef(pDexFile, pClassDef);
1786 const void* classMapData;
1787 u4 numMethods;
1788
1789 if (gDvm.preciseGc) {
1790 classMapData =
Andy McFaddend45a8872009-03-24 20:41:52 -07001791 dvmRegisterMapGetClassData(pDexFile, classDefIdx, &numMethods);
The Android Open Source Project99409882009-03-18 22:20:24 -07001792
1793 /* sanity check */
1794 if (classMapData != NULL &&
1795 pHeader->directMethodsSize + pHeader->virtualMethodsSize != numMethods)
1796 {
1797 LOGE("ERROR: in %s, direct=%d virtual=%d, maps have %d\n",
1798 newClass->descriptor, pHeader->directMethodsSize,
1799 pHeader->virtualMethodsSize, numMethods);
1800 assert(false);
1801 classMapData = NULL; /* abandon */
1802 }
1803 } else {
1804 classMapData = NULL;
1805 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001806
1807 if (pHeader->directMethodsSize != 0) {
1808 int count = (int) pHeader->directMethodsSize;
1809 u4 lastIndex = 0;
1810 DexMethod method;
1811
1812 newClass->directMethodCount = count;
1813 newClass->directMethods = (Method*) dvmLinearAlloc(classLoader,
1814 count * sizeof(Method));
1815 for (i = 0; i < count; i++) {
1816 dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1817 loadMethodFromDex(newClass, &method, &newClass->directMethods[i]);
The Android Open Source Project99409882009-03-18 22:20:24 -07001818 if (classMapData != NULL) {
Andy McFaddend45a8872009-03-24 20:41:52 -07001819 const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
1820 if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
The Android Open Source Project99409882009-03-18 22:20:24 -07001821 newClass->directMethods[i].registerMap = pMap;
1822 /* TODO: add rigorous checks */
1823 assert((newClass->directMethods[i].registersSize+7) / 8 ==
1824 newClass->directMethods[i].registerMap->regWidth);
1825 }
1826 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001827 }
1828 dvmLinearReadOnly(classLoader, newClass->directMethods);
1829 }
1830
1831 if (pHeader->virtualMethodsSize != 0) {
1832 int count = (int) pHeader->virtualMethodsSize;
1833 u4 lastIndex = 0;
1834 DexMethod method;
1835
1836 newClass->virtualMethodCount = count;
1837 newClass->virtualMethods = (Method*) dvmLinearAlloc(classLoader,
1838 count * sizeof(Method));
1839 for (i = 0; i < count; i++) {
1840 dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1841 loadMethodFromDex(newClass, &method, &newClass->virtualMethods[i]);
The Android Open Source Project99409882009-03-18 22:20:24 -07001842 if (classMapData != NULL) {
Andy McFaddend45a8872009-03-24 20:41:52 -07001843 const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
1844 if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
The Android Open Source Project99409882009-03-18 22:20:24 -07001845 newClass->virtualMethods[i].registerMap = pMap;
1846 /* TODO: add rigorous checks */
1847 assert((newClass->virtualMethods[i].registersSize+7) / 8 ==
1848 newClass->virtualMethods[i].registerMap->regWidth);
1849 }
1850 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001851 }
1852 dvmLinearReadOnly(classLoader, newClass->virtualMethods);
1853 }
1854
1855 newClass->sourceFile = dexGetSourceFile(pDexFile, pClassDef);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001856
1857 /* caller must call dvmReleaseTrackedAlloc */
1858 return newClass;
1859}
1860
1861/*
1862 * Try to load the indicated class from the specified DEX file.
1863 *
1864 * This is effectively loadClass()+defineClass() for a DexClassDef. The
1865 * loading was largely done when we crunched through the DEX.
1866 *
1867 * Returns NULL on failure. If we locate the class but encounter an error
1868 * while processing it, an appropriate exception is thrown.
1869 */
1870static ClassObject* loadClassFromDex(DvmDex* pDvmDex,
1871 const DexClassDef* pClassDef, Object* classLoader)
1872{
1873 ClassObject* result;
1874 DexClassDataHeader header;
1875 const u1* pEncodedData;
1876 const DexFile* pDexFile;
1877
1878 assert((pDvmDex != NULL) && (pClassDef != NULL));
1879 pDexFile = pDvmDex->pDexFile;
1880
1881 if (gDvm.verboseClass) {
1882 LOGV("CLASS: loading '%s'...\n",
1883 dexGetClassDescriptor(pDexFile, pClassDef));
1884 }
1885
1886 pEncodedData = dexGetClassData(pDexFile, pClassDef);
1887
1888 if (pEncodedData != NULL) {
1889 dexReadClassDataHeader(&pEncodedData, &header);
1890 } else {
1891 // Provide an all-zeroes header for the rest of the loading.
1892 memset(&header, 0, sizeof(header));
1893 }
1894
1895 result = loadClassFromDex0(pDvmDex, pClassDef, &header, pEncodedData,
1896 classLoader);
1897
1898 if (gDvm.verboseClass && (result != NULL)) {
1899 LOGI("[Loaded %s from DEX %p (cl=%p)]\n",
1900 result->descriptor, pDvmDex, classLoader);
1901 }
1902
1903 return result;
1904}
1905
1906/*
1907 * Free anything in a ClassObject that was allocated on the system heap.
1908 *
1909 * The ClassObject itself is allocated on the GC heap, so we leave it for
1910 * the garbage collector.
1911 *
1912 * NOTE: this may be called with a partially-constructed object.
1913 * NOTE: there is no particular ordering imposed, so don't go poking at
1914 * superclasses.
1915 */
1916void dvmFreeClassInnards(ClassObject* clazz)
1917{
1918 void *tp;
1919 int i;
1920
1921 if (clazz == NULL)
1922 return;
1923
Barry Hayesc49db852010-05-14 13:43:34 -07001924 assert(clazz->obj.clazz == gDvm.classJavaLangClass);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001925
1926 /* Guarantee that dvmFreeClassInnards can be called on a given
1927 * class multiple times by clearing things out as we free them.
1928 * We don't make any attempt at real atomicity here; higher
1929 * levels need to make sure that no two threads can free the
1930 * same ClassObject at the same time.
1931 *
1932 * TODO: maybe just make it so the GC will never free the
1933 * innards of an already-freed class.
1934 *
1935 * TODO: this #define isn't MT-safe -- the compiler could rearrange it.
1936 */
1937#define NULL_AND_FREE(p) \
1938 do { \
1939 if ((p) != NULL) { \
1940 tp = (p); \
1941 (p) = NULL; \
1942 free(tp); \
1943 } \
1944 } while (0)
1945#define NULL_AND_LINEAR_FREE(p) \
1946 do { \
1947 if ((p) != NULL) { \
1948 tp = (p); \
1949 (p) = NULL; \
1950 dvmLinearFree(clazz->classLoader, tp); \
1951 } \
1952 } while (0)
1953
1954 /* arrays just point at Object's vtable; don't free vtable in this case.
1955 * dvmIsArrayClass() checks clazz->descriptor, so we have to do this check
1956 * before freeing the name.
1957 */
1958 clazz->vtableCount = -1;
1959 if (dvmIsArrayClass(clazz)) {
1960 clazz->vtable = NULL;
1961 } else {
1962 NULL_AND_LINEAR_FREE(clazz->vtable);
1963 }
1964
1965 clazz->descriptor = NULL;
1966 NULL_AND_FREE(clazz->descriptorAlloc);
1967
1968 if (clazz->directMethods != NULL) {
1969 Method *directMethods = clazz->directMethods;
1970 int directMethodCount = clazz->directMethodCount;
1971 clazz->directMethods = NULL;
1972 clazz->directMethodCount = -1;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001973 dvmLinearReadWrite(clazz->classLoader, directMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001974 for (i = 0; i < directMethodCount; i++) {
1975 freeMethodInnards(&directMethods[i]);
1976 }
Andy McFaddenb51ea112009-05-08 16:50:17 -07001977 dvmLinearReadOnly(clazz->classLoader, directMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001978 dvmLinearFree(clazz->classLoader, directMethods);
1979 }
1980 if (clazz->virtualMethods != NULL) {
1981 Method *virtualMethods = clazz->virtualMethods;
1982 int virtualMethodCount = clazz->virtualMethodCount;
1983 clazz->virtualMethodCount = -1;
1984 clazz->virtualMethods = NULL;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001985 dvmLinearReadWrite(clazz->classLoader, virtualMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001986 for (i = 0; i < virtualMethodCount; i++) {
1987 freeMethodInnards(&virtualMethods[i]);
1988 }
Andy McFaddenb51ea112009-05-08 16:50:17 -07001989 dvmLinearReadOnly(clazz->classLoader, virtualMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001990 dvmLinearFree(clazz->classLoader, virtualMethods);
1991 }
1992
Barry Hayes2c987472009-04-06 10:03:48 -07001993 InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz);
1994 loaderList->initiatingLoaderCount = -1;
1995 NULL_AND_FREE(loaderList->initiatingLoaders);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001996
1997 clazz->interfaceCount = -1;
1998 NULL_AND_LINEAR_FREE(clazz->interfaces);
1999
2000 clazz->iftableCount = -1;
2001 NULL_AND_LINEAR_FREE(clazz->iftable);
2002
2003 clazz->ifviPoolCount = -1;
2004 NULL_AND_LINEAR_FREE(clazz->ifviPool);
2005
2006 clazz->sfieldCount = -1;
Barry Hayes03aa70a2010-03-01 15:49:41 -08002007 /* The sfields are attached to the ClassObject, and will be freed
2008 * with it. */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002009
2010 clazz->ifieldCount = -1;
2011 NULL_AND_LINEAR_FREE(clazz->ifields);
2012
2013#undef NULL_AND_FREE
2014#undef NULL_AND_LINEAR_FREE
2015}
2016
2017/*
2018 * Free anything in a Method that was allocated on the system heap.
The Android Open Source Project99409882009-03-18 22:20:24 -07002019 *
2020 * The containing class is largely torn down by this point.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002021 */
2022static void freeMethodInnards(Method* meth)
2023{
2024#if 0
2025 free(meth->exceptions);
2026 free(meth->lines);
2027 free(meth->locals);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002028#endif
The Android Open Source Project99409882009-03-18 22:20:24 -07002029
2030 /*
2031 * Some register maps are allocated on the heap, either because of late
2032 * verification or because we're caching an uncompressed form.
2033 */
2034 const RegisterMap* pMap = meth->registerMap;
Andy McFaddend45a8872009-03-24 20:41:52 -07002035 if (pMap != NULL && dvmRegisterMapGetOnHeap(pMap)) {
The Android Open Source Project99409882009-03-18 22:20:24 -07002036 dvmFreeRegisterMap((RegisterMap*) pMap);
2037 meth->registerMap = NULL;
2038 }
Andy McFaddenb51ea112009-05-08 16:50:17 -07002039
2040 /*
2041 * We may have copied the instructions.
2042 */
2043 if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
2044 DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2045 dvmLinearFree(meth->clazz->classLoader, methodDexCode);
2046 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002047}
2048
2049/*
2050 * Clone a Method, making new copies of anything that will be freed up
The Android Open Source Project99409882009-03-18 22:20:24 -07002051 * by freeMethodInnards(). This is used for "miranda" methods.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002052 */
2053static void cloneMethod(Method* dst, const Method* src)
2054{
The Android Open Source Project99409882009-03-18 22:20:24 -07002055 if (src->registerMap != NULL) {
2056 LOGE("GLITCH: only expected abstract methods here\n");
2057 LOGE(" cloning %s.%s\n", src->clazz->descriptor, src->name);
2058 dvmAbort();
2059 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002060 memcpy(dst, src, sizeof(Method));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002061}
2062
2063/*
2064 * Pull the interesting pieces out of a DexMethod.
2065 *
2066 * The DEX file isn't going anywhere, so we don't need to make copies of
2067 * the code area.
2068 */
2069static void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,
2070 Method* meth)
2071{
2072 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2073 const DexMethodId* pMethodId;
2074 const DexCode* pDexCode;
2075
2076 pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
2077
2078 meth->name = dexStringById(pDexFile, pMethodId->nameIdx);
2079 dexProtoSetFromMethodId(&meth->prototype, pDexFile, pMethodId);
2080 meth->shorty = dexProtoGetShorty(&meth->prototype);
2081 meth->accessFlags = pDexMethod->accessFlags;
2082 meth->clazz = clazz;
2083 meth->jniArgInfo = 0;
2084
2085 if (dvmCompareNameDescriptorAndMethod("finalize", "()V", meth) == 0) {
2086 SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2087 }
2088
2089 pDexCode = dexGetCode(pDexFile, pDexMethod);
2090 if (pDexCode != NULL) {
2091 /* integer constants, copy over for faster access */
2092 meth->registersSize = pDexCode->registersSize;
2093 meth->insSize = pDexCode->insSize;
2094 meth->outsSize = pDexCode->outsSize;
2095
2096 /* pointer to code area */
2097 meth->insns = pDexCode->insns;
2098 } else {
2099 /*
2100 * We don't have a DexCode block, but we still want to know how
2101 * much space is needed for the arguments (so we don't have to
2102 * compute it later). We also take this opportunity to compute
2103 * JNI argument info.
2104 *
2105 * We do this for abstract methods as well, because we want to
2106 * be able to substitute our exception-throwing "stub" in.
2107 */
2108 int argsSize = dvmComputeMethodArgsSize(meth);
2109 if (!dvmIsStaticMethod(meth))
2110 argsSize++;
2111 meth->registersSize = meth->insSize = argsSize;
2112 assert(meth->outsSize == 0);
2113 assert(meth->insns == NULL);
2114
2115 if (dvmIsNativeMethod(meth)) {
2116 meth->nativeFunc = dvmResolveNativeMethod;
2117 meth->jniArgInfo = computeJniArgInfo(&meth->prototype);
2118 }
2119 }
2120}
2121
Andy McFadden96516932009-10-28 17:39:02 -07002122#if 0 /* replaced with private/read-write mapping */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002123/*
Andy McFaddenb51ea112009-05-08 16:50:17 -07002124 * We usually map bytecode directly out of the DEX file, which is mapped
2125 * shared read-only. If we want to be able to modify it, we have to make
2126 * a new copy.
2127 *
2128 * Once copied, the code will be in the LinearAlloc region, which may be
2129 * marked read-only.
2130 *
2131 * The bytecode instructions are embedded inside a DexCode structure, so we
2132 * need to copy all of that. (The dvmGetMethodCode function backs up the
2133 * instruction pointer to find the start of the DexCode.)
2134 */
2135void dvmMakeCodeReadWrite(Method* meth)
2136{
2137 DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2138
2139 if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
2140 dvmLinearReadWrite(meth->clazz->classLoader, methodDexCode);
2141 return;
2142 }
2143
2144 assert(!dvmIsNativeMethod(meth) && !dvmIsAbstractMethod(meth));
2145
2146 size_t dexCodeSize = dexGetDexCodeSize(methodDexCode);
2147 LOGD("Making a copy of %s.%s code (%d bytes)\n",
2148 meth->clazz->descriptor, meth->name, dexCodeSize);
2149
2150 DexCode* newCode =
2151 (DexCode*) dvmLinearAlloc(meth->clazz->classLoader, dexCodeSize);
2152 memcpy(newCode, methodDexCode, dexCodeSize);
2153
2154 meth->insns = newCode->insns;
2155 SET_METHOD_FLAG(meth, METHOD_ISWRITABLE);
2156}
2157
2158/*
2159 * Mark the bytecode read-only.
2160 *
2161 * If the contents of the DexCode haven't actually changed, we could revert
2162 * to the original shared page.
2163 */
2164void dvmMakeCodeReadOnly(Method* meth)
2165{
2166 DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2167 LOGV("+++ marking %p read-only\n", methodDexCode);
2168 dvmLinearReadOnly(meth->clazz->classLoader, methodDexCode);
2169}
Andy McFadden96516932009-10-28 17:39:02 -07002170#endif
Andy McFaddenb51ea112009-05-08 16:50:17 -07002171
2172
2173/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002174 * jniArgInfo (32-bit int) layout:
2175 * SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
2176 *
2177 * S - if set, do things the hard way (scan the signature)
2178 * R - return-type enumeration
2179 * H - target-specific hints
2180 *
2181 * This info is used at invocation time by dvmPlatformInvoke. In most
2182 * cases, the target-specific hints allow dvmPlatformInvoke to avoid
2183 * having to fully parse the signature.
2184 *
2185 * The return-type bits are always set, even if target-specific hint bits
2186 * are unavailable.
2187 */
2188static int computeJniArgInfo(const DexProto* proto)
2189{
2190 const char* sig = dexProtoGetShorty(proto);
Carl Shapiroe3c01da2010-05-20 22:54:18 -07002191 int returnType, jniArgInfo;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002192 u4 hints;
2193
2194 /* The first shorty character is the return type. */
2195 switch (*(sig++)) {
2196 case 'V':
2197 returnType = DALVIK_JNI_RETURN_VOID;
2198 break;
2199 case 'F':
2200 returnType = DALVIK_JNI_RETURN_FLOAT;
2201 break;
2202 case 'D':
2203 returnType = DALVIK_JNI_RETURN_DOUBLE;
2204 break;
2205 case 'J':
2206 returnType = DALVIK_JNI_RETURN_S8;
2207 break;
Bill Buzbeee2557512009-07-27 15:51:54 -07002208 case 'Z':
2209 case 'B':
2210 returnType = DALVIK_JNI_RETURN_S1;
2211 break;
2212 case 'C':
2213 returnType = DALVIK_JNI_RETURN_U2;
2214 break;
2215 case 'S':
2216 returnType = DALVIK_JNI_RETURN_S2;
2217 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002218 default:
2219 returnType = DALVIK_JNI_RETURN_S4;
2220 break;
2221 }
2222
2223 jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT;
2224
2225 hints = dvmPlatformInvokeHints(proto);
2226
2227 if (hints & DALVIK_JNI_NO_ARG_INFO) {
2228 jniArgInfo |= DALVIK_JNI_NO_ARG_INFO;
2229 } else {
2230 assert((hints & DALVIK_JNI_RETURN_MASK) == 0);
2231 jniArgInfo |= hints;
2232 }
2233
2234 return jniArgInfo;
2235}
2236
2237/*
2238 * Load information about a static field.
2239 *
2240 * This also "prepares" static fields by initializing them
2241 * to their "standard default values".
2242 */
2243static void loadSFieldFromDex(ClassObject* clazz,
2244 const DexField* pDexSField, StaticField* sfield)
2245{
2246 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2247 const DexFieldId* pFieldId;
2248
2249 pFieldId = dexGetFieldId(pDexFile, pDexSField->fieldIdx);
2250
2251 sfield->field.clazz = clazz;
2252 sfield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2253 sfield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2254 sfield->field.accessFlags = pDexSField->accessFlags;
2255
2256 /* Static object field values are set to "standard default values"
2257 * (null or 0) until the class is initialized. We delay loading
2258 * constant values from the class until that time.
2259 */
2260 //sfield->value.j = 0;
2261 assert(sfield->value.j == 0LL); // cleared earlier with calloc
2262
2263#ifdef PROFILE_FIELD_ACCESS
2264 sfield->field.gets = sfield->field.puts = 0;
2265#endif
2266}
2267
2268/*
2269 * Load information about an instance field.
2270 */
2271static void loadIFieldFromDex(ClassObject* clazz,
2272 const DexField* pDexIField, InstField* ifield)
2273{
2274 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2275 const DexFieldId* pFieldId;
2276
2277 pFieldId = dexGetFieldId(pDexFile, pDexIField->fieldIdx);
2278
2279 ifield->field.clazz = clazz;
2280 ifield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2281 ifield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2282 ifield->field.accessFlags = pDexIField->accessFlags;
2283#ifndef NDEBUG
2284 assert(ifield->byteOffset == 0); // cleared earlier with calloc
2285 ifield->byteOffset = -1; // make it obvious if we fail to set later
2286#endif
2287
2288#ifdef PROFILE_FIELD_ACCESS
2289 ifield->field.gets = ifield->field.puts = 0;
2290#endif
2291}
2292
2293/*
2294 * Cache java.lang.ref.Reference fields and methods.
2295 */
Barry Hayes6daaac12009-07-08 10:01:56 -07002296static bool precacheReferenceOffsets(ClassObject* clazz)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002297{
2298 Method *meth;
2299 int i;
2300
2301 /* We trick the GC object scanner by not counting
2302 * java.lang.ref.Reference.referent as an object
2303 * field. It will get explicitly scanned as part
2304 * of the reference-walking process.
2305 *
2306 * Find the object field named "referent" and put it
2307 * just after the list of object reference fields.
2308 */
2309 dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
2310 for (i = 0; i < clazz->ifieldRefCount; i++) {
2311 InstField *pField = &clazz->ifields[i];
2312 if (strcmp(pField->field.name, "referent") == 0) {
2313 int targetIndex;
2314
2315 /* Swap this field with the last object field.
2316 */
2317 targetIndex = clazz->ifieldRefCount - 1;
2318 if (i != targetIndex) {
2319 InstField *swapField = &clazz->ifields[targetIndex];
2320 InstField tmpField;
2321 int tmpByteOffset;
2322
2323 /* It's not currently strictly necessary
2324 * for the fields to be in byteOffset order,
2325 * but it's more predictable that way.
2326 */
2327 tmpByteOffset = swapField->byteOffset;
2328 swapField->byteOffset = pField->byteOffset;
2329 pField->byteOffset = tmpByteOffset;
2330
2331 tmpField = *swapField;
2332 *swapField = *pField;
2333 *pField = tmpField;
2334 }
2335
2336 /* One fewer object field (wink wink).
2337 */
2338 clazz->ifieldRefCount--;
2339 i--; /* don't trip "didn't find it" test if field was last */
2340 break;
2341 }
2342 }
2343 dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
2344 if (i == clazz->ifieldRefCount) {
2345 LOGE("Unable to reorder 'referent' in %s\n", clazz->descriptor);
2346 return false;
2347 }
2348
2349 /* Cache pretty much everything about Reference so that
2350 * we don't need to call interpreted code when clearing/enqueueing
2351 * references. This is fragile, so we'll be paranoid.
2352 */
2353 gDvm.classJavaLangRefReference = clazz;
2354
2355 gDvm.offJavaLangRefReference_referent =
2356 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2357 "referent", "Ljava/lang/Object;");
2358 assert(gDvm.offJavaLangRefReference_referent >= 0);
2359
2360 gDvm.offJavaLangRefReference_queue =
2361 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2362 "queue", "Ljava/lang/ref/ReferenceQueue;");
2363 assert(gDvm.offJavaLangRefReference_queue >= 0);
2364
2365 gDvm.offJavaLangRefReference_queueNext =
2366 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2367 "queueNext", "Ljava/lang/ref/Reference;");
2368 assert(gDvm.offJavaLangRefReference_queueNext >= 0);
2369
2370 gDvm.offJavaLangRefReference_vmData =
2371 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2372 "vmData", "I");
2373 assert(gDvm.offJavaLangRefReference_vmData >= 0);
2374
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002375 /* enqueueInternal() is private and thus a direct method. */
2376 meth = dvmFindDirectMethodByDescriptor(clazz, "enqueueInternal", "()Z");
2377 assert(meth != NULL);
2378 gDvm.methJavaLangRefReference_enqueueInternal = meth;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002379
2380 return true;
2381}
2382
2383
2384/*
Barry Hayes6daaac12009-07-08 10:01:56 -07002385 * Set the bitmap of reference offsets, refOffsets, from the ifields
2386 * list.
2387 */
2388static void computeRefOffsets(ClassObject* clazz)
2389{
2390 if (clazz->super != NULL) {
2391 clazz->refOffsets = clazz->super->refOffsets;
2392 } else {
2393 clazz->refOffsets = 0;
2394 }
2395 /*
2396 * If our superclass overflowed, we don't stand a chance.
2397 */
2398 if (clazz->refOffsets != CLASS_WALK_SUPER) {
2399 InstField *f;
2400 int i;
2401
2402 /* All of the fields that contain object references
2403 * are guaranteed to be at the beginning of the ifields list.
2404 */
2405 f = clazz->ifields;
2406 const int ifieldRefCount = clazz->ifieldRefCount;
2407 for (i = 0; i < ifieldRefCount; i++) {
2408 /*
2409 * Note that, per the comment on struct InstField,
2410 * f->byteOffset is the offset from the beginning of
2411 * obj, not the offset into obj->instanceData.
2412 */
Andy McFadden2fbe6d12009-09-04 15:38:13 -07002413 assert(f->byteOffset >= (int) CLASS_SMALLEST_OFFSET);
Barry Hayes6daaac12009-07-08 10:01:56 -07002414 assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
2415 if (CLASS_CAN_ENCODE_OFFSET(f->byteOffset)) {
2416 u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
2417 assert(newBit != 0);
2418 clazz->refOffsets |= newBit;
2419 } else {
2420 clazz->refOffsets = CLASS_WALK_SUPER;
2421 break;
2422 }
2423 f++;
2424 }
2425 }
2426}
2427
2428
2429/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002430 * Link (prepare and resolve). Verification is deferred until later.
2431 *
2432 * This converts symbolic references into pointers. It's independent of
2433 * the source file format.
2434 *
Barry Hayesc49db852010-05-14 13:43:34 -07002435 * If clazz->status is CLASS_IDX, then clazz->super and interfaces[] are
2436 * holding class reference indices rather than pointers. The class
2437 * references will be resolved during link. (This is done when
2438 * loading from DEX to avoid having to create additional storage to
2439 * pass the indices around.)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002440 *
2441 * Returns "false" with an exception pending on failure.
2442 */
Barry Hayesc49db852010-05-14 13:43:34 -07002443bool dvmLinkClass(ClassObject* clazz)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002444{
2445 u4 superclassIdx = 0;
Barry Hayesc49db852010-05-14 13:43:34 -07002446 u4 *interfaceIdxArray = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002447 bool okay = false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002448 int i;
2449
Barry Hayesc49db852010-05-14 13:43:34 -07002450 assert(clazz != NULL);
2451 assert(clazz->descriptor != NULL);
2452 assert(clazz->status == CLASS_IDX || clazz->status == CLASS_LOADED);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002453 if (gDvm.verboseClass)
2454 LOGV("CLASS: linking '%s'...\n", clazz->descriptor);
2455
Barry Hayesc49db852010-05-14 13:43:34 -07002456 assert(gDvm.classJavaLangClass != NULL);
2457 assert(clazz->obj.clazz == gDvm.classJavaLangClass);
2458 if (clazz->classLoader == NULL &&
2459 (strcmp(clazz->descriptor, "Ljava/lang/Class;") == 0))
2460 {
2461 if (gDvm.classJavaLangClass->ifieldCount > CLASS_FIELD_SLOTS) {
2462 LOGE("java.lang.Class has %d instance fields (expected at most %d)",
2463 gDvm.classJavaLangClass->ifieldCount, CLASS_FIELD_SLOTS);
2464 dvmAbort();
2465 }
2466 if (gDvm.classJavaLangClass->sfieldCount != CLASS_SFIELD_SLOTS) {
2467 LOGE("java.lang.Class has %d static fields (expected %d)",
2468 gDvm.classJavaLangClass->sfieldCount, CLASS_SFIELD_SLOTS);
2469 dvmAbort();
2470 }
2471 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002472 /* "Resolve" the class.
2473 *
Barry Hayesc49db852010-05-14 13:43:34 -07002474 * At this point, clazz's reference fields may contain Dex file
2475 * indices instead of direct object references. Proxy objects are
2476 * an exception, and may be the only exception. We need to
2477 * translate those indices into real references, and let the GC
2478 * look inside this ClassObject.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002479 */
Barry Hayesc49db852010-05-14 13:43:34 -07002480 if (clazz->status == CLASS_IDX) {
2481 if (clazz->interfaceCount > 0) {
2482 /* Copy u4 DEX idx values out of the ClassObject* array
2483 * where we stashed them.
2484 */
2485 assert(sizeof(*interfaceIdxArray) == sizeof(*clazz->interfaces));
2486 size_t len = clazz->interfaceCount * sizeof(*interfaceIdxArray);
2487 interfaceIdxArray = malloc(len);
2488 if (interfaceIdxArray == NULL) {
2489 LOGW("Unable to allocate memory to link %s", clazz->descriptor);
2490 goto bail;
Barry Hayes3595a092010-05-24 12:13:30 -07002491 }
Barry Hayesc49db852010-05-14 13:43:34 -07002492 memcpy(interfaceIdxArray, clazz->interfaces, len);
2493 memset(clazz->interfaces, 0, len);
2494 }
2495
2496 assert(sizeof(superclassIdx) == sizeof(clazz->super));
2497 superclassIdx = (u4) clazz->super;
2498 clazz->super = NULL;
2499 /* After this line, clazz will be fair game for the GC. The
2500 * superclass and interfaces are all NULL.
2501 */
2502 clazz->status = CLASS_LOADED;
2503
2504 if (superclassIdx != kDexNoIndex) {
2505 clazz->super = dvmResolveClass(clazz, superclassIdx, false);
2506 if (clazz->super == NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002507 assert(dvmCheckException(dvmThreadSelf()));
Barry Hayesc49db852010-05-14 13:43:34 -07002508 if (gDvm.optimizing) {
2509 /* happens with "external" libs */
2510 LOGV("Unable to resolve superclass of %s (%d)\n",
2511 clazz->descriptor, superclassIdx);
2512 } else {
2513 LOGW("Unable to resolve superclass of %s (%d)\n",
2514 clazz->descriptor, superclassIdx);
2515 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002516 goto bail;
2517 }
2518 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002519
Barry Hayesc49db852010-05-14 13:43:34 -07002520 if (clazz->interfaceCount > 0) {
2521 /* Resolve the interfaces implemented directly by this class. */
2522 assert(interfaceIdxArray != NULL);
2523 dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
2524 for (i = 0; i < clazz->interfaceCount; i++) {
2525 assert(interfaceIdxArray[i] != kDexNoIndex);
2526 clazz->interfaces[i] =
2527 dvmResolveClass(clazz, interfaceIdxArray[i], false);
2528 if (clazz->interfaces[i] == NULL) {
2529 const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2530
2531 assert(dvmCheckException(dvmThreadSelf()));
2532 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2533
2534 const char* classDescriptor;
2535 classDescriptor =
2536 dexStringByTypeIdx(pDexFile, interfaceIdxArray[i]);
2537 if (gDvm.optimizing) {
2538 /* happens with "external" libs */
2539 LOGV("Failed resolving %s interface %d '%s'\n",
2540 clazz->descriptor, interfaceIdxArray[i],
2541 classDescriptor);
2542 } else {
2543 LOGI("Failed resolving %s interface %d '%s'\n",
2544 clazz->descriptor, interfaceIdxArray[i],
2545 classDescriptor);
2546 }
2547 goto bail;
2548 }
2549
2550 /* are we allowed to implement this interface? */
2551 if (!dvmCheckClassAccess(clazz, clazz->interfaces[i])) {
2552 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2553 LOGW("Interface '%s' is not accessible to '%s'\n",
2554 clazz->interfaces[i]->descriptor, clazz->descriptor);
2555 dvmThrowException("Ljava/lang/IllegalAccessError;",
2556 "interface not accessible");
2557 goto bail;
2558 }
2559 LOGVV("+++ found interface '%s'\n",
2560 clazz->interfaces[i]->descriptor);
2561 }
2562 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2563 }
2564 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002565 /*
Barry Hayesc49db852010-05-14 13:43:34 -07002566 * There are now Class references visible to the GC in super and
2567 * interfaces.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002568 */
2569
2570 /*
Barry Hayesc49db852010-05-14 13:43:34 -07002571 * All classes have a direct superclass, except for
2572 * java/lang/Object and primitive classes. Primitive classes are
2573 * are created CLASS_INITIALIZED, so won't get here.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002574 */
Barry Hayesc49db852010-05-14 13:43:34 -07002575 assert(clazz->primitiveType == PRIM_NOT);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002576 if (strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0) {
Barry Hayesc49db852010-05-14 13:43:34 -07002577 if (clazz->super != NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002578 /* TODO: is this invariant true for all java/lang/Objects,
2579 * regardless of the class loader? For now, assume it is.
2580 */
2581 dvmThrowException("Ljava/lang/ClassFormatError;",
2582 "java.lang.Object has a superclass");
2583 goto bail;
2584 }
2585
2586 /* Don't finalize objects whose classes use the
2587 * default (empty) Object.finalize().
2588 */
2589 CLEAR_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2590 } else {
Barry Hayesc49db852010-05-14 13:43:34 -07002591 if (clazz->super == NULL) {
2592 dvmThrowException("Ljava/lang/LinkageError;",
2593 "no superclass defined");
2594 goto bail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002595 }
2596 /* verify */
2597 if (dvmIsFinalClass(clazz->super)) {
2598 LOGW("Superclass of '%s' is final '%s'\n",
2599 clazz->descriptor, clazz->super->descriptor);
2600 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2601 "superclass is final");
2602 goto bail;
2603 } else if (dvmIsInterfaceClass(clazz->super)) {
2604 LOGW("Superclass of '%s' is interface '%s'\n",
2605 clazz->descriptor, clazz->super->descriptor);
2606 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2607 "superclass is an interface");
2608 goto bail;
2609 } else if (!dvmCheckClassAccess(clazz, clazz->super)) {
2610 LOGW("Superclass of '%s' (%s) is not accessible\n",
2611 clazz->descriptor, clazz->super->descriptor);
2612 dvmThrowException("Ljava/lang/IllegalAccessError;",
2613 "superclass not accessible");
2614 goto bail;
2615 }
2616
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002617 /* Inherit finalizability from the superclass. If this
2618 * class also overrides finalize(), its CLASS_ISFINALIZABLE
2619 * bit will already be set.
2620 */
2621 if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISFINALIZABLE)) {
2622 SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2623 }
2624
2625 /* See if this class descends from java.lang.Reference
2626 * and set the class flags appropriately.
2627 */
2628 if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISREFERENCE)) {
2629 u4 superRefFlags;
2630
2631 /* We've already determined the reference type of this
2632 * inheritance chain. Inherit reference-ness from the superclass.
2633 */
2634 superRefFlags = GET_CLASS_FLAG_GROUP(clazz->super,
2635 CLASS_ISREFERENCE |
2636 CLASS_ISWEAKREFERENCE |
2637 CLASS_ISPHANTOMREFERENCE);
2638 SET_CLASS_FLAG(clazz, superRefFlags);
2639 } else if (clazz->classLoader == NULL &&
2640 clazz->super->classLoader == NULL &&
2641 strcmp(clazz->super->descriptor,
2642 "Ljava/lang/ref/Reference;") == 0)
2643 {
2644 u4 refFlags;
2645
2646 /* This class extends Reference, which means it should
2647 * be one of the magic Soft/Weak/PhantomReference classes.
2648 */
2649 refFlags = CLASS_ISREFERENCE;
2650 if (strcmp(clazz->descriptor,
2651 "Ljava/lang/ref/SoftReference;") == 0)
2652 {
2653 /* Only CLASS_ISREFERENCE is set for soft references.
2654 */
2655 } else if (strcmp(clazz->descriptor,
2656 "Ljava/lang/ref/WeakReference;") == 0)
2657 {
2658 refFlags |= CLASS_ISWEAKREFERENCE;
2659 } else if (strcmp(clazz->descriptor,
2660 "Ljava/lang/ref/PhantomReference;") == 0)
2661 {
2662 refFlags |= CLASS_ISPHANTOMREFERENCE;
2663 } else {
2664 /* No-one else is allowed to inherit directly
2665 * from Reference.
2666 */
2667//xxx is this the right exception? better than an assertion.
2668 dvmThrowException("Ljava/lang/LinkageError;",
2669 "illegal inheritance from Reference");
2670 goto bail;
2671 }
2672
2673 /* The class should not have any reference bits set yet.
2674 */
2675 assert(GET_CLASS_FLAG_GROUP(clazz,
2676 CLASS_ISREFERENCE |
2677 CLASS_ISWEAKREFERENCE |
2678 CLASS_ISPHANTOMREFERENCE) == 0);
2679
2680 SET_CLASS_FLAG(clazz, refFlags);
2681 }
2682 }
2683
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002684 /*
2685 * Populate vtable.
2686 */
2687 if (dvmIsInterfaceClass(clazz)) {
2688 /* no vtable; just set the method indices */
2689 int count = clazz->virtualMethodCount;
2690
2691 if (count != (u2) count) {
2692 LOGE("Too many methods (%d) in interface '%s'\n", count,
2693 clazz->descriptor);
2694 goto bail;
2695 }
2696
2697 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2698
2699 for (i = 0; i < count; i++)
2700 clazz->virtualMethods[i].methodIndex = (u2) i;
2701
2702 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2703 } else {
2704 if (!createVtable(clazz)) {
2705 LOGW("failed creating vtable\n");
2706 goto bail;
2707 }
2708 }
2709
2710 /*
2711 * Populate interface method tables. Can alter the vtable.
2712 */
2713 if (!createIftable(clazz))
2714 goto bail;
2715
2716 /*
2717 * Insert special-purpose "stub" method implementations.
2718 */
2719 if (!insertMethodStubs(clazz))
2720 goto bail;
2721
2722 /*
2723 * Compute instance field offsets and, hence, the size of the object.
2724 */
2725 if (!computeFieldOffsets(clazz))
2726 goto bail;
2727
2728 /*
2729 * Cache fields and methods from java/lang/ref/Reference and
2730 * java/lang/Class. This has to happen after computeFieldOffsets().
2731 */
2732 if (clazz->classLoader == NULL) {
2733 if (strcmp(clazz->descriptor, "Ljava/lang/ref/Reference;") == 0) {
2734 if (!precacheReferenceOffsets(clazz)) {
2735 LOGE("failed pre-caching Reference offsets\n");
2736 dvmThrowException("Ljava/lang/InternalError;", NULL);
2737 goto bail;
2738 }
2739 } else if (clazz == gDvm.classJavaLangClass) {
2740 gDvm.offJavaLangClass_pd = dvmFindFieldOffset(clazz, "pd",
2741 "Ljava/security/ProtectionDomain;");
2742 if (gDvm.offJavaLangClass_pd <= 0) {
2743 LOGE("ERROR: unable to find 'pd' field in Class\n");
2744 dvmAbort(); /* we're not going to get much farther */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002745 }
2746 }
2747 }
2748
2749 /*
Barry Hayes6daaac12009-07-08 10:01:56 -07002750 * Compact the offsets the GC has to examine into a bitmap, if
2751 * possible. (This has to happen after Reference.referent is
2752 * massaged in precacheReferenceOffsets.)
2753 */
2754 computeRefOffsets(clazz);
2755
2756 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002757 * Done!
2758 */
2759 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED))
2760 clazz->status = CLASS_VERIFIED;
2761 else
2762 clazz->status = CLASS_RESOLVED;
2763 okay = true;
2764 if (gDvm.verboseClass)
2765 LOGV("CLASS: linked '%s'\n", clazz->descriptor);
2766
2767 /*
2768 * We send CLASS_PREPARE events to the debugger from here. The
2769 * definition of "preparation" is creating the static fields for a
2770 * class and initializing them to the standard default values, but not
2771 * executing any code (that comes later, during "initialization").
2772 *
2773 * We did the static prep in loadSFieldFromDex() while loading the class.
2774 *
2775 * The class has been prepared and resolved but possibly not yet verified
2776 * at this point.
2777 */
2778 if (gDvm.debuggerActive) {
2779 dvmDbgPostClassPrepare(clazz);
2780 }
2781
2782bail:
2783 if (!okay) {
2784 clazz->status = CLASS_ERROR;
2785 if (!dvmCheckException(dvmThreadSelf())) {
2786 dvmThrowException("Ljava/lang/VirtualMachineError;", NULL);
2787 }
2788 }
Barry Hayesc49db852010-05-14 13:43:34 -07002789 if (interfaceIdxArray != NULL) {
2790 free(interfaceIdxArray);
2791 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002792 return okay;
2793}
2794
2795/*
2796 * Create the virtual method table.
2797 *
2798 * The top part of the table is a copy of the table from our superclass,
2799 * with our local methods overriding theirs. The bottom part of the table
2800 * has any new methods we defined.
2801 */
2802static bool createVtable(ClassObject* clazz)
2803{
2804 bool result = false;
2805 int maxCount;
2806 int i;
2807
2808 if (clazz->super != NULL) {
2809 //LOGI("SUPER METHODS %d %s->%s\n", clazz->super->vtableCount,
2810 // clazz->descriptor, clazz->super->descriptor);
2811 }
2812
2813 /* the virtual methods we define, plus the superclass vtable size */
2814 maxCount = clazz->virtualMethodCount;
2815 if (clazz->super != NULL) {
2816 maxCount += clazz->super->vtableCount;
2817 } else {
2818 /* TODO: is this invariant true for all java/lang/Objects,
2819 * regardless of the class loader? For now, assume it is.
2820 */
2821 assert(strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0);
2822 }
2823 //LOGD("+++ max vmethods for '%s' is %d\n", clazz->descriptor, maxCount);
2824
2825 /*
2826 * Over-allocate the table, then realloc it down if necessary. So
2827 * long as we don't allocate anything in between we won't cause
2828 * fragmentation, and reducing the size should be unlikely to cause
2829 * a buffer copy.
2830 */
2831 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2832 clazz->vtable = (Method**) dvmLinearAlloc(clazz->classLoader,
2833 sizeof(Method*) * maxCount);
2834 if (clazz->vtable == NULL)
2835 goto bail;
2836
2837 if (clazz->super != NULL) {
2838 int actualCount;
2839
2840 memcpy(clazz->vtable, clazz->super->vtable,
2841 sizeof(*(clazz->vtable)) * clazz->super->vtableCount);
2842 actualCount = clazz->super->vtableCount;
2843
2844 /*
2845 * See if any of our virtual methods override the superclass.
2846 */
2847 for (i = 0; i < clazz->virtualMethodCount; i++) {
2848 Method* localMeth = &clazz->virtualMethods[i];
2849 int si;
2850
2851 for (si = 0; si < clazz->super->vtableCount; si++) {
2852 Method* superMeth = clazz->vtable[si];
2853
2854 if (dvmCompareMethodNamesAndProtos(localMeth, superMeth) == 0)
2855 {
2856 /* verify */
2857 if (dvmIsFinalMethod(superMeth)) {
2858 LOGW("Method %s.%s overrides final %s.%s\n",
2859 localMeth->clazz->descriptor, localMeth->name,
2860 superMeth->clazz->descriptor, superMeth->name);
2861 goto bail;
2862 }
2863 clazz->vtable[si] = localMeth;
2864 localMeth->methodIndex = (u2) si;
2865 //LOGV("+++ override %s.%s (slot %d)\n",
2866 // clazz->descriptor, localMeth->name, si);
2867 break;
2868 }
2869 }
2870
2871 if (si == clazz->super->vtableCount) {
2872 /* not an override, add to end */
2873 clazz->vtable[actualCount] = localMeth;
2874 localMeth->methodIndex = (u2) actualCount;
2875 actualCount++;
2876
2877 //LOGV("+++ add method %s.%s\n",
2878 // clazz->descriptor, localMeth->name);
2879 }
2880 }
2881
2882 if (actualCount != (u2) actualCount) {
2883 LOGE("Too many methods (%d) in class '%s'\n", actualCount,
2884 clazz->descriptor);
2885 goto bail;
2886 }
2887
2888 assert(actualCount <= maxCount);
2889
2890 if (actualCount < maxCount) {
2891 assert(clazz->vtable != NULL);
2892 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2893 clazz->vtable = dvmLinearRealloc(clazz->classLoader, clazz->vtable,
2894 sizeof(*(clazz->vtable)) * actualCount);
2895 if (clazz->vtable == NULL) {
2896 LOGE("vtable realloc failed\n");
2897 goto bail;
2898 } else {
2899 LOGVV("+++ reduced vtable from %d to %d\n",
2900 maxCount, actualCount);
2901 }
2902 }
2903
2904 clazz->vtableCount = actualCount;
2905 } else {
2906 /* java/lang/Object case */
2907 int count = clazz->virtualMethodCount;
2908 if (count != (u2) count) {
2909 LOGE("Too many methods (%d) in base class '%s'\n", count,
2910 clazz->descriptor);
2911 goto bail;
2912 }
2913
2914 for (i = 0; i < count; i++) {
2915 clazz->vtable[i] = &clazz->virtualMethods[i];
2916 clazz->virtualMethods[i].methodIndex = (u2) i;
2917 }
2918 clazz->vtableCount = clazz->virtualMethodCount;
2919 }
2920
2921 result = true;
2922
2923bail:
2924 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2925 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2926 return result;
2927}
2928
2929/*
2930 * Create and populate "iftable".
2931 *
2932 * The set of interfaces we support is the combination of the interfaces
2933 * we implement directly and those implemented by our superclass. Each
2934 * interface can have one or more "superinterfaces", which we must also
2935 * support. For speed we flatten the tree out.
2936 *
2937 * We might be able to speed this up when there are lots of interfaces
2938 * by merge-sorting the class pointers and binary-searching when removing
2939 * duplicates. We could also drop the duplicate removal -- it's only
2940 * there to reduce the memory footprint.
2941 *
2942 * Because of "Miranda methods", this may reallocate clazz->virtualMethods.
2943 *
2944 * Returns "true" on success.
2945 */
2946static bool createIftable(ClassObject* clazz)
2947{
2948 bool result = false;
2949 bool zapIftable = false;
2950 bool zapVtable = false;
2951 bool zapIfvipool = false;
2952 int ifCount, superIfCount, idx;
2953 int i;
2954
2955 if (clazz->super != NULL)
2956 superIfCount = clazz->super->iftableCount;
2957 else
2958 superIfCount = 0;
2959
2960 ifCount = superIfCount;
2961 ifCount += clazz->interfaceCount;
2962 for (i = 0; i < clazz->interfaceCount; i++)
2963 ifCount += clazz->interfaces[i]->iftableCount;
2964
2965 LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d\n",
2966 clazz->descriptor, ifCount - superIfCount, superIfCount, ifCount);
2967
2968 if (ifCount == 0) {
2969 assert(clazz->iftableCount == 0);
2970 assert(clazz->iftable == NULL);
2971 result = true;
2972 goto bail;
2973 }
2974
2975 /*
2976 * Create a table with enough space for all interfaces, and copy the
2977 * superclass' table in.
2978 */
2979 clazz->iftable = (InterfaceEntry*) dvmLinearAlloc(clazz->classLoader,
2980 sizeof(InterfaceEntry) * ifCount);
2981 zapIftable = true;
2982 memset(clazz->iftable, 0x00, sizeof(InterfaceEntry) * ifCount);
2983 if (superIfCount != 0) {
2984 memcpy(clazz->iftable, clazz->super->iftable,
2985 sizeof(InterfaceEntry) * superIfCount);
2986 }
2987
2988 /*
2989 * Create a flattened interface hierarchy of our immediate interfaces.
2990 */
2991 idx = superIfCount;
2992
2993 for (i = 0; i < clazz->interfaceCount; i++) {
2994 ClassObject* interf;
2995 int j;
2996
2997 interf = clazz->interfaces[i];
2998 assert(interf != NULL);
2999
3000 /* make sure this is still an interface class */
3001 if (!dvmIsInterfaceClass(interf)) {
3002 LOGW("Class '%s' implements non-interface '%s'\n",
3003 clazz->descriptor, interf->descriptor);
3004 dvmThrowExceptionWithClassMessage(
3005 "Ljava/lang/IncompatibleClassChangeError;",
3006 clazz->descriptor);
3007 goto bail;
3008 }
3009
3010 /* add entry for this interface */
3011 clazz->iftable[idx++].clazz = interf;
3012
3013 /* add entries for the interface's superinterfaces */
3014 for (j = 0; j < interf->iftableCount; j++) {
3015 clazz->iftable[idx++].clazz = interf->iftable[j].clazz;
3016 }
3017 }
3018
3019 assert(idx == ifCount);
3020
3021 if (false) {
3022 /*
3023 * Remove anything redundant from our recent additions. Note we have
3024 * to traverse the recent adds when looking for duplicates, because
3025 * it's possible the recent additions are self-redundant. This
3026 * reduces the memory footprint of classes with lots of inherited
3027 * interfaces.
3028 *
3029 * (I don't know if this will cause problems later on when we're trying
3030 * to find a static field. It looks like the proper search order is
3031 * (1) current class, (2) interfaces implemented by current class,
3032 * (3) repeat with superclass. A field implemented by an interface
3033 * and by a superclass might come out wrong if the superclass also
3034 * implements the interface. The javac compiler will reject the
3035 * situation as ambiguous, so the concern is somewhat artificial.)
3036 *
3037 * UPDATE: this makes ReferenceType.Interfaces difficult to implement,
3038 * because it wants to return just the interfaces declared to be
3039 * implemented directly by the class. I'm excluding this code for now.
3040 */
3041 for (i = superIfCount; i < ifCount; i++) {
3042 int j;
3043
3044 for (j = 0; j < ifCount; j++) {
3045 if (i == j)
3046 continue;
3047 if (clazz->iftable[i].clazz == clazz->iftable[j].clazz) {
3048 LOGVV("INTF: redundant interface %s in %s\n",
3049 clazz->iftable[i].clazz->descriptor,
3050 clazz->descriptor);
3051
3052 if (i != ifCount-1)
3053 memmove(&clazz->iftable[i], &clazz->iftable[i+1],
3054 (ifCount - i -1) * sizeof(InterfaceEntry));
3055 ifCount--;
3056 i--; // adjust for i++ above
3057 break;
3058 }
3059 }
3060 }
3061 LOGVV("INTF: class '%s' nodupes=%d\n", clazz->descriptor, ifCount);
3062 } // if (false)
3063
3064 clazz->iftableCount = ifCount;
3065
3066 /*
3067 * If we're an interface, we don't need the vtable pointers, so
3068 * we're done. If this class doesn't implement an interface that our
3069 * superclass doesn't have, then we again have nothing to do.
3070 */
3071 if (dvmIsInterfaceClass(clazz) || superIfCount == ifCount) {
3072 //dvmDumpClass(clazz, kDumpClassFullDetail);
3073 result = true;
3074 goto bail;
3075 }
3076
3077 /*
3078 * When we're handling invokeinterface, we probably have an object
3079 * whose type is an interface class rather than a concrete class. We
3080 * need to convert the method reference into a vtable index. So, for
3081 * every entry in "iftable", we create a list of vtable indices.
3082 *
3083 * Because our vtable encompasses the superclass vtable, we can use
3084 * the vtable indices from our superclass for all of the interfaces
3085 * that weren't directly implemented by us.
3086 *
3087 * Each entry in "iftable" has a pointer to the start of its set of
3088 * vtable offsets. The iftable entries in the superclass point to
3089 * storage allocated in the superclass, and the iftable entries added
3090 * for this class point to storage allocated in this class. "iftable"
3091 * is flat for fast access in a class and all of its subclasses, but
3092 * "ifviPool" is only created for the topmost implementor.
3093 */
3094 int poolSize = 0;
3095 for (i = superIfCount; i < ifCount; i++) {
3096 /*
3097 * Note it's valid for an interface to have no methods (e.g.
3098 * java/io/Serializable).
3099 */
3100 LOGVV("INTF: pool: %d from %s\n",
3101 clazz->iftable[i].clazz->virtualMethodCount,
3102 clazz->iftable[i].clazz->descriptor);
3103 poolSize += clazz->iftable[i].clazz->virtualMethodCount;
3104 }
3105
3106 if (poolSize == 0) {
3107 LOGVV("INTF: didn't find any new interfaces with methods\n");
3108 result = true;
3109 goto bail;
3110 }
3111
3112 clazz->ifviPoolCount = poolSize;
3113 clazz->ifviPool = (int*) dvmLinearAlloc(clazz->classLoader,
3114 poolSize * sizeof(int*));
3115 zapIfvipool = true;
3116
3117 /*
3118 * Fill in the vtable offsets for the interfaces that weren't part of
3119 * our superclass.
3120 */
3121 int poolOffset = 0;
3122 Method** mirandaList = NULL;
3123 int mirandaCount = 0, mirandaAlloc = 0;
3124
3125 for (i = superIfCount; i < ifCount; i++) {
3126 ClassObject* interface;
3127 int methIdx;
3128
3129 clazz->iftable[i].methodIndexArray = clazz->ifviPool + poolOffset;
3130 interface = clazz->iftable[i].clazz;
3131 poolOffset += interface->virtualMethodCount; // end here
3132
3133 /*
3134 * For each method listed in the interface's method list, find the
3135 * matching method in our class's method list. We want to favor the
3136 * subclass over the superclass, which just requires walking
3137 * back from the end of the vtable. (This only matters if the
3138 * superclass defines a private method and this class redefines
3139 * it -- otherwise it would use the same vtable slot. In Dalvik
3140 * those don't end up in the virtual method table, so it shouldn't
3141 * matter which direction we go. We walk it backward anyway.)
3142 *
3143 *
3144 * Suppose we have the following arrangement:
3145 * public interface MyInterface
3146 * public boolean inInterface();
3147 * public abstract class MirandaAbstract implements MirandaInterface
3148 * //public abstract boolean inInterface(); // not declared!
3149 * public boolean inAbstract() { stuff } // in vtable
3150 * public class MirandClass extends MirandaAbstract
3151 * public boolean inInterface() { stuff }
3152 * public boolean inAbstract() { stuff } // in vtable
3153 *
3154 * The javac compiler happily compiles MirandaAbstract even though
3155 * it doesn't declare all methods from its interface. When we try
3156 * to set up a vtable for MirandaAbstract, we find that we don't
3157 * have an slot for inInterface. To prevent this, we synthesize
3158 * abstract method declarations in MirandaAbstract.
3159 *
3160 * We have to expand vtable and update some things that point at it,
3161 * so we accumulate the method list and do it all at once below.
3162 */
3163 for (methIdx = 0; methIdx < interface->virtualMethodCount; methIdx++) {
3164 Method* imeth = &interface->virtualMethods[methIdx];
3165 int j;
3166
3167 IF_LOGVV() {
3168 char* desc = dexProtoCopyMethodDescriptor(&imeth->prototype);
3169 LOGVV("INTF: matching '%s' '%s'\n", imeth->name, desc);
3170 free(desc);
3171 }
3172
3173 for (j = clazz->vtableCount-1; j >= 0; j--) {
3174 if (dvmCompareMethodNamesAndProtos(imeth, clazz->vtable[j])
3175 == 0)
3176 {
3177 LOGVV("INTF: matched at %d\n", j);
3178 if (!dvmIsPublicMethod(clazz->vtable[j])) {
3179 LOGW("Implementation of %s.%s is not public\n",
3180 clazz->descriptor, clazz->vtable[j]->name);
3181 dvmThrowException("Ljava/lang/IllegalAccessError;",
3182 "interface implementation not public");
3183 goto bail;
3184 }
3185 clazz->iftable[i].methodIndexArray[methIdx] = j;
3186 break;
3187 }
3188 }
3189 if (j < 0) {
3190 IF_LOGV() {
3191 char* desc =
3192 dexProtoCopyMethodDescriptor(&imeth->prototype);
3193 LOGV("No match for '%s' '%s' in '%s' (creating miranda)\n",
3194 imeth->name, desc, clazz->descriptor);
3195 free(desc);
3196 }
3197 //dvmThrowException("Ljava/lang/RuntimeException;", "Miranda!");
3198 //return false;
3199
3200 if (mirandaCount == mirandaAlloc) {
3201 mirandaAlloc += 8;
3202 if (mirandaList == NULL) {
3203 mirandaList = dvmLinearAlloc(clazz->classLoader,
3204 mirandaAlloc * sizeof(Method*));
3205 } else {
3206 dvmLinearReadOnly(clazz->classLoader, mirandaList);
3207 mirandaList = dvmLinearRealloc(clazz->classLoader,
3208 mirandaList, mirandaAlloc * sizeof(Method*));
3209 }
3210 assert(mirandaList != NULL); // mem failed + we leaked
3211 }
3212
3213 /*
3214 * These may be redundant (e.g. method with same name and
3215 * signature declared in two interfaces implemented by the
3216 * same abstract class). We can squeeze the duplicates
3217 * out here.
3218 */
3219 int mir;
3220 for (mir = 0; mir < mirandaCount; mir++) {
3221 if (dvmCompareMethodNamesAndProtos(
3222 mirandaList[mir], imeth) == 0)
3223 {
3224 IF_LOGVV() {
3225 char* desc = dexProtoCopyMethodDescriptor(
3226 &imeth->prototype);
3227 LOGVV("MIRANDA dupe: %s and %s %s%s\n",
3228 mirandaList[mir]->clazz->descriptor,
3229 imeth->clazz->descriptor,
3230 imeth->name, desc);
3231 free(desc);
3232 }
3233 break;
3234 }
3235 }
3236
3237 /* point the iftable at a phantom slot index */
3238 clazz->iftable[i].methodIndexArray[methIdx] =
3239 clazz->vtableCount + mir;
3240 LOGVV("MIRANDA: %s points at slot %d\n",
3241 imeth->name, clazz->vtableCount + mir);
3242
3243 /* if non-duplicate among Mirandas, add to Miranda list */
3244 if (mir == mirandaCount) {
3245 //LOGV("MIRANDA: holding '%s' in slot %d\n",
3246 // imeth->name, mir);
3247 mirandaList[mirandaCount++] = imeth;
3248 }
3249 }
3250 }
3251 }
3252
3253 if (mirandaCount != 0) {
Andy McFadden68825972009-05-08 11:25:35 -07003254 static const int kManyMirandas = 150; /* arbitrary */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003255 Method* newVirtualMethods;
3256 Method* meth;
3257 int oldMethodCount, oldVtableCount;
3258
3259 for (i = 0; i < mirandaCount; i++) {
3260 LOGVV("MIRANDA %d: %s.%s\n", i,
3261 mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
3262 }
Andy McFadden68825972009-05-08 11:25:35 -07003263 if (mirandaCount > kManyMirandas) {
3264 /*
3265 * Some obfuscators like to create an interface with a huge
3266 * pile of methods, declare classes as implementing it, and then
3267 * only define a couple of methods. This leads to a rather
3268 * massive collection of Miranda methods and a lot of wasted
3269 * space, sometimes enough to blow out the LinearAlloc cap.
3270 */
3271 LOGD("Note: class %s has %d unimplemented (abstract) methods\n",
3272 clazz->descriptor, mirandaCount);
3273 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003274
3275 /*
3276 * We found methods in one or more interfaces for which we do not
3277 * have vtable entries. We have to expand our virtualMethods
3278 * table (which might be empty) to hold some new entries.
3279 */
3280 if (clazz->virtualMethods == NULL) {
3281 newVirtualMethods = (Method*) dvmLinearAlloc(clazz->classLoader,
3282 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3283 } else {
3284 //dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3285 newVirtualMethods = (Method*) dvmLinearRealloc(clazz->classLoader,
3286 clazz->virtualMethods,
3287 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3288 }
3289 if (newVirtualMethods != clazz->virtualMethods) {
3290 /*
3291 * Table was moved in memory. We have to run through the
3292 * vtable and fix the pointers. The vtable entries might be
3293 * pointing at superclasses, so we flip it around: run through
3294 * all locally-defined virtual methods, and fix their entries
3295 * in the vtable. (This would get really messy if sub-classes
3296 * had already been loaded.)
3297 *
3298 * Reminder: clazz->virtualMethods and clazz->virtualMethodCount
3299 * hold the virtual methods declared by this class. The
3300 * method's methodIndex is the vtable index, and is the same
3301 * for all sub-classes (and all super classes in which it is
3302 * defined). We're messing with these because the Miranda
3303 * stuff makes it look like the class actually has an abstract
3304 * method declaration in it.
3305 */
3306 LOGVV("MIRANDA fixing vtable pointers\n");
3307 dvmLinearReadWrite(clazz->classLoader, clazz->vtable);
3308 Method* meth = newVirtualMethods;
3309 for (i = 0; i < clazz->virtualMethodCount; i++, meth++)
3310 clazz->vtable[meth->methodIndex] = meth;
3311 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3312 }
3313
3314 oldMethodCount = clazz->virtualMethodCount;
3315 clazz->virtualMethods = newVirtualMethods;
3316 clazz->virtualMethodCount += mirandaCount;
3317
3318 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3319
3320 /*
3321 * We also have to expand the vtable.
3322 */
3323 assert(clazz->vtable != NULL);
3324 clazz->vtable = (Method**) dvmLinearRealloc(clazz->classLoader,
3325 clazz->vtable,
3326 sizeof(Method*) * (clazz->vtableCount + mirandaCount));
3327 if (clazz->vtable == NULL) {
3328 assert(false);
3329 goto bail;
3330 }
3331 zapVtable = true;
3332
3333 oldVtableCount = clazz->vtableCount;
3334 clazz->vtableCount += mirandaCount;
3335
3336 /*
3337 * Now we need to create the fake methods. We clone the abstract
3338 * method definition from the interface and then replace a few
3339 * things.
Andy McFadden68825972009-05-08 11:25:35 -07003340 *
3341 * The Method will be an "abstract native", with nativeFunc set to
3342 * dvmAbstractMethodStub().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003343 */
3344 meth = clazz->virtualMethods + oldMethodCount;
3345 for (i = 0; i < mirandaCount; i++, meth++) {
3346 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3347 cloneMethod(meth, mirandaList[i]);
3348 meth->clazz = clazz;
3349 meth->accessFlags |= ACC_MIRANDA;
3350 meth->methodIndex = (u2) (oldVtableCount + i);
3351 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3352
3353 /* point the new vtable entry at the new method */
3354 clazz->vtable[oldVtableCount + i] = meth;
3355 }
3356
3357 dvmLinearReadOnly(clazz->classLoader, mirandaList);
3358 dvmLinearFree(clazz->classLoader, mirandaList);
3359
3360 }
3361
3362 /*
3363 * TODO?
3364 * Sort the interfaces by number of declared methods. All we really
3365 * want is to get the interfaces with zero methods at the end of the
3366 * list, so that when we walk through the list during invoke-interface
3367 * we don't examine interfaces that can't possibly be useful.
3368 *
3369 * The set will usually be small, so a simple insertion sort works.
3370 *
3371 * We have to be careful not to change the order of two interfaces
3372 * that define the same method. (Not a problem if we only move the
3373 * zero-method interfaces to the end.)
3374 *
3375 * PROBLEM:
3376 * If we do this, we will no longer be able to identify super vs.
3377 * current class interfaces by comparing clazz->super->iftableCount. This
3378 * breaks anything that only wants to find interfaces declared directly
3379 * by the class (dvmFindStaticFieldHier, ReferenceType.Interfaces,
3380 * dvmDbgOutputAllInterfaces, etc). Need to provide a workaround.
3381 *
3382 * We can sort just the interfaces implemented directly by this class,
3383 * but that doesn't seem like it would provide much of an advantage. I'm
3384 * not sure this is worthwhile.
3385 *
3386 * (This has been made largely obsolete by the interface cache mechanism.)
3387 */
3388
3389 //dvmDumpClass(clazz);
3390
3391 result = true;
3392
3393bail:
3394 if (zapIftable)
3395 dvmLinearReadOnly(clazz->classLoader, clazz->iftable);
3396 if (zapVtable)
3397 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3398 if (zapIfvipool)
3399 dvmLinearReadOnly(clazz->classLoader, clazz->ifviPool);
3400 return result;
3401}
3402
3403
3404/*
3405 * Provide "stub" implementations for methods without them.
3406 *
3407 * Currently we provide an implementation for all abstract methods that
3408 * throws an AbstractMethodError exception. This allows us to avoid an
3409 * explicit check for abstract methods in every virtual call.
3410 *
3411 * NOTE: for Miranda methods, the method declaration is a clone of what
3412 * was found in the interface class. That copy may already have had the
3413 * function pointer filled in, so don't be surprised if it's not NULL.
3414 *
3415 * NOTE: this sets the "native" flag, giving us an "abstract native" method,
3416 * which is nonsensical. Need to make sure that this doesn't escape the
3417 * VM. We can either mask it out in reflection calls, or copy "native"
3418 * into the high 16 bits of accessFlags and check that internally.
3419 */
3420static bool insertMethodStubs(ClassObject* clazz)
3421{
3422 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3423
3424 Method* meth;
3425 int i;
3426
3427 meth = clazz->virtualMethods;
3428 for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
3429 if (dvmIsAbstractMethod(meth)) {
3430 assert(meth->insns == NULL);
3431 assert(meth->nativeFunc == NULL ||
3432 meth->nativeFunc == (DalvikBridgeFunc)dvmAbstractMethodStub);
3433
3434 meth->accessFlags |= ACC_NATIVE;
3435 meth->nativeFunc = (DalvikBridgeFunc) dvmAbstractMethodStub;
3436 }
3437 }
3438
3439 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3440 return true;
3441}
3442
3443
3444/*
3445 * Swap two instance fields.
3446 */
3447static inline void swapField(InstField* pOne, InstField* pTwo)
3448{
3449 InstField swap;
3450
3451 LOGVV(" --- swap '%s' and '%s'\n", pOne->field.name, pTwo->field.name);
3452 swap = *pOne;
3453 *pOne = *pTwo;
3454 *pTwo = swap;
3455}
3456
3457/*
3458 * Assign instance fields to u4 slots.
3459 *
3460 * The top portion of the instance field area is occupied by the superclass
3461 * fields, the bottom by the fields for this class.
3462 *
3463 * "long" and "double" fields occupy two adjacent slots. On some
3464 * architectures, 64-bit quantities must be 64-bit aligned, so we need to
3465 * arrange fields (or introduce padding) to ensure this. We assume the
3466 * fields of the topmost superclass (i.e. Object) are 64-bit aligned, so
3467 * we can just ensure that the offset is "even". To avoid wasting space,
3468 * we want to move non-reference 32-bit fields into gaps rather than
3469 * creating pad words.
3470 *
3471 * In the worst case we will waste 4 bytes, but because objects are
3472 * allocated on >= 64-bit boundaries, those bytes may well be wasted anyway
3473 * (assuming this is the most-derived class).
3474 *
3475 * Pad words are not represented in the field table, so the field table
3476 * itself does not change size.
3477 *
3478 * The number of field slots determines the size of the object, so we
3479 * set that here too.
3480 *
3481 * This function feels a little more complicated than I'd like, but it
3482 * has the property of moving the smallest possible set of fields, which
3483 * should reduce the time required to load a class.
3484 *
3485 * NOTE: reference fields *must* come first, or precacheReferenceOffsets()
3486 * will break.
3487 */
3488static bool computeFieldOffsets(ClassObject* clazz)
3489{
3490 int fieldOffset;
3491 int i, j;
3492
3493 dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
3494
3495 if (clazz->super != NULL)
3496 fieldOffset = clazz->super->objectSize;
3497 else
3498 fieldOffset = offsetof(DataObject, instanceData);
3499
3500 LOGVV("--- computeFieldOffsets '%s'\n", clazz->descriptor);
3501
3502 //LOGI("OFFSETS fieldCount=%d\n", clazz->ifieldCount);
3503 //LOGI("dataobj, instance: %d\n", offsetof(DataObject, instanceData));
3504 //LOGI("classobj, access: %d\n", offsetof(ClassObject, accessFlags));
3505 //LOGI("super=%p, fieldOffset=%d\n", clazz->super, fieldOffset);
3506
3507 /*
3508 * Start by moving all reference fields to the front.
3509 */
3510 clazz->ifieldRefCount = 0;
3511 j = clazz->ifieldCount - 1;
3512 for (i = 0; i < clazz->ifieldCount; i++) {
3513 InstField* pField = &clazz->ifields[i];
3514 char c = pField->field.signature[0];
3515
3516 if (c != '[' && c != 'L') {
3517 /* This isn't a reference field; see if any reference fields
3518 * follow this one. If so, we'll move it to this position.
3519 * (quicksort-style partitioning)
3520 */
3521 while (j > i) {
3522 InstField* refField = &clazz->ifields[j--];
3523 char rc = refField->field.signature[0];
3524
3525 if (rc == '[' || rc == 'L') {
3526 /* Here's a reference field that follows at least one
3527 * non-reference field. Swap it with the current field.
3528 * (When this returns, "pField" points to the reference
3529 * field, and "refField" points to the non-ref field.)
3530 */
3531 swapField(pField, refField);
3532
3533 /* Fix the signature.
3534 */
3535 c = rc;
3536
3537 clazz->ifieldRefCount++;
3538 break;
3539 }
3540 }
3541 /* We may or may not have swapped a field.
3542 */
3543 } else {
3544 /* This is a reference field.
3545 */
3546 clazz->ifieldRefCount++;
3547 }
3548
3549 /*
3550 * If we've hit the end of the reference fields, break.
3551 */
3552 if (c != '[' && c != 'L')
3553 break;
3554
3555 pField->byteOffset = fieldOffset;
3556 fieldOffset += sizeof(u4);
3557 LOGVV(" --- offset1 '%s'=%d\n", pField->field.name,pField->byteOffset);
3558 }
3559
3560 /*
3561 * Now we want to pack all of the double-wide fields together. If we're
3562 * not aligned, though, we want to shuffle one 32-bit field into place.
3563 * If we can't find one, we'll have to pad it.
3564 */
3565 if (i != clazz->ifieldCount && (fieldOffset & 0x04) != 0) {
3566 LOGVV(" +++ not aligned\n");
3567
3568 InstField* pField = &clazz->ifields[i];
3569 char c = pField->field.signature[0];
3570
3571 if (c != 'J' && c != 'D') {
3572 /*
3573 * The field that comes next is 32-bit, so just advance past it.
3574 */
3575 assert(c != '[' && c != 'L');
3576 pField->byteOffset = fieldOffset;
3577 fieldOffset += sizeof(u4);
3578 i++;
3579 LOGVV(" --- offset2 '%s'=%d\n",
3580 pField->field.name, pField->byteOffset);
3581 } else {
3582 /*
3583 * Next field is 64-bit, so search for a 32-bit field we can
3584 * swap into it.
3585 */
3586 bool found = false;
3587 j = clazz->ifieldCount - 1;
3588 while (j > i) {
3589 InstField* singleField = &clazz->ifields[j--];
3590 char rc = singleField->field.signature[0];
3591
3592 if (rc != 'J' && rc != 'D') {
3593 swapField(pField, singleField);
3594 //c = rc;
3595 LOGVV(" +++ swapped '%s' for alignment\n",
3596 pField->field.name);
3597 pField->byteOffset = fieldOffset;
3598 fieldOffset += sizeof(u4);
3599 LOGVV(" --- offset3 '%s'=%d\n",
3600 pField->field.name, pField->byteOffset);
3601 found = true;
3602 i++;
3603 break;
3604 }
3605 }
3606 if (!found) {
3607 LOGV(" +++ inserting pad field in '%s'\n", clazz->descriptor);
3608 fieldOffset += sizeof(u4);
3609 }
3610 }
3611 }
3612
3613 /*
3614 * Alignment is good, shuffle any double-wide fields forward, and
3615 * finish assigning field offsets to all fields.
3616 */
3617 assert(i == clazz->ifieldCount || (fieldOffset & 0x04) == 0);
3618 j = clazz->ifieldCount - 1;
3619 for ( ; i < clazz->ifieldCount; i++) {
3620 InstField* pField = &clazz->ifields[i];
3621 char c = pField->field.signature[0];
3622
3623 if (c != 'D' && c != 'J') {
3624 /* This isn't a double-wide field; see if any double fields
3625 * follow this one. If so, we'll move it to this position.
3626 * (quicksort-style partitioning)
3627 */
3628 while (j > i) {
3629 InstField* doubleField = &clazz->ifields[j--];
3630 char rc = doubleField->field.signature[0];
3631
3632 if (rc == 'D' || rc == 'J') {
3633 /* Here's a double-wide field that follows at least one
3634 * non-double field. Swap it with the current field.
3635 * (When this returns, "pField" points to the reference
3636 * field, and "doubleField" points to the non-double field.)
3637 */
3638 swapField(pField, doubleField);
3639 c = rc;
3640
3641 break;
3642 }
3643 }
3644 /* We may or may not have swapped a field.
3645 */
3646 } else {
3647 /* This is a double-wide field, leave it be.
3648 */
3649 }
3650
3651 pField->byteOffset = fieldOffset;
3652 LOGVV(" --- offset4 '%s'=%d\n", pField->field.name,pField->byteOffset);
3653 fieldOffset += sizeof(u4);
3654 if (c == 'J' || c == 'D')
3655 fieldOffset += sizeof(u4);
3656 }
3657
3658#ifndef NDEBUG
3659 /* Make sure that all reference fields appear before
3660 * non-reference fields, and all double-wide fields are aligned.
3661 */
3662 j = 0; // seen non-ref
3663 for (i = 0; i < clazz->ifieldCount; i++) {
3664 InstField *pField = &clazz->ifields[i];
3665 char c = pField->field.signature[0];
3666
3667 if (c == 'D' || c == 'J') {
3668 assert((pField->byteOffset & 0x07) == 0);
3669 }
3670
3671 if (c != '[' && c != 'L') {
3672 if (!j) {
3673 assert(i == clazz->ifieldRefCount);
3674 j = 1;
3675 }
3676 } else if (j) {
3677 assert(false);
3678 }
3679 }
3680 if (!j) {
3681 assert(clazz->ifieldRefCount == clazz->ifieldCount);
3682 }
3683#endif
3684
3685 /*
3686 * We map a C struct directly on top of java/lang/Class objects. Make
3687 * sure we left enough room for the instance fields.
3688 */
3689 assert(clazz != gDvm.classJavaLangClass || (size_t)fieldOffset <
3690 offsetof(ClassObject, instanceData) + sizeof(clazz->instanceData));
3691
3692 clazz->objectSize = fieldOffset;
3693
3694 dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
3695 return true;
3696}
3697
3698/*
3699 * Throw the VM-spec-mandated error when an exception is thrown during
3700 * class initialization.
3701 *
3702 * The safest way to do this is to call the ExceptionInInitializerError
3703 * constructor that takes a Throwable.
3704 *
3705 * [Do we want to wrap it if the original is an Error rather than
3706 * an Exception?]
3707 */
3708static void throwClinitError(void)
3709{
3710 Thread* self = dvmThreadSelf();
3711 Object* exception;
3712 Object* eiie;
3713
3714 exception = dvmGetException(self);
3715 dvmAddTrackedAlloc(exception, self);
3716 dvmClearException(self);
3717
3718 if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3719 /*
3720 * Always resolves to same thing -- no race condition.
3721 */
3722 gDvm.classJavaLangExceptionInInitializerError =
3723 dvmFindSystemClass(
3724 "Ljava/lang/ExceptionInInitializerError;");
3725 if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3726 LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3727 goto fail;
3728 }
3729
3730 gDvm.methJavaLangExceptionInInitializerError_init =
3731 dvmFindDirectMethodByDescriptor(gDvm.classJavaLangExceptionInInitializerError,
3732 "<init>", "(Ljava/lang/Throwable;)V");
3733 if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) {
3734 LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3735 goto fail;
3736 }
3737 }
3738
3739 eiie = dvmAllocObject(gDvm.classJavaLangExceptionInInitializerError,
3740 ALLOC_DEFAULT);
3741 if (eiie == NULL)
3742 goto fail;
3743
3744 /*
3745 * Construct the new object, and replace the exception with it.
3746 */
3747 JValue unused;
3748 dvmCallMethod(self, gDvm.methJavaLangExceptionInInitializerError_init,
3749 eiie, &unused, exception);
3750 dvmSetException(self, eiie);
3751 dvmReleaseTrackedAlloc(eiie, NULL);
3752 dvmReleaseTrackedAlloc(exception, self);
3753 return;
3754
3755fail: /* restore original exception */
3756 dvmSetException(self, exception);
3757 dvmReleaseTrackedAlloc(exception, self);
3758 return;
3759}
3760
3761/*
3762 * The class failed to initialize on a previous attempt, so we want to throw
3763 * a NoClassDefFoundError (v2 2.17.5). The exception to this rule is if we
3764 * failed in verification, in which case v2 5.4.1 says we need to re-throw
3765 * the previous error.
3766 */
3767static void throwEarlierClassFailure(ClassObject* clazz)
3768{
3769 LOGI("Rejecting re-init on previously-failed class %s v=%p\n",
3770 clazz->descriptor, clazz->verifyErrorClass);
3771
3772 if (clazz->verifyErrorClass == NULL) {
3773 dvmThrowExceptionWithClassMessage("Ljava/lang/NoClassDefFoundError;",
3774 clazz->descriptor);
3775 } else {
3776 dvmThrowExceptionByClassWithClassMessage(clazz->verifyErrorClass,
3777 clazz->descriptor);
3778 }
3779}
3780
3781/*
3782 * Initialize any static fields whose values are stored in
3783 * the DEX file. This must be done during class initialization.
3784 */
3785static void initSFields(ClassObject* clazz)
3786{
3787 Thread* self = dvmThreadSelf(); /* for dvmReleaseTrackedAlloc() */
3788 DexFile* pDexFile;
3789 const DexClassDef* pClassDef;
3790 const DexEncodedArray* pValueList;
3791 EncodedArrayIterator iterator;
3792 int i;
3793
3794 if (clazz->sfieldCount == 0) {
3795 return;
3796 }
3797 if (clazz->pDvmDex == NULL) {
3798 /* generated class; any static fields should already be set up */
3799 LOGV("Not initializing static fields in %s\n", clazz->descriptor);
3800 return;
3801 }
3802 pDexFile = clazz->pDvmDex->pDexFile;
3803
3804 pClassDef = dexFindClass(pDexFile, clazz->descriptor);
3805 assert(pClassDef != NULL);
3806
3807 pValueList = dexGetStaticValuesList(pDexFile, pClassDef);
3808 if (pValueList == NULL) {
3809 return;
3810 }
3811
3812 dvmEncodedArrayIteratorInitialize(&iterator, pValueList, clazz);
3813
3814 /*
3815 * Iterate over the initial values array, setting the corresponding
3816 * static field for each array element.
3817 */
3818
3819 for (i = 0; dvmEncodedArrayIteratorHasNext(&iterator); i++) {
3820 AnnotationValue value;
3821 bool parsed = dvmEncodedArrayIteratorGetNext(&iterator, &value);
3822 StaticField* sfield = &clazz->sfields[i];
3823 const char* descriptor = sfield->field.signature;
3824 bool needRelease = false;
3825
3826 if (! parsed) {
3827 /*
3828 * TODO: Eventually verification should attempt to ensure
3829 * that this can't happen at least due to a data integrity
3830 * problem.
3831 */
3832 LOGE("Static initializer parse failed for %s at index %d",
3833 clazz->descriptor, i);
3834 dvmAbort();
3835 }
3836
3837 /* Verify that the value we got was of a valid type. */
3838
3839 switch (descriptor[0]) {
3840 case 'Z': parsed = (value.type == kDexAnnotationBoolean); break;
3841 case 'B': parsed = (value.type == kDexAnnotationByte); break;
3842 case 'C': parsed = (value.type == kDexAnnotationChar); break;
3843 case 'S': parsed = (value.type == kDexAnnotationShort); break;
3844 case 'I': parsed = (value.type == kDexAnnotationInt); break;
3845 case 'J': parsed = (value.type == kDexAnnotationLong); break;
3846 case 'F': parsed = (value.type == kDexAnnotationFloat); break;
3847 case 'D': parsed = (value.type == kDexAnnotationDouble); break;
3848 case '[': parsed = (value.type == kDexAnnotationNull); break;
3849 case 'L': {
3850 switch (value.type) {
3851 case kDexAnnotationNull: {
3852 /* No need for further tests. */
3853 break;
3854 }
3855 case kDexAnnotationString: {
3856 parsed =
3857 (strcmp(descriptor, "Ljava/lang/String;") == 0);
3858 needRelease = true;
3859 break;
3860 }
3861 case kDexAnnotationType: {
3862 parsed =
3863 (strcmp(descriptor, "Ljava/lang/Class;") == 0);
3864 needRelease = true;
3865 break;
3866 }
3867 default: {
3868 parsed = false;
3869 break;
3870 }
3871 }
3872 break;
3873 }
3874 default: {
3875 parsed = false;
3876 break;
3877 }
3878 }
3879
3880 if (parsed) {
3881 /*
3882 * All's well, so store the value. Note: This always
3883 * stores the full width of a JValue, even though most of
3884 * the time only the first word is needed.
3885 */
3886 sfield->value = value.value;
3887 if (needRelease) {
3888 dvmReleaseTrackedAlloc(value.value.l, self);
3889 }
3890 } else {
3891 /*
3892 * Something up above had a problem. TODO: See comment
3893 * above the switch about verfication.
3894 */
3895 LOGE("Bogus static initialization: value type %d in field type "
3896 "%s for %s at index %d",
3897 value.type, descriptor, clazz->descriptor, i);
3898 dvmAbort();
3899 }
3900 }
3901}
3902
3903
3904/*
3905 * Determine whether "descriptor" yields the same class object in the
3906 * context of clazz1 and clazz2.
3907 *
3908 * The caller must hold gDvm.loadedClasses.
3909 *
3910 * Returns "true" if they match.
3911 */
3912static bool compareDescriptorClasses(const char* descriptor,
3913 const ClassObject* clazz1, const ClassObject* clazz2)
3914{
3915 ClassObject* result1;
3916 ClassObject* result2;
3917
3918 /*
3919 * Do the first lookup by name.
3920 */
3921 result1 = dvmFindClassNoInit(descriptor, clazz1->classLoader);
3922
3923 /*
3924 * We can skip a second lookup by name if the second class loader is
3925 * in the initiating loader list of the class object we retrieved.
3926 * (This means that somebody already did a lookup of this class through
3927 * the second loader, and it resolved to the same class.) If it's not
3928 * there, we may simply not have had an opportunity to add it yet, so
3929 * we do the full lookup.
3930 *
3931 * The initiating loader test should catch the majority of cases
3932 * (in particular, the zillions of references to String/Object).
3933 *
3934 * Unfortunately we're still stuck grabbing a mutex to do the lookup.
3935 *
3936 * For this to work, the superclass/interface should be the first
3937 * argument, so that way if it's from the bootstrap loader this test
3938 * will work. (The bootstrap loader, by definition, never shows up
3939 * as the initiating loader of a class defined by some other loader.)
3940 */
3941 dvmHashTableLock(gDvm.loadedClasses);
3942 bool isInit = dvmLoaderInInitiatingList(result1, clazz2->classLoader);
3943 dvmHashTableUnlock(gDvm.loadedClasses);
3944
3945 if (isInit) {
3946 //printf("%s(obj=%p) / %s(cl=%p): initiating\n",
3947 // result1->descriptor, result1,
3948 // clazz2->descriptor, clazz2->classLoader);
3949 return true;
3950 } else {
3951 //printf("%s(obj=%p) / %s(cl=%p): RAW\n",
3952 // result1->descriptor, result1,
3953 // clazz2->descriptor, clazz2->classLoader);
3954 result2 = dvmFindClassNoInit(descriptor, clazz2->classLoader);
3955 }
3956
3957 if (result1 == NULL || result2 == NULL) {
3958 dvmClearException(dvmThreadSelf());
3959 if (result1 == result2) {
3960 /*
3961 * Neither class loader could find this class. Apparently it
3962 * doesn't exist.
3963 *
3964 * We can either throw some sort of exception now, or just
3965 * assume that it'll fail later when something actually tries
3966 * to use the class. For strict handling we should throw now,
3967 * because a "tricky" class loader could start returning
3968 * something later, and a pair of "tricky" loaders could set
3969 * us up for confusion.
3970 *
3971 * I'm not sure if we're allowed to complain about nonexistent
3972 * classes in method signatures during class init, so for now
3973 * this will just return "true" and let nature take its course.
3974 */
3975 return true;
3976 } else {
3977 /* only one was found, so clearly they're not the same */
3978 return false;
3979 }
3980 }
3981
3982 return result1 == result2;
3983}
3984
3985/*
3986 * For every component in the method descriptor, resolve the class in the
3987 * context of the two classes and compare the results.
3988 *
3989 * For best results, the "superclass" class should be first.
3990 *
3991 * Returns "true" if the classes match, "false" otherwise.
3992 */
3993static bool checkMethodDescriptorClasses(const Method* meth,
3994 const ClassObject* clazz1, const ClassObject* clazz2)
3995{
3996 DexParameterIterator iterator;
3997 const char* descriptor;
3998
3999 /* walk through the list of parameters */
4000 dexParameterIteratorInit(&iterator, &meth->prototype);
4001 while (true) {
4002 descriptor = dexParameterIteratorNextDescriptor(&iterator);
4003
4004 if (descriptor == NULL)
4005 break;
4006
4007 if (descriptor[0] == 'L' || descriptor[0] == '[') {
4008 /* non-primitive type */
4009 if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4010 return false;
4011 }
4012 }
4013
4014 /* check the return type */
4015 descriptor = dexProtoGetReturnType(&meth->prototype);
4016 if (descriptor[0] == 'L' || descriptor[0] == '[') {
4017 if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4018 return false;
4019 }
4020 return true;
4021}
4022
4023/*
4024 * Validate the descriptors in the superclass and interfaces.
4025 *
4026 * What we need to do is ensure that the classes named in the method
4027 * descriptors in our ancestors and ourselves resolve to the same class
Andy McFaddencab8be02009-05-26 13:39:57 -07004028 * objects. We can get conflicts when the classes come from different
4029 * class loaders, and the resolver comes up with different results for
4030 * the same class name in different contexts.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004031 *
Andy McFaddencab8be02009-05-26 13:39:57 -07004032 * An easy way to cause the problem is to declare a base class that uses
4033 * class Foo in a method signature (e.g. as the return type). Then,
4034 * define a subclass and a different version of Foo, and load them from a
4035 * different class loader. If the subclass overrides the method, it will
4036 * have a different concept of what Foo is than its parent does, so even
4037 * though the method signature strings are identical, they actually mean
4038 * different things.
4039 *
4040 * A call to the method through a base-class reference would be treated
4041 * differently than a call to the method through a subclass reference, which
4042 * isn't the way polymorphism works, so we have to reject the subclass.
4043 * If the subclass doesn't override the base method, then there's no
4044 * problem, because calls through base-class references and subclass
4045 * references end up in the same place.
4046 *
4047 * We don't need to check to see if an interface's methods match with its
4048 * superinterface's methods, because you can't instantiate an interface
4049 * and do something inappropriate with it. If interface I1 extends I2
4050 * and is implemented by C, and I1 and I2 are in separate class loaders
4051 * and have conflicting views of other classes, we will catch the conflict
4052 * when we process C. Anything that implements I1 is doomed to failure,
4053 * but we don't need to catch that while processing I1.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004054 *
4055 * On failure, throws an exception and returns "false".
4056 */
4057static bool validateSuperDescriptors(const ClassObject* clazz)
4058{
4059 int i;
4060
4061 if (dvmIsInterfaceClass(clazz))
4062 return true;
4063
4064 /*
4065 * Start with the superclass-declared methods.
4066 */
4067 if (clazz->super != NULL &&
4068 clazz->classLoader != clazz->super->classLoader)
4069 {
4070 /*
Andy McFaddencab8be02009-05-26 13:39:57 -07004071 * Walk through every overridden method and compare resolved
4072 * descriptor components. We pull the Method structs out of
4073 * the vtable. It doesn't matter whether we get the struct from
4074 * the parent or child, since we just need the UTF-8 descriptor,
4075 * which must match.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004076 *
4077 * We need to do this even for the stuff inherited from Object,
4078 * because it's possible that the new class loader has redefined
4079 * a basic class like String.
Andy McFaddene7b30942009-05-27 12:42:38 -07004080 *
4081 * We don't need to check stuff defined in a superclass because
4082 * it was checked when the superclass was loaded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004083 */
4084 const Method* meth;
4085
4086 //printf("Checking %s %p vs %s %p\n",
4087 // clazz->descriptor, clazz->classLoader,
4088 // clazz->super->descriptor, clazz->super->classLoader);
4089 for (i = clazz->super->vtableCount - 1; i >= 0; i--) {
4090 meth = clazz->vtable[i];
Andy McFaddencab8be02009-05-26 13:39:57 -07004091 if (meth != clazz->super->vtable[i] &&
4092 !checkMethodDescriptorClasses(meth, clazz->super, clazz))
4093 {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004094 LOGW("Method mismatch: %s in %s (cl=%p) and super %s (cl=%p)\n",
4095 meth->name, clazz->descriptor, clazz->classLoader,
4096 clazz->super->descriptor, clazz->super->classLoader);
4097 dvmThrowException("Ljava/lang/LinkageError;",
4098 "Classes resolve differently in superclass");
4099 return false;
4100 }
4101 }
4102 }
4103
4104 /*
Andy McFaddene7b30942009-05-27 12:42:38 -07004105 * Check the methods defined by this class against the interfaces it
4106 * implements. If we inherited the implementation from a superclass,
4107 * we have to check it against the superclass (which might be in a
4108 * different class loader). If the superclass also implements the
4109 * interface, we could skip the check since by definition it was
4110 * performed when the class was loaded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004111 */
4112 for (i = 0; i < clazz->iftableCount; i++) {
4113 const InterfaceEntry* iftable = &clazz->iftable[i];
4114
4115 if (clazz->classLoader != iftable->clazz->classLoader) {
4116 const ClassObject* iface = iftable->clazz;
4117 int j;
4118
4119 for (j = 0; j < iface->virtualMethodCount; j++) {
4120 const Method* meth;
4121 int vtableIndex;
4122
4123 vtableIndex = iftable->methodIndexArray[j];
4124 meth = clazz->vtable[vtableIndex];
4125
Andy McFaddene7b30942009-05-27 12:42:38 -07004126 if (!checkMethodDescriptorClasses(meth, iface, meth->clazz)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004127 LOGW("Method mismatch: %s in %s (cl=%p) and "
4128 "iface %s (cl=%p)\n",
4129 meth->name, clazz->descriptor, clazz->classLoader,
4130 iface->descriptor, iface->classLoader);
4131 dvmThrowException("Ljava/lang/LinkageError;",
4132 "Classes resolve differently in interface");
4133 return false;
4134 }
4135 }
4136 }
4137 }
4138
4139 return true;
4140}
4141
4142/*
4143 * Returns true if the class is being initialized by us (which means that
4144 * calling dvmInitClass will return immediately after fiddling with locks).
4145 *
4146 * There isn't a race here, because either clazz->initThreadId won't match
4147 * us, or it will and it was set in the same thread.
4148 */
4149bool dvmIsClassInitializing(const ClassObject* clazz)
4150{
4151 return (clazz->status == CLASS_INITIALIZING &&
4152 clazz->initThreadId == dvmThreadSelf()->threadId);
4153}
4154
4155/*
4156 * If a class has not been initialized, do so by executing the code in
4157 * <clinit>. The sequence is described in the VM spec v2 2.17.5.
4158 *
4159 * It is possible for multiple threads to arrive here simultaneously, so
4160 * we need to lock the class while we check stuff. We know that no
4161 * interpreted code has access to the class yet, so we can use the class's
4162 * monitor lock.
4163 *
4164 * We will often be called recursively, e.g. when the <clinit> code resolves
4165 * one of its fields, the field resolution will try to initialize the class.
Andy McFadden77514ab2010-05-06 13:39:07 -07004166 * In that case we will return "true" even though the class isn't actually
4167 * ready to go. The ambiguity can be resolved with dvmIsClassInitializing().
4168 * (TODO: consider having this return an enum to avoid the extra call --
4169 * return -1 on failure, 0 on success, 1 on still-initializing. Looks like
4170 * dvmIsClassInitializing() is always paired with *Initialized())
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004171 *
4172 * This can get very interesting if a class has a static field initialized
4173 * to a new instance of itself. <clinit> will end up calling <init> on
4174 * the members it is initializing, which is fine unless it uses the contents
4175 * of static fields to initialize instance fields. This will leave the
4176 * static-referenced objects in a partially initialized state. This is
4177 * reasonably rare and can sometimes be cured with proper field ordering.
4178 *
4179 * On failure, returns "false" with an exception raised.
4180 *
4181 * -----
4182 *
4183 * It is possible to cause a deadlock by having a situation like this:
4184 * class A { static { sleep(10000); new B(); } }
4185 * class B { static { sleep(10000); new A(); } }
4186 * new Thread() { public void run() { new A(); } }.start();
4187 * new Thread() { public void run() { new B(); } }.start();
4188 * This appears to be expected under the spec.
4189 *
4190 * The interesting question is what to do if somebody calls Thread.interrupt()
4191 * on one of the deadlocked threads. According to the VM spec, they're both
4192 * sitting in "wait". Should the interrupt code quietly raise the
4193 * "interrupted" flag, or should the "wait" return immediately with an
4194 * exception raised?
4195 *
4196 * This gets a little murky. The VM spec says we call "wait", and the
4197 * spec for Thread.interrupt says Object.wait is interruptible. So it
4198 * seems that, if we get unlucky and interrupt class initialization, we
4199 * are expected to throw (which gets converted to ExceptionInInitializerError
4200 * since InterruptedException is checked).
4201 *
4202 * There are a couple of problems here. First, all threads are expected to
4203 * present a consistent view of class initialization, so we can't have it
4204 * fail in one thread and succeed in another. Second, once a class fails
4205 * to initialize, it must *always* fail. This means that a stray interrupt()
4206 * call could render a class unusable for the lifetime of the VM.
4207 *
4208 * In most cases -- the deadlock example above being a counter-example --
4209 * the interrupting thread can't tell whether the target thread handled
4210 * the initialization itself or had to wait while another thread did the
4211 * work. Refusing to interrupt class initialization is, in most cases,
4212 * not something that a program can reliably detect.
4213 *
4214 * On the assumption that interrupting class initialization is highly
4215 * undesirable in most circumstances, and that failing to do so does not
4216 * deviate from the spec in a meaningful way, we don't allow class init
4217 * to be interrupted by Thread.interrupt().
4218 */
4219bool dvmInitClass(ClassObject* clazz)
4220{
4221#if LOG_CLASS_LOADING
4222 bool initializedByUs = false;
4223#endif
4224
4225 Thread* self = dvmThreadSelf();
4226 const Method* method;
4227
4228 dvmLockObject(self, (Object*) clazz);
4229 assert(dvmIsClassLinked(clazz) || clazz->status == CLASS_ERROR);
4230
4231 /*
4232 * If the class hasn't been verified yet, do so now.
4233 */
4234 if (clazz->status < CLASS_VERIFIED) {
4235 /*
4236 * If we're in an "erroneous" state, throw an exception and bail.
4237 */
4238 if (clazz->status == CLASS_ERROR) {
4239 throwEarlierClassFailure(clazz);
4240 goto bail_unlock;
4241 }
4242
4243 assert(clazz->status == CLASS_RESOLVED);
4244 assert(!IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4245
4246 if (gDvm.classVerifyMode == VERIFY_MODE_NONE ||
4247 (gDvm.classVerifyMode == VERIFY_MODE_REMOTE &&
4248 clazz->classLoader == NULL))
4249 {
Andy McFaddend22748a2010-04-22 17:08:11 -07004250 /* advance to "verified" state */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004251 LOGV("+++ not verifying class %s (cl=%p)\n",
4252 clazz->descriptor, clazz->classLoader);
Andy McFaddend22748a2010-04-22 17:08:11 -07004253 clazz->status = CLASS_VERIFIED;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004254 goto noverify;
4255 }
4256
4257 if (!gDvm.optimizing)
4258 LOGV("+++ late verify on %s\n", clazz->descriptor);
4259
4260 /*
4261 * We're not supposed to optimize an unverified class, but during
4262 * development this mode was useful. We can't verify an optimized
4263 * class because the optimization process discards information.
4264 */
4265 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) {
4266 LOGW("Class '%s' was optimized without verification; "
4267 "not verifying now\n",
4268 clazz->descriptor);
4269 LOGW(" ('rm /data/dalvik-cache/*' and restart to fix this)");
4270 goto verify_failed;
4271 }
4272
4273 clazz->status = CLASS_VERIFYING;
Andy McFadden228a6b02010-05-04 15:02:32 -07004274 if (!dvmVerifyClass(clazz)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004275verify_failed:
4276 dvmThrowExceptionWithClassMessage("Ljava/lang/VerifyError;",
4277 clazz->descriptor);
4278 clazz->verifyErrorClass = dvmGetException(self)->clazz;
4279 clazz->status = CLASS_ERROR;
4280 goto bail_unlock;
4281 }
4282
4283 clazz->status = CLASS_VERIFIED;
4284 }
4285noverify:
4286
Andy McFaddend22748a2010-04-22 17:08:11 -07004287#ifdef WITH_DEBUGGER
4288 /* update instruction stream now that the verifier is done */
4289 dvmFlushBreakpoints(clazz);
4290#endif
4291
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004292 if (clazz->status == CLASS_INITIALIZED)
4293 goto bail_unlock;
4294
4295 while (clazz->status == CLASS_INITIALIZING) {
4296 /* we caught somebody else in the act; was it us? */
4297 if (clazz->initThreadId == self->threadId) {
4298 //LOGV("HEY: found a recursive <clinit>\n");
4299 goto bail_unlock;
4300 }
4301
4302 if (dvmCheckException(self)) {
4303 LOGW("GLITCH: exception pending at start of class init\n");
4304 dvmAbort();
4305 }
4306
4307 /*
4308 * Wait for the other thread to finish initialization. We pass
4309 * "false" for the "interruptShouldThrow" arg so it doesn't throw
4310 * an exception on interrupt.
4311 */
4312 dvmObjectWait(self, (Object*) clazz, 0, 0, false);
4313
4314 /*
4315 * When we wake up, repeat the test for init-in-progress. If there's
4316 * an exception pending (only possible if "interruptShouldThrow"
4317 * was set), bail out.
4318 */
4319 if (dvmCheckException(self)) {
4320 LOGI("Class init of '%s' failing with wait() exception\n",
4321 clazz->descriptor);
4322 /*
4323 * TODO: this is bogus, because it means the two threads have a
4324 * different idea of the class status. We need to flag the
4325 * class as bad and ensure that the initializer thread respects
4326 * our notice. If we get lucky and wake up after the class has
4327 * finished initialization but before being woken, we have to
4328 * swallow the exception, perhaps raising thread->interrupted
4329 * to preserve semantics.
4330 *
4331 * Since we're not currently allowing interrupts, this should
4332 * never happen and we don't need to fix this.
4333 */
4334 assert(false);
4335 throwClinitError();
4336 clazz->status = CLASS_ERROR;
4337 goto bail_unlock;
4338 }
4339 if (clazz->status == CLASS_INITIALIZING) {
4340 LOGI("Waiting again for class init\n");
4341 continue;
4342 }
4343 assert(clazz->status == CLASS_INITIALIZED ||
4344 clazz->status == CLASS_ERROR);
4345 if (clazz->status == CLASS_ERROR) {
4346 /*
4347 * The caller wants an exception, but it was thrown in a
4348 * different thread. Synthesize one here.
4349 */
4350 dvmThrowException("Ljava/lang/UnsatisfiedLinkError;",
4351 "(<clinit> failed, see exception in other thread)");
4352 }
4353 goto bail_unlock;
4354 }
4355
4356 /* see if we failed previously */
4357 if (clazz->status == CLASS_ERROR) {
4358 // might be wise to unlock before throwing; depends on which class
4359 // it is that we have locked
4360 dvmUnlockObject(self, (Object*) clazz);
4361 throwEarlierClassFailure(clazz);
4362 return false;
4363 }
4364
Andy McFaddenc95e0fb2010-04-29 14:13:01 -07004365#ifdef WITH_PROFILER
Andy McFaddene15a8eb2010-02-22 17:07:23 -08004366 u8 startWhen = 0;
4367 if (gDvm.allocProf.enabled) {
4368 startWhen = dvmGetRelativeTimeNsec();
4369 }
Andy McFaddenc95e0fb2010-04-29 14:13:01 -07004370#endif
Andy McFaddene15a8eb2010-02-22 17:07:23 -08004371
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004372 /*
4373 * We're ready to go, and have exclusive access to the class.
4374 *
4375 * Before we start initialization, we need to do one extra bit of
4376 * validation: make sure that the methods declared here match up
4377 * with our superclass and interfaces. We know that the UTF-8
4378 * descriptors match, but classes from different class loaders can
4379 * have the same name.
4380 *
4381 * We do this now, rather than at load/link time, for the same reason
4382 * that we defer verification.
4383 *
4384 * It's unfortunate that we need to do this at all, but we risk
4385 * mixing reference types with identical names (see Dalvik test 068).
4386 */
4387 if (!validateSuperDescriptors(clazz)) {
4388 assert(dvmCheckException(self));
4389 clazz->status = CLASS_ERROR;
4390 goto bail_unlock;
4391 }
4392
4393 /*
4394 * Let's initialize this thing.
4395 *
4396 * We unlock the object so that other threads can politely sleep on
4397 * our mutex with Object.wait(), instead of hanging or spinning trying
4398 * to grab our mutex.
4399 */
4400 assert(clazz->status < CLASS_INITIALIZING);
4401
4402#if LOG_CLASS_LOADING
4403 // We started initializing.
4404 logClassLoad('+', clazz);
4405 initializedByUs = true;
4406#endif
4407
4408 clazz->status = CLASS_INITIALIZING;
4409 clazz->initThreadId = self->threadId;
4410 dvmUnlockObject(self, (Object*) clazz);
4411
4412 /* init our superclass */
4413 if (clazz->super != NULL && clazz->super->status != CLASS_INITIALIZED) {
4414 assert(!dvmIsInterfaceClass(clazz));
4415 if (!dvmInitClass(clazz->super)) {
4416 assert(dvmCheckException(self));
4417 clazz->status = CLASS_ERROR;
4418 /* wake up anybody who started waiting while we were unlocked */
4419 dvmLockObject(self, (Object*) clazz);
4420 goto bail_notify;
4421 }
4422 }
4423
4424 /* Initialize any static fields whose values are
4425 * stored in the Dex file. This should include all of the
4426 * simple "final static" fields, which are required to
4427 * be initialized first. (vmspec 2 sec 2.17.5 item 8)
4428 * More-complicated final static fields should be set
4429 * at the beginning of <clinit>; all we can do is trust
4430 * that the compiler did the right thing.
4431 */
4432 initSFields(clazz);
4433
4434 /* Execute any static initialization code.
4435 */
4436 method = dvmFindDirectMethodByDescriptor(clazz, "<clinit>", "()V");
4437 if (method == NULL) {
4438 LOGVV("No <clinit> found for %s\n", clazz->descriptor);
4439 } else {
4440 LOGVV("Invoking %s.<clinit>\n", clazz->descriptor);
4441 JValue unused;
4442 dvmCallMethod(self, method, NULL, &unused);
4443 }
4444
4445 if (dvmCheckException(self)) {
4446 /*
4447 * We've had an exception thrown during static initialization. We
4448 * need to throw an ExceptionInInitializerError, but we want to
4449 * tuck the original exception into the "cause" field.
4450 */
4451 LOGW("Exception %s thrown during %s.<clinit>\n",
4452 (dvmGetException(self)->clazz)->descriptor, clazz->descriptor);
4453 throwClinitError();
4454 //LOGW("+++ replaced\n");
4455
4456 dvmLockObject(self, (Object*) clazz);
4457 clazz->status = CLASS_ERROR;
4458 } else {
4459 /* success! */
4460 dvmLockObject(self, (Object*) clazz);
4461 clazz->status = CLASS_INITIALIZED;
4462 LOGVV("Initialized class: %s\n", clazz->descriptor);
Andy McFaddene15a8eb2010-02-22 17:07:23 -08004463
Andy McFaddenc95e0fb2010-04-29 14:13:01 -07004464#ifdef WITH_PROFILER
Andy McFaddene15a8eb2010-02-22 17:07:23 -08004465 /*
4466 * Update alloc counters. TODO: guard with mutex.
4467 */
4468 if (gDvm.allocProf.enabled && startWhen != 0) {
4469 u8 initDuration = dvmGetRelativeTimeNsec() - startWhen;
4470 gDvm.allocProf.classInitTime += initDuration;
4471 self->allocProf.classInitTime += initDuration;
4472 gDvm.allocProf.classInitCount++;
4473 self->allocProf.classInitCount++;
4474 }
Andy McFaddenc95e0fb2010-04-29 14:13:01 -07004475#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004476 }
4477
4478bail_notify:
4479 /*
4480 * Notify anybody waiting on the object.
4481 */
4482 dvmObjectNotifyAll(self, (Object*) clazz);
4483
4484bail_unlock:
4485
4486#if LOG_CLASS_LOADING
4487 if (initializedByUs) {
4488 // We finished initializing.
4489 logClassLoad('-', clazz);
4490 }
4491#endif
4492
4493 dvmUnlockObject(self, (Object*) clazz);
4494
4495 return (clazz->status != CLASS_ERROR);
4496}
4497
4498/*
4499 * Replace method->nativeFunc and method->insns with new values. This is
4500 * performed on resolution of a native method.
4501 */
4502void dvmSetNativeFunc(const Method* method, DalvikBridgeFunc func,
4503 const u2* insns)
4504{
4505 ClassObject* clazz = method->clazz;
4506
4507 /* just open up both; easier that way */
4508 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4509 dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4510
4511 ((Method*)method)->nativeFunc = func;
4512 ((Method*)method)->insns = insns;
4513
4514 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4515 dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4516}
4517
4518/*
4519 * Add a RegisterMap to a Method. This is done when we verify the class
The Android Open Source Project99409882009-03-18 22:20:24 -07004520 * and compute the register maps at class initialization time (i.e. when
4521 * we don't have a pre-generated map). This means "pMap" is on the heap
4522 * and should be freed when the Method is discarded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004523 */
4524void dvmSetRegisterMap(Method* method, const RegisterMap* pMap)
4525{
4526 ClassObject* clazz = method->clazz;
4527
4528 if (method->registerMap != NULL) {
Andy McFaddend45a8872009-03-24 20:41:52 -07004529 /* unexpected during class loading, okay on first use (uncompress) */
Andy McFadden9faa9e62009-04-08 00:35:55 -07004530 LOGV("NOTE: registerMap already set for %s.%s\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004531 method->clazz->descriptor, method->name);
4532 /* keep going */
4533 }
The Android Open Source Project99409882009-03-18 22:20:24 -07004534 assert(!dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004535
4536 /* might be virtual or direct */
4537 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4538 dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4539
4540 method->registerMap = pMap;
4541
4542 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4543 dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4544}
4545
4546/*
4547 * dvmHashForeach callback. A nonzero return value causes foreach to
4548 * bail out.
4549 */
4550static int findClassCallback(void* vclazz, void* arg)
4551{
4552 ClassObject* clazz = vclazz;
4553 const char* descriptor = (const char*) arg;
4554
4555 if (strcmp(clazz->descriptor, descriptor) == 0)
4556 return (int) clazz;
4557 return 0;
4558}
4559
4560/*
4561 * Find a loaded class by descriptor. Returns the first one found.
4562 * Because there can be more than one if class loaders are involved,
4563 * this is not an especially good API. (Currently only used by the
4564 * debugger and "checking" JNI.)
4565 *
4566 * "descriptor" should have the form "Ljava/lang/Class;" or
4567 * "[Ljava/lang/Class;", i.e. a descriptor and not an internal-form
4568 * class name.
4569 */
4570ClassObject* dvmFindLoadedClass(const char* descriptor)
4571{
4572 int result;
4573
4574 dvmHashTableLock(gDvm.loadedClasses);
4575 result = dvmHashForeach(gDvm.loadedClasses, findClassCallback,
4576 (void*) descriptor);
4577 dvmHashTableUnlock(gDvm.loadedClasses);
4578
4579 return (ClassObject*) result;
4580}
4581
4582/*
4583 * Retrieve the system (a/k/a application) class loader.
4584 */
4585Object* dvmGetSystemClassLoader(void)
4586{
4587 ClassObject* clazz;
4588 Method* getSysMeth;
4589 Object* loader;
4590
4591 clazz = dvmFindSystemClass("Ljava/lang/ClassLoader;");
4592 if (clazz == NULL)
4593 return NULL;
4594
4595 getSysMeth = dvmFindDirectMethodByDescriptor(clazz, "getSystemClassLoader",
4596 "()Ljava/lang/ClassLoader;");
4597 if (getSysMeth == NULL)
4598 return NULL;
4599
4600 JValue result;
4601 dvmCallMethod(dvmThreadSelf(), getSysMeth, NULL, &result);
4602 loader = (Object*)result.l;
4603 return loader;
4604}
4605
4606
4607/*
4608 * This is a dvmHashForeach callback.
4609 */
4610static int dumpClass(void* vclazz, void* varg)
4611{
4612 const ClassObject* clazz = (const ClassObject*) vclazz;
4613 const ClassObject* super;
4614 int flags = (int) varg;
4615 char* desc;
4616 int i;
4617
4618 if (clazz == NULL) {
4619 LOGI("dumpClass: ignoring request to dump null class\n");
4620 return 0;
4621 }
4622
4623 if ((flags & kDumpClassFullDetail) == 0) {
4624 bool showInit = (flags & kDumpClassInitialized) != 0;
4625 bool showLoader = (flags & kDumpClassClassLoader) != 0;
4626 const char* initStr;
4627
4628 initStr = dvmIsClassInitialized(clazz) ? "true" : "false";
4629
4630 if (showInit && showLoader)
4631 LOGI("%s %p %s\n", clazz->descriptor, clazz->classLoader, initStr);
4632 else if (showInit)
4633 LOGI("%s %s\n", clazz->descriptor, initStr);
4634 else if (showLoader)
4635 LOGI("%s %p\n", clazz->descriptor, clazz->classLoader);
4636 else
4637 LOGI("%s\n", clazz->descriptor);
4638
4639 return 0;
4640 }
4641
4642 /* clazz->super briefly holds the superclass index during class prep */
4643 if ((u4)clazz->super > 0x10000 && (u4) clazz->super != (u4)-1)
4644 super = clazz->super;
4645 else
4646 super = NULL;
4647
4648 LOGI("----- %s '%s' cl=%p ser=0x%08x -----\n",
4649 dvmIsInterfaceClass(clazz) ? "interface" : "class",
4650 clazz->descriptor, clazz->classLoader, clazz->serialNumber);
4651 LOGI(" objectSize=%d (%d from super)\n", (int) clazz->objectSize,
4652 super != NULL ? (int) super->objectSize : -1);
4653 LOGI(" access=0x%04x.%04x\n", clazz->accessFlags >> 16,
4654 clazz->accessFlags & JAVA_FLAGS_MASK);
4655 if (super != NULL)
4656 LOGI(" super='%s' (cl=%p)\n", super->descriptor, super->classLoader);
4657 if (dvmIsArrayClass(clazz)) {
4658 LOGI(" dimensions=%d elementClass=%s\n",
4659 clazz->arrayDim, clazz->elementClass->descriptor);
4660 }
4661 if (clazz->iftableCount > 0) {
4662 LOGI(" interfaces (%d):\n", clazz->iftableCount);
4663 for (i = 0; i < clazz->iftableCount; i++) {
4664 InterfaceEntry* ent = &clazz->iftable[i];
4665 int j;
4666
4667 LOGI(" %2d: %s (cl=%p)\n",
4668 i, ent->clazz->descriptor, ent->clazz->classLoader);
4669
4670 /* enable when needed */
4671 if (false && ent->methodIndexArray != NULL) {
4672 for (j = 0; j < ent->clazz->virtualMethodCount; j++)
4673 LOGI(" %2d: %d %s %s\n",
4674 j, ent->methodIndexArray[j],
4675 ent->clazz->virtualMethods[j].name,
4676 clazz->vtable[ent->methodIndexArray[j]]->name);
4677 }
4678 }
4679 }
4680 if (!dvmIsInterfaceClass(clazz)) {
4681 LOGI(" vtable (%d entries, %d in super):\n", clazz->vtableCount,
4682 super != NULL ? super->vtableCount : 0);
4683 for (i = 0; i < clazz->vtableCount; i++) {
4684 desc = dexProtoCopyMethodDescriptor(&clazz->vtable[i]->prototype);
4685 LOGI(" %s%2d: %p %20s %s\n",
4686 (i != clazz->vtable[i]->methodIndex) ? "*** " : "",
4687 (u4) clazz->vtable[i]->methodIndex, clazz->vtable[i],
4688 clazz->vtable[i]->name, desc);
4689 free(desc);
4690 }
4691 LOGI(" direct methods (%d entries):\n", clazz->directMethodCount);
4692 for (i = 0; i < clazz->directMethodCount; i++) {
4693 desc = dexProtoCopyMethodDescriptor(
4694 &clazz->directMethods[i].prototype);
4695 LOGI(" %2d: %20s %s\n", i, clazz->directMethods[i].name,
4696 desc);
4697 free(desc);
4698 }
4699 } else {
4700 LOGI(" interface methods (%d):\n", clazz->virtualMethodCount);
4701 for (i = 0; i < clazz->virtualMethodCount; i++) {
4702 desc = dexProtoCopyMethodDescriptor(
4703 &clazz->virtualMethods[i].prototype);
4704 LOGI(" %2d: %2d %20s %s\n", i,
4705 (u4) clazz->virtualMethods[i].methodIndex,
4706 clazz->virtualMethods[i].name,
4707 desc);
4708 free(desc);
4709 }
4710 }
4711 if (clazz->sfieldCount > 0) {
4712 LOGI(" static fields (%d entries):\n", clazz->sfieldCount);
4713 for (i = 0; i < clazz->sfieldCount; i++) {
4714 LOGI(" %2d: %20s %s\n", i, clazz->sfields[i].field.name,
4715 clazz->sfields[i].field.signature);
4716 }
4717 }
4718 if (clazz->ifieldCount > 0) {
4719 LOGI(" instance fields (%d entries):\n", clazz->ifieldCount);
4720 for (i = 0; i < clazz->ifieldCount; i++) {
4721 LOGI(" %2d: %20s %s\n", i, clazz->ifields[i].field.name,
4722 clazz->ifields[i].field.signature);
4723 }
4724 }
4725 return 0;
4726}
4727
4728/*
4729 * Dump the contents of a single class.
4730 *
4731 * Pass kDumpClassFullDetail into "flags" to get lots of detail.
4732 */
4733void dvmDumpClass(const ClassObject* clazz, int flags)
4734{
4735 dumpClass((void*) clazz, (void*) flags);
4736}
4737
4738/*
4739 * Dump the contents of all classes.
4740 */
4741void dvmDumpAllClasses(int flags)
4742{
4743 dvmHashTableLock(gDvm.loadedClasses);
4744 dvmHashForeach(gDvm.loadedClasses, dumpClass, (void*) flags);
4745 dvmHashTableUnlock(gDvm.loadedClasses);
4746}
4747
4748/*
4749 * Get the number of loaded classes
4750 */
4751int dvmGetNumLoadedClasses()
4752{
4753 int count;
4754 dvmHashTableLock(gDvm.loadedClasses);
4755 count = dvmHashTableNumEntries(gDvm.loadedClasses);
4756 dvmHashTableUnlock(gDvm.loadedClasses);
4757 return count;
4758}
4759
4760/*
4761 * Write some statistics to the log file.
4762 */
4763void dvmDumpLoaderStats(const char* msg)
4764{
4765 LOGV("VM stats (%s): cls=%d/%d meth=%d ifld=%d sfld=%d linear=%d\n",
4766 msg, gDvm.numLoadedClasses, dvmHashTableNumEntries(gDvm.loadedClasses),
4767 gDvm.numDeclaredMethods, gDvm.numDeclaredInstFields,
4768 gDvm.numDeclaredStaticFields, gDvm.pBootLoaderAlloc->curOffset);
4769#ifdef COUNT_PRECISE_METHODS
4770 LOGI("GC precise methods: %d\n",
4771 dvmPointerSetGetCount(gDvm.preciseMethods));
4772#endif
4773}
4774
4775#ifdef PROFILE_FIELD_ACCESS
4776/*
4777 * Dump the field access counts for all fields in this method.
4778 */
4779static int dumpAccessCounts(void* vclazz, void* varg)
4780{
4781 const ClassObject* clazz = (const ClassObject*) vclazz;
4782 int i;
4783
4784 for (i = 0; i < clazz->ifieldCount; i++) {
4785 Field* field = &clazz->ifields[i].field;
4786
4787 if (field->gets != 0)
4788 printf("GI %d %s.%s\n", field->gets,
4789 field->clazz->descriptor, field->name);
4790 if (field->puts != 0)
4791 printf("PI %d %s.%s\n", field->puts,
4792 field->clazz->descriptor, field->name);
4793 }
4794 for (i = 0; i < clazz->sfieldCount; i++) {
4795 Field* field = &clazz->sfields[i].field;
4796
4797 if (field->gets != 0)
4798 printf("GS %d %s.%s\n", field->gets,
4799 field->clazz->descriptor, field->name);
4800 if (field->puts != 0)
4801 printf("PS %d %s.%s\n", field->puts,
4802 field->clazz->descriptor, field->name);
4803 }
4804
4805 return 0;
4806}
4807
4808/*
4809 * Dump the field access counts for all loaded classes.
4810 */
4811void dvmDumpFieldAccessCounts(void)
4812{
4813 dvmHashTableLock(gDvm.loadedClasses);
4814 dvmHashForeach(gDvm.loadedClasses, dumpAccessCounts, NULL);
4815 dvmHashTableUnlock(gDvm.loadedClasses);
4816}
4817#endif
4818
4819
4820/*
4821 * Mark all classes associated with the built-in loader.
4822 */
4823static int markClassObject(void *clazz, void *arg)
4824{
4825 UNUSED_PARAMETER(arg);
4826
4827 dvmMarkObjectNonNull((Object *)clazz);
4828 return 0;
4829}
4830
4831/*
4832 * The garbage collector calls this to mark the class objects for all
4833 * loaded classes.
4834 */
4835void dvmGcScanRootClassLoader()
4836{
4837 /* dvmClassStartup() may not have been called before the first GC.
4838 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004839 if (gDvm.loadedClasses != NULL) {
4840 dvmHashTableLock(gDvm.loadedClasses);
4841 dvmHashForeach(gDvm.loadedClasses, markClassObject, NULL);
4842 dvmHashTableUnlock(gDvm.loadedClasses);
4843 }
4844}
4845
4846
4847/*
4848 * ===========================================================================
4849 * Method Prototypes and Descriptors
4850 * ===========================================================================
4851 */
4852
4853/*
4854 * Compare the two method names and prototypes, a la strcmp(). The
4855 * name is considered the "major" order and the prototype the "minor"
4856 * order. The prototypes are compared as if by dvmCompareMethodProtos().
4857 */
4858int dvmCompareMethodNamesAndProtos(const Method* method1,
4859 const Method* method2)
4860{
4861 int result = strcmp(method1->name, method2->name);
4862
4863 if (result != 0) {
4864 return result;
4865 }
4866
4867 return dvmCompareMethodProtos(method1, method2);
4868}
4869
4870/*
4871 * Compare the two method names and prototypes, a la strcmp(), ignoring
4872 * the return value. The name is considered the "major" order and the
4873 * prototype the "minor" order. The prototypes are compared as if by
4874 * dvmCompareMethodArgProtos().
4875 */
4876int dvmCompareMethodNamesAndParameterProtos(const Method* method1,
4877 const Method* method2)
4878{
4879 int result = strcmp(method1->name, method2->name);
4880
4881 if (result != 0) {
4882 return result;
4883 }
4884
4885 return dvmCompareMethodParameterProtos(method1, method2);
4886}
4887
4888/*
4889 * Compare a (name, prototype) pair with the (name, prototype) of
4890 * a method, a la strcmp(). The name is considered the "major" order and
4891 * the prototype the "minor" order. The descriptor and prototype are
4892 * compared as if by dvmCompareDescriptorAndMethodProto().
4893 */
4894int dvmCompareNameProtoAndMethod(const char* name,
4895 const DexProto* proto, const Method* method)
4896{
4897 int result = strcmp(name, method->name);
4898
4899 if (result != 0) {
4900 return result;
4901 }
4902
4903 return dexProtoCompare(proto, &method->prototype);
4904}
4905
4906/*
4907 * Compare a (name, method descriptor) pair with the (name, prototype) of
4908 * a method, a la strcmp(). The name is considered the "major" order and
4909 * the prototype the "minor" order. The descriptor and prototype are
4910 * compared as if by dvmCompareDescriptorAndMethodProto().
4911 */
4912int dvmCompareNameDescriptorAndMethod(const char* name,
4913 const char* descriptor, const Method* method)
4914{
4915 int result = strcmp(name, method->name);
4916
4917 if (result != 0) {
4918 return result;
4919 }
4920
4921 return dvmCompareDescriptorAndMethodProto(descriptor, method);
4922}