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