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