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