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