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