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