blob: bbb8a3523548a3e8b58a33e9980c8a34e3a48ac9 [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);
2190 int returnType, padFlags, jniArgInfo;
2191 char sigByte;
2192 int stackOffset, padMask;
2193 u4 hints;
2194
2195 /* The first shorty character is the return type. */
2196 switch (*(sig++)) {
2197 case 'V':
2198 returnType = DALVIK_JNI_RETURN_VOID;
2199 break;
2200 case 'F':
2201 returnType = DALVIK_JNI_RETURN_FLOAT;
2202 break;
2203 case 'D':
2204 returnType = DALVIK_JNI_RETURN_DOUBLE;
2205 break;
2206 case 'J':
2207 returnType = DALVIK_JNI_RETURN_S8;
2208 break;
Bill Buzbeee2557512009-07-27 15:51:54 -07002209 case 'Z':
2210 case 'B':
2211 returnType = DALVIK_JNI_RETURN_S1;
2212 break;
2213 case 'C':
2214 returnType = DALVIK_JNI_RETURN_U2;
2215 break;
2216 case 'S':
2217 returnType = DALVIK_JNI_RETURN_S2;
2218 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002219 default:
2220 returnType = DALVIK_JNI_RETURN_S4;
2221 break;
2222 }
2223
2224 jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT;
2225
2226 hints = dvmPlatformInvokeHints(proto);
2227
2228 if (hints & DALVIK_JNI_NO_ARG_INFO) {
2229 jniArgInfo |= DALVIK_JNI_NO_ARG_INFO;
2230 } else {
2231 assert((hints & DALVIK_JNI_RETURN_MASK) == 0);
2232 jniArgInfo |= hints;
2233 }
2234
2235 return jniArgInfo;
2236}
2237
2238/*
2239 * Load information about a static field.
2240 *
2241 * This also "prepares" static fields by initializing them
2242 * to their "standard default values".
2243 */
2244static void loadSFieldFromDex(ClassObject* clazz,
2245 const DexField* pDexSField, StaticField* sfield)
2246{
2247 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2248 const DexFieldId* pFieldId;
2249
2250 pFieldId = dexGetFieldId(pDexFile, pDexSField->fieldIdx);
2251
2252 sfield->field.clazz = clazz;
2253 sfield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2254 sfield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2255 sfield->field.accessFlags = pDexSField->accessFlags;
2256
2257 /* Static object field values are set to "standard default values"
2258 * (null or 0) until the class is initialized. We delay loading
2259 * constant values from the class until that time.
2260 */
2261 //sfield->value.j = 0;
2262 assert(sfield->value.j == 0LL); // cleared earlier with calloc
2263
2264#ifdef PROFILE_FIELD_ACCESS
2265 sfield->field.gets = sfield->field.puts = 0;
2266#endif
2267}
2268
2269/*
2270 * Load information about an instance field.
2271 */
2272static void loadIFieldFromDex(ClassObject* clazz,
2273 const DexField* pDexIField, InstField* ifield)
2274{
2275 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2276 const DexFieldId* pFieldId;
2277
2278 pFieldId = dexGetFieldId(pDexFile, pDexIField->fieldIdx);
2279
2280 ifield->field.clazz = clazz;
2281 ifield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2282 ifield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2283 ifield->field.accessFlags = pDexIField->accessFlags;
2284#ifndef NDEBUG
2285 assert(ifield->byteOffset == 0); // cleared earlier with calloc
2286 ifield->byteOffset = -1; // make it obvious if we fail to set later
2287#endif
2288
2289#ifdef PROFILE_FIELD_ACCESS
2290 ifield->field.gets = ifield->field.puts = 0;
2291#endif
2292}
2293
2294/*
2295 * Cache java.lang.ref.Reference fields and methods.
2296 */
Barry Hayes6daaac12009-07-08 10:01:56 -07002297static bool precacheReferenceOffsets(ClassObject* clazz)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002298{
2299 Method *meth;
2300 int i;
2301
2302 /* We trick the GC object scanner by not counting
2303 * java.lang.ref.Reference.referent as an object
2304 * field. It will get explicitly scanned as part
2305 * of the reference-walking process.
2306 *
2307 * Find the object field named "referent" and put it
2308 * just after the list of object reference fields.
2309 */
2310 dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
2311 for (i = 0; i < clazz->ifieldRefCount; i++) {
2312 InstField *pField = &clazz->ifields[i];
2313 if (strcmp(pField->field.name, "referent") == 0) {
2314 int targetIndex;
2315
2316 /* Swap this field with the last object field.
2317 */
2318 targetIndex = clazz->ifieldRefCount - 1;
2319 if (i != targetIndex) {
2320 InstField *swapField = &clazz->ifields[targetIndex];
2321 InstField tmpField;
2322 int tmpByteOffset;
2323
2324 /* It's not currently strictly necessary
2325 * for the fields to be in byteOffset order,
2326 * but it's more predictable that way.
2327 */
2328 tmpByteOffset = swapField->byteOffset;
2329 swapField->byteOffset = pField->byteOffset;
2330 pField->byteOffset = tmpByteOffset;
2331
2332 tmpField = *swapField;
2333 *swapField = *pField;
2334 *pField = tmpField;
2335 }
2336
2337 /* One fewer object field (wink wink).
2338 */
2339 clazz->ifieldRefCount--;
2340 i--; /* don't trip "didn't find it" test if field was last */
2341 break;
2342 }
2343 }
2344 dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
2345 if (i == clazz->ifieldRefCount) {
2346 LOGE("Unable to reorder 'referent' in %s\n", clazz->descriptor);
2347 return false;
2348 }
2349
2350 /* Cache pretty much everything about Reference so that
2351 * we don't need to call interpreted code when clearing/enqueueing
2352 * references. This is fragile, so we'll be paranoid.
2353 */
2354 gDvm.classJavaLangRefReference = clazz;
2355
2356 gDvm.offJavaLangRefReference_referent =
2357 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2358 "referent", "Ljava/lang/Object;");
2359 assert(gDvm.offJavaLangRefReference_referent >= 0);
2360
2361 gDvm.offJavaLangRefReference_queue =
2362 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2363 "queue", "Ljava/lang/ref/ReferenceQueue;");
2364 assert(gDvm.offJavaLangRefReference_queue >= 0);
2365
2366 gDvm.offJavaLangRefReference_queueNext =
2367 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2368 "queueNext", "Ljava/lang/ref/Reference;");
2369 assert(gDvm.offJavaLangRefReference_queueNext >= 0);
2370
2371 gDvm.offJavaLangRefReference_vmData =
2372 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2373 "vmData", "I");
2374 assert(gDvm.offJavaLangRefReference_vmData >= 0);
2375
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002376 /* enqueueInternal() is private and thus a direct method. */
2377 meth = dvmFindDirectMethodByDescriptor(clazz, "enqueueInternal", "()Z");
2378 assert(meth != NULL);
2379 gDvm.methJavaLangRefReference_enqueueInternal = meth;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002380
2381 return true;
2382}
2383
2384
2385/*
Barry Hayes6daaac12009-07-08 10:01:56 -07002386 * Set the bitmap of reference offsets, refOffsets, from the ifields
2387 * list.
2388 */
2389static void computeRefOffsets(ClassObject* clazz)
2390{
2391 if (clazz->super != NULL) {
2392 clazz->refOffsets = clazz->super->refOffsets;
2393 } else {
2394 clazz->refOffsets = 0;
2395 }
2396 /*
2397 * If our superclass overflowed, we don't stand a chance.
2398 */
2399 if (clazz->refOffsets != CLASS_WALK_SUPER) {
2400 InstField *f;
2401 int i;
2402
2403 /* All of the fields that contain object references
2404 * are guaranteed to be at the beginning of the ifields list.
2405 */
2406 f = clazz->ifields;
2407 const int ifieldRefCount = clazz->ifieldRefCount;
2408 for (i = 0; i < ifieldRefCount; i++) {
2409 /*
2410 * Note that, per the comment on struct InstField,
2411 * f->byteOffset is the offset from the beginning of
2412 * obj, not the offset into obj->instanceData.
2413 */
Andy McFadden2fbe6d12009-09-04 15:38:13 -07002414 assert(f->byteOffset >= (int) CLASS_SMALLEST_OFFSET);
Barry Hayes6daaac12009-07-08 10:01:56 -07002415 assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
2416 if (CLASS_CAN_ENCODE_OFFSET(f->byteOffset)) {
2417 u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
2418 assert(newBit != 0);
2419 clazz->refOffsets |= newBit;
2420 } else {
2421 clazz->refOffsets = CLASS_WALK_SUPER;
2422 break;
2423 }
2424 f++;
2425 }
2426 }
2427}
2428
2429
2430/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002431 * Link (prepare and resolve). Verification is deferred until later.
2432 *
2433 * This converts symbolic references into pointers. It's independent of
2434 * the source file format.
2435 *
2436 * If "classesResolved" is false, we assume that superclassIdx and
2437 * interfaces[] are holding class reference indices rather than pointers.
2438 * The class references will be resolved during link. (This is done when
2439 * loading from DEX to avoid having to create additional storage to pass
2440 * the indices around.)
2441 *
2442 * Returns "false" with an exception pending on failure.
2443 */
2444bool dvmLinkClass(ClassObject* clazz, bool classesResolved)
2445{
2446 u4 superclassIdx = 0;
2447 bool okay = false;
2448 bool resolve_okay;
2449 int numInterfacesResolved = 0;
2450 int i;
2451
2452 if (gDvm.verboseClass)
2453 LOGV("CLASS: linking '%s'...\n", clazz->descriptor);
2454
2455 /* "Resolve" the class.
2456 *
2457 * At this point, clazz's reference fields contain Dex
2458 * file indices instead of direct object references.
2459 * We need to translate those indices into real references,
2460 * while making sure that the GC doesn't sweep any of
2461 * the referenced objects.
2462 *
2463 * The GC will avoid scanning this object as long as
2464 * clazz->obj.clazz is gDvm.unlinkedJavaLangClass.
2465 * Once clazz is ready, we'll replace clazz->obj.clazz
2466 * with gDvm.classJavaLangClass to let the GC know
2467 * to look at it.
2468 */
2469 assert(clazz->obj.clazz == gDvm.unlinkedJavaLangClass);
2470
2471 /* It's important that we take care of java.lang.Class
2472 * first. If we were to do this after looking up the
2473 * superclass (below), Class wouldn't be ready when
2474 * java.lang.Object needed it.
2475 *
2476 * Note that we don't set clazz->obj.clazz yet.
2477 */
2478 if (gDvm.classJavaLangClass == NULL) {
2479 if (clazz->classLoader == NULL &&
2480 strcmp(clazz->descriptor, "Ljava/lang/Class;") == 0)
2481 {
2482 gDvm.classJavaLangClass = clazz;
2483 } else {
2484 gDvm.classJavaLangClass =
2485 dvmFindSystemClassNoInit("Ljava/lang/Class;");
2486 if (gDvm.classJavaLangClass == NULL) {
2487 /* should have thrown one */
2488 assert(dvmCheckException(dvmThreadSelf()));
2489 goto bail;
2490 }
2491 }
2492 }
2493 assert(gDvm.classJavaLangClass != NULL);
2494
2495 /*
2496 * Resolve all Dex indices so we can hand the ClassObject
2497 * over to the GC. If we fail at any point, we need to remove
2498 * any tracked references to avoid leaking memory.
2499 */
2500
2501 /*
2502 * All classes have a direct superclass, except for java/lang/Object.
2503 */
2504 if (!classesResolved) {
2505 superclassIdx = (u4) clazz->super; /* unpack temp store */
2506 clazz->super = NULL;
2507 }
2508 if (strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0) {
2509 assert(!classesResolved);
2510 if (superclassIdx != kDexNoIndex) {
2511 /* TODO: is this invariant true for all java/lang/Objects,
2512 * regardless of the class loader? For now, assume it is.
2513 */
2514 dvmThrowException("Ljava/lang/ClassFormatError;",
2515 "java.lang.Object has a superclass");
2516 goto bail;
2517 }
2518
2519 /* Don't finalize objects whose classes use the
2520 * default (empty) Object.finalize().
2521 */
2522 CLEAR_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2523 } else {
2524 if (!classesResolved) {
2525 if (superclassIdx == kDexNoIndex) {
2526 dvmThrowException("Ljava/lang/LinkageError;",
2527 "no superclass defined");
2528 goto bail;
2529 }
2530 clazz->super = dvmResolveClass(clazz, superclassIdx, false);
2531 if (clazz->super == NULL) {
2532 assert(dvmCheckException(dvmThreadSelf()));
2533 if (gDvm.optimizing) {
2534 /* happens with "external" libs */
2535 LOGV("Unable to resolve superclass of %s (%d)\n",
2536 clazz->descriptor, superclassIdx);
2537 } else {
2538 LOGW("Unable to resolve superclass of %s (%d)\n",
2539 clazz->descriptor, superclassIdx);
2540 }
2541 goto bail;
2542 }
2543 }
2544 /* verify */
2545 if (dvmIsFinalClass(clazz->super)) {
2546 LOGW("Superclass of '%s' is final '%s'\n",
2547 clazz->descriptor, clazz->super->descriptor);
2548 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2549 "superclass is final");
2550 goto bail;
2551 } else if (dvmIsInterfaceClass(clazz->super)) {
2552 LOGW("Superclass of '%s' is interface '%s'\n",
2553 clazz->descriptor, clazz->super->descriptor);
2554 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2555 "superclass is an interface");
2556 goto bail;
2557 } else if (!dvmCheckClassAccess(clazz, clazz->super)) {
2558 LOGW("Superclass of '%s' (%s) is not accessible\n",
2559 clazz->descriptor, clazz->super->descriptor);
2560 dvmThrowException("Ljava/lang/IllegalAccessError;",
2561 "superclass not accessible");
2562 goto bail;
2563 }
2564
2565 /* Don't let the GC reclaim the superclass.
2566 * TODO: shouldn't be needed; remove when things stabilize
2567 */
2568 dvmAddTrackedAlloc((Object *)clazz->super, NULL);
2569
2570 /* Inherit finalizability from the superclass. If this
2571 * class also overrides finalize(), its CLASS_ISFINALIZABLE
2572 * bit will already be set.
2573 */
2574 if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISFINALIZABLE)) {
2575 SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2576 }
2577
2578 /* See if this class descends from java.lang.Reference
2579 * and set the class flags appropriately.
2580 */
2581 if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISREFERENCE)) {
2582 u4 superRefFlags;
2583
2584 /* We've already determined the reference type of this
2585 * inheritance chain. Inherit reference-ness from the superclass.
2586 */
2587 superRefFlags = GET_CLASS_FLAG_GROUP(clazz->super,
2588 CLASS_ISREFERENCE |
2589 CLASS_ISWEAKREFERENCE |
2590 CLASS_ISPHANTOMREFERENCE);
2591 SET_CLASS_FLAG(clazz, superRefFlags);
2592 } else if (clazz->classLoader == NULL &&
2593 clazz->super->classLoader == NULL &&
2594 strcmp(clazz->super->descriptor,
2595 "Ljava/lang/ref/Reference;") == 0)
2596 {
2597 u4 refFlags;
2598
2599 /* This class extends Reference, which means it should
2600 * be one of the magic Soft/Weak/PhantomReference classes.
2601 */
2602 refFlags = CLASS_ISREFERENCE;
2603 if (strcmp(clazz->descriptor,
2604 "Ljava/lang/ref/SoftReference;") == 0)
2605 {
2606 /* Only CLASS_ISREFERENCE is set for soft references.
2607 */
2608 } else if (strcmp(clazz->descriptor,
2609 "Ljava/lang/ref/WeakReference;") == 0)
2610 {
2611 refFlags |= CLASS_ISWEAKREFERENCE;
2612 } else if (strcmp(clazz->descriptor,
2613 "Ljava/lang/ref/PhantomReference;") == 0)
2614 {
2615 refFlags |= CLASS_ISPHANTOMREFERENCE;
2616 } else {
2617 /* No-one else is allowed to inherit directly
2618 * from Reference.
2619 */
2620//xxx is this the right exception? better than an assertion.
2621 dvmThrowException("Ljava/lang/LinkageError;",
2622 "illegal inheritance from Reference");
2623 goto bail;
2624 }
2625
2626 /* The class should not have any reference bits set yet.
2627 */
2628 assert(GET_CLASS_FLAG_GROUP(clazz,
2629 CLASS_ISREFERENCE |
2630 CLASS_ISWEAKREFERENCE |
2631 CLASS_ISPHANTOMREFERENCE) == 0);
2632
2633 SET_CLASS_FLAG(clazz, refFlags);
2634 }
2635 }
2636
2637 if (!classesResolved && clazz->interfaceCount > 0) {
2638 /*
2639 * Resolve the interfaces implemented directly by this class. We
2640 * stuffed the class index into the interface pointer slot.
2641 */
2642 dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
2643 for (i = 0; i < clazz->interfaceCount; i++) {
2644 u4 interfaceIdx;
2645
2646 interfaceIdx = (u4) clazz->interfaces[i]; /* unpack temp store */
2647 assert(interfaceIdx != kDexNoIndex);
2648
2649 clazz->interfaces[i] = dvmResolveClass(clazz, interfaceIdx, false);
2650 if (clazz->interfaces[i] == NULL) {
2651 const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2652
2653 assert(dvmCheckException(dvmThreadSelf()));
2654 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2655
2656 const char* classDescriptor;
2657 classDescriptor = dexStringByTypeIdx(pDexFile, interfaceIdx);
2658 if (gDvm.optimizing) {
2659 /* happens with "external" libs */
2660 LOGV("Failed resolving %s interface %d '%s'\n",
2661 clazz->descriptor, interfaceIdx, classDescriptor);
2662 } else {
2663 LOGI("Failed resolving %s interface %d '%s'\n",
2664 clazz->descriptor, interfaceIdx, classDescriptor);
2665 }
2666 goto bail_during_resolve;
2667 }
2668
2669 /* are we allowed to implement this interface? */
2670 if (!dvmCheckClassAccess(clazz, clazz->interfaces[i])) {
2671 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2672 LOGW("Interface '%s' is not accessible to '%s'\n",
2673 clazz->interfaces[i]->descriptor, clazz->descriptor);
2674 dvmThrowException("Ljava/lang/IllegalAccessError;",
2675 "interface not accessible");
2676 goto bail_during_resolve;
2677 }
2678
2679 /* Don't let the GC reclaim the interface class.
2680 * TODO: shouldn't be needed; remove when things stabilize
2681 */
2682 dvmAddTrackedAlloc((Object *)clazz->interfaces[i], NULL);
2683 numInterfacesResolved++;
2684
2685 LOGVV("+++ found interface '%s'\n",
2686 clazz->interfaces[i]->descriptor);
2687 }
2688 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2689 }
2690
2691 /*
2692 * The ClassObject is now in a GC-able state. We let the GC
2693 * realize this by punching in the real class type, which is
2694 * always java.lang.Class.
2695 *
2696 * After this line, clazz will be fair game for the GC.
2697 * Every field that the GC will look at must now be valid:
2698 * - clazz->super
2699 * - class->classLoader
2700 * - clazz->sfields
2701 * - clazz->interfaces
2702 */
2703 clazz->obj.clazz = gDvm.classJavaLangClass;
2704
2705 if (false) {
2706bail_during_resolve:
2707 resolve_okay = false;
2708 } else {
2709 resolve_okay = true;
2710 }
2711
2712 /*
2713 * Now that the GC can scan the ClassObject, we can let
2714 * go of the explicit references we were holding onto.
2715 *
2716 * Either that or we failed, in which case we need to
2717 * release the references so we don't leak memory.
2718 */
2719 if (clazz->super != NULL) {
2720 dvmReleaseTrackedAlloc((Object *)clazz->super, NULL);
2721 }
2722 for (i = 0; i < numInterfacesResolved; i++) {
2723 dvmReleaseTrackedAlloc((Object *)clazz->interfaces[i], NULL);
2724 }
2725
2726 if (!resolve_okay) {
2727 //LOGW("resolve_okay is false\n");
2728 goto bail;
2729 }
2730
2731 /*
2732 * Populate vtable.
2733 */
2734 if (dvmIsInterfaceClass(clazz)) {
2735 /* no vtable; just set the method indices */
2736 int count = clazz->virtualMethodCount;
2737
2738 if (count != (u2) count) {
2739 LOGE("Too many methods (%d) in interface '%s'\n", count,
2740 clazz->descriptor);
2741 goto bail;
2742 }
2743
2744 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2745
2746 for (i = 0; i < count; i++)
2747 clazz->virtualMethods[i].methodIndex = (u2) i;
2748
2749 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2750 } else {
2751 if (!createVtable(clazz)) {
2752 LOGW("failed creating vtable\n");
2753 goto bail;
2754 }
2755 }
2756
2757 /*
2758 * Populate interface method tables. Can alter the vtable.
2759 */
2760 if (!createIftable(clazz))
2761 goto bail;
2762
2763 /*
2764 * Insert special-purpose "stub" method implementations.
2765 */
2766 if (!insertMethodStubs(clazz))
2767 goto bail;
2768
2769 /*
2770 * Compute instance field offsets and, hence, the size of the object.
2771 */
2772 if (!computeFieldOffsets(clazz))
2773 goto bail;
2774
2775 /*
2776 * Cache fields and methods from java/lang/ref/Reference and
2777 * java/lang/Class. This has to happen after computeFieldOffsets().
2778 */
2779 if (clazz->classLoader == NULL) {
2780 if (strcmp(clazz->descriptor, "Ljava/lang/ref/Reference;") == 0) {
2781 if (!precacheReferenceOffsets(clazz)) {
2782 LOGE("failed pre-caching Reference offsets\n");
2783 dvmThrowException("Ljava/lang/InternalError;", NULL);
2784 goto bail;
2785 }
2786 } else if (clazz == gDvm.classJavaLangClass) {
2787 gDvm.offJavaLangClass_pd = dvmFindFieldOffset(clazz, "pd",
2788 "Ljava/security/ProtectionDomain;");
2789 if (gDvm.offJavaLangClass_pd <= 0) {
2790 LOGE("ERROR: unable to find 'pd' field in Class\n");
2791 dvmAbort(); /* we're not going to get much farther */
2792 //goto bail;
2793 }
2794 }
2795 }
2796
2797 /*
Barry Hayes6daaac12009-07-08 10:01:56 -07002798 * Compact the offsets the GC has to examine into a bitmap, if
2799 * possible. (This has to happen after Reference.referent is
2800 * massaged in precacheReferenceOffsets.)
2801 */
2802 computeRefOffsets(clazz);
2803
2804 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002805 * Done!
2806 */
2807 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED))
2808 clazz->status = CLASS_VERIFIED;
2809 else
2810 clazz->status = CLASS_RESOLVED;
2811 okay = true;
2812 if (gDvm.verboseClass)
2813 LOGV("CLASS: linked '%s'\n", clazz->descriptor);
2814
2815 /*
2816 * We send CLASS_PREPARE events to the debugger from here. The
2817 * definition of "preparation" is creating the static fields for a
2818 * class and initializing them to the standard default values, but not
2819 * executing any code (that comes later, during "initialization").
2820 *
2821 * We did the static prep in loadSFieldFromDex() while loading the class.
2822 *
2823 * The class has been prepared and resolved but possibly not yet verified
2824 * at this point.
2825 */
2826 if (gDvm.debuggerActive) {
2827 dvmDbgPostClassPrepare(clazz);
2828 }
2829
2830bail:
2831 if (!okay) {
2832 clazz->status = CLASS_ERROR;
2833 if (!dvmCheckException(dvmThreadSelf())) {
2834 dvmThrowException("Ljava/lang/VirtualMachineError;", NULL);
2835 }
2836 }
2837 return okay;
2838}
2839
2840/*
2841 * Create the virtual method table.
2842 *
2843 * The top part of the table is a copy of the table from our superclass,
2844 * with our local methods overriding theirs. The bottom part of the table
2845 * has any new methods we defined.
2846 */
2847static bool createVtable(ClassObject* clazz)
2848{
2849 bool result = false;
2850 int maxCount;
2851 int i;
2852
2853 if (clazz->super != NULL) {
2854 //LOGI("SUPER METHODS %d %s->%s\n", clazz->super->vtableCount,
2855 // clazz->descriptor, clazz->super->descriptor);
2856 }
2857
2858 /* the virtual methods we define, plus the superclass vtable size */
2859 maxCount = clazz->virtualMethodCount;
2860 if (clazz->super != NULL) {
2861 maxCount += clazz->super->vtableCount;
2862 } else {
2863 /* TODO: is this invariant true for all java/lang/Objects,
2864 * regardless of the class loader? For now, assume it is.
2865 */
2866 assert(strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0);
2867 }
2868 //LOGD("+++ max vmethods for '%s' is %d\n", clazz->descriptor, maxCount);
2869
2870 /*
2871 * Over-allocate the table, then realloc it down if necessary. So
2872 * long as we don't allocate anything in between we won't cause
2873 * fragmentation, and reducing the size should be unlikely to cause
2874 * a buffer copy.
2875 */
2876 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2877 clazz->vtable = (Method**) dvmLinearAlloc(clazz->classLoader,
2878 sizeof(Method*) * maxCount);
2879 if (clazz->vtable == NULL)
2880 goto bail;
2881
2882 if (clazz->super != NULL) {
2883 int actualCount;
2884
2885 memcpy(clazz->vtable, clazz->super->vtable,
2886 sizeof(*(clazz->vtable)) * clazz->super->vtableCount);
2887 actualCount = clazz->super->vtableCount;
2888
2889 /*
2890 * See if any of our virtual methods override the superclass.
2891 */
2892 for (i = 0; i < clazz->virtualMethodCount; i++) {
2893 Method* localMeth = &clazz->virtualMethods[i];
2894 int si;
2895
2896 for (si = 0; si < clazz->super->vtableCount; si++) {
2897 Method* superMeth = clazz->vtable[si];
2898
2899 if (dvmCompareMethodNamesAndProtos(localMeth, superMeth) == 0)
2900 {
2901 /* verify */
2902 if (dvmIsFinalMethod(superMeth)) {
2903 LOGW("Method %s.%s overrides final %s.%s\n",
2904 localMeth->clazz->descriptor, localMeth->name,
2905 superMeth->clazz->descriptor, superMeth->name);
2906 goto bail;
2907 }
2908 clazz->vtable[si] = localMeth;
2909 localMeth->methodIndex = (u2) si;
2910 //LOGV("+++ override %s.%s (slot %d)\n",
2911 // clazz->descriptor, localMeth->name, si);
2912 break;
2913 }
2914 }
2915
2916 if (si == clazz->super->vtableCount) {
2917 /* not an override, add to end */
2918 clazz->vtable[actualCount] = localMeth;
2919 localMeth->methodIndex = (u2) actualCount;
2920 actualCount++;
2921
2922 //LOGV("+++ add method %s.%s\n",
2923 // clazz->descriptor, localMeth->name);
2924 }
2925 }
2926
2927 if (actualCount != (u2) actualCount) {
2928 LOGE("Too many methods (%d) in class '%s'\n", actualCount,
2929 clazz->descriptor);
2930 goto bail;
2931 }
2932
2933 assert(actualCount <= maxCount);
2934
2935 if (actualCount < maxCount) {
2936 assert(clazz->vtable != NULL);
2937 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2938 clazz->vtable = dvmLinearRealloc(clazz->classLoader, clazz->vtable,
2939 sizeof(*(clazz->vtable)) * actualCount);
2940 if (clazz->vtable == NULL) {
2941 LOGE("vtable realloc failed\n");
2942 goto bail;
2943 } else {
2944 LOGVV("+++ reduced vtable from %d to %d\n",
2945 maxCount, actualCount);
2946 }
2947 }
2948
2949 clazz->vtableCount = actualCount;
2950 } else {
2951 /* java/lang/Object case */
2952 int count = clazz->virtualMethodCount;
2953 if (count != (u2) count) {
2954 LOGE("Too many methods (%d) in base class '%s'\n", count,
2955 clazz->descriptor);
2956 goto bail;
2957 }
2958
2959 for (i = 0; i < count; i++) {
2960 clazz->vtable[i] = &clazz->virtualMethods[i];
2961 clazz->virtualMethods[i].methodIndex = (u2) i;
2962 }
2963 clazz->vtableCount = clazz->virtualMethodCount;
2964 }
2965
2966 result = true;
2967
2968bail:
2969 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2970 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2971 return result;
2972}
2973
2974/*
2975 * Create and populate "iftable".
2976 *
2977 * The set of interfaces we support is the combination of the interfaces
2978 * we implement directly and those implemented by our superclass. Each
2979 * interface can have one or more "superinterfaces", which we must also
2980 * support. For speed we flatten the tree out.
2981 *
2982 * We might be able to speed this up when there are lots of interfaces
2983 * by merge-sorting the class pointers and binary-searching when removing
2984 * duplicates. We could also drop the duplicate removal -- it's only
2985 * there to reduce the memory footprint.
2986 *
2987 * Because of "Miranda methods", this may reallocate clazz->virtualMethods.
2988 *
2989 * Returns "true" on success.
2990 */
2991static bool createIftable(ClassObject* clazz)
2992{
2993 bool result = false;
2994 bool zapIftable = false;
2995 bool zapVtable = false;
2996 bool zapIfvipool = false;
2997 int ifCount, superIfCount, idx;
2998 int i;
2999
3000 if (clazz->super != NULL)
3001 superIfCount = clazz->super->iftableCount;
3002 else
3003 superIfCount = 0;
3004
3005 ifCount = superIfCount;
3006 ifCount += clazz->interfaceCount;
3007 for (i = 0; i < clazz->interfaceCount; i++)
3008 ifCount += clazz->interfaces[i]->iftableCount;
3009
3010 LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d\n",
3011 clazz->descriptor, ifCount - superIfCount, superIfCount, ifCount);
3012
3013 if (ifCount == 0) {
3014 assert(clazz->iftableCount == 0);
3015 assert(clazz->iftable == NULL);
3016 result = true;
3017 goto bail;
3018 }
3019
3020 /*
3021 * Create a table with enough space for all interfaces, and copy the
3022 * superclass' table in.
3023 */
3024 clazz->iftable = (InterfaceEntry*) dvmLinearAlloc(clazz->classLoader,
3025 sizeof(InterfaceEntry) * ifCount);
3026 zapIftable = true;
3027 memset(clazz->iftable, 0x00, sizeof(InterfaceEntry) * ifCount);
3028 if (superIfCount != 0) {
3029 memcpy(clazz->iftable, clazz->super->iftable,
3030 sizeof(InterfaceEntry) * superIfCount);
3031 }
3032
3033 /*
3034 * Create a flattened interface hierarchy of our immediate interfaces.
3035 */
3036 idx = superIfCount;
3037
3038 for (i = 0; i < clazz->interfaceCount; i++) {
3039 ClassObject* interf;
3040 int j;
3041
3042 interf = clazz->interfaces[i];
3043 assert(interf != NULL);
3044
3045 /* make sure this is still an interface class */
3046 if (!dvmIsInterfaceClass(interf)) {
3047 LOGW("Class '%s' implements non-interface '%s'\n",
3048 clazz->descriptor, interf->descriptor);
3049 dvmThrowExceptionWithClassMessage(
3050 "Ljava/lang/IncompatibleClassChangeError;",
3051 clazz->descriptor);
3052 goto bail;
3053 }
3054
3055 /* add entry for this interface */
3056 clazz->iftable[idx++].clazz = interf;
3057
3058 /* add entries for the interface's superinterfaces */
3059 for (j = 0; j < interf->iftableCount; j++) {
3060 clazz->iftable[idx++].clazz = interf->iftable[j].clazz;
3061 }
3062 }
3063
3064 assert(idx == ifCount);
3065
3066 if (false) {
3067 /*
3068 * Remove anything redundant from our recent additions. Note we have
3069 * to traverse the recent adds when looking for duplicates, because
3070 * it's possible the recent additions are self-redundant. This
3071 * reduces the memory footprint of classes with lots of inherited
3072 * interfaces.
3073 *
3074 * (I don't know if this will cause problems later on when we're trying
3075 * to find a static field. It looks like the proper search order is
3076 * (1) current class, (2) interfaces implemented by current class,
3077 * (3) repeat with superclass. A field implemented by an interface
3078 * and by a superclass might come out wrong if the superclass also
3079 * implements the interface. The javac compiler will reject the
3080 * situation as ambiguous, so the concern is somewhat artificial.)
3081 *
3082 * UPDATE: this makes ReferenceType.Interfaces difficult to implement,
3083 * because it wants to return just the interfaces declared to be
3084 * implemented directly by the class. I'm excluding this code for now.
3085 */
3086 for (i = superIfCount; i < ifCount; i++) {
3087 int j;
3088
3089 for (j = 0; j < ifCount; j++) {
3090 if (i == j)
3091 continue;
3092 if (clazz->iftable[i].clazz == clazz->iftable[j].clazz) {
3093 LOGVV("INTF: redundant interface %s in %s\n",
3094 clazz->iftable[i].clazz->descriptor,
3095 clazz->descriptor);
3096
3097 if (i != ifCount-1)
3098 memmove(&clazz->iftable[i], &clazz->iftable[i+1],
3099 (ifCount - i -1) * sizeof(InterfaceEntry));
3100 ifCount--;
3101 i--; // adjust for i++ above
3102 break;
3103 }
3104 }
3105 }
3106 LOGVV("INTF: class '%s' nodupes=%d\n", clazz->descriptor, ifCount);
3107 } // if (false)
3108
3109 clazz->iftableCount = ifCount;
3110
3111 /*
3112 * If we're an interface, we don't need the vtable pointers, so
3113 * we're done. If this class doesn't implement an interface that our
3114 * superclass doesn't have, then we again have nothing to do.
3115 */
3116 if (dvmIsInterfaceClass(clazz) || superIfCount == ifCount) {
3117 //dvmDumpClass(clazz, kDumpClassFullDetail);
3118 result = true;
3119 goto bail;
3120 }
3121
3122 /*
3123 * When we're handling invokeinterface, we probably have an object
3124 * whose type is an interface class rather than a concrete class. We
3125 * need to convert the method reference into a vtable index. So, for
3126 * every entry in "iftable", we create a list of vtable indices.
3127 *
3128 * Because our vtable encompasses the superclass vtable, we can use
3129 * the vtable indices from our superclass for all of the interfaces
3130 * that weren't directly implemented by us.
3131 *
3132 * Each entry in "iftable" has a pointer to the start of its set of
3133 * vtable offsets. The iftable entries in the superclass point to
3134 * storage allocated in the superclass, and the iftable entries added
3135 * for this class point to storage allocated in this class. "iftable"
3136 * is flat for fast access in a class and all of its subclasses, but
3137 * "ifviPool" is only created for the topmost implementor.
3138 */
3139 int poolSize = 0;
3140 for (i = superIfCount; i < ifCount; i++) {
3141 /*
3142 * Note it's valid for an interface to have no methods (e.g.
3143 * java/io/Serializable).
3144 */
3145 LOGVV("INTF: pool: %d from %s\n",
3146 clazz->iftable[i].clazz->virtualMethodCount,
3147 clazz->iftable[i].clazz->descriptor);
3148 poolSize += clazz->iftable[i].clazz->virtualMethodCount;
3149 }
3150
3151 if (poolSize == 0) {
3152 LOGVV("INTF: didn't find any new interfaces with methods\n");
3153 result = true;
3154 goto bail;
3155 }
3156
3157 clazz->ifviPoolCount = poolSize;
3158 clazz->ifviPool = (int*) dvmLinearAlloc(clazz->classLoader,
3159 poolSize * sizeof(int*));
3160 zapIfvipool = true;
3161
3162 /*
3163 * Fill in the vtable offsets for the interfaces that weren't part of
3164 * our superclass.
3165 */
3166 int poolOffset = 0;
3167 Method** mirandaList = NULL;
3168 int mirandaCount = 0, mirandaAlloc = 0;
3169
3170 for (i = superIfCount; i < ifCount; i++) {
3171 ClassObject* interface;
3172 int methIdx;
3173
3174 clazz->iftable[i].methodIndexArray = clazz->ifviPool + poolOffset;
3175 interface = clazz->iftable[i].clazz;
3176 poolOffset += interface->virtualMethodCount; // end here
3177
3178 /*
3179 * For each method listed in the interface's method list, find the
3180 * matching method in our class's method list. We want to favor the
3181 * subclass over the superclass, which just requires walking
3182 * back from the end of the vtable. (This only matters if the
3183 * superclass defines a private method and this class redefines
3184 * it -- otherwise it would use the same vtable slot. In Dalvik
3185 * those don't end up in the virtual method table, so it shouldn't
3186 * matter which direction we go. We walk it backward anyway.)
3187 *
3188 *
3189 * Suppose we have the following arrangement:
3190 * public interface MyInterface
3191 * public boolean inInterface();
3192 * public abstract class MirandaAbstract implements MirandaInterface
3193 * //public abstract boolean inInterface(); // not declared!
3194 * public boolean inAbstract() { stuff } // in vtable
3195 * public class MirandClass extends MirandaAbstract
3196 * public boolean inInterface() { stuff }
3197 * public boolean inAbstract() { stuff } // in vtable
3198 *
3199 * The javac compiler happily compiles MirandaAbstract even though
3200 * it doesn't declare all methods from its interface. When we try
3201 * to set up a vtable for MirandaAbstract, we find that we don't
3202 * have an slot for inInterface. To prevent this, we synthesize
3203 * abstract method declarations in MirandaAbstract.
3204 *
3205 * We have to expand vtable and update some things that point at it,
3206 * so we accumulate the method list and do it all at once below.
3207 */
3208 for (methIdx = 0; methIdx < interface->virtualMethodCount; methIdx++) {
3209 Method* imeth = &interface->virtualMethods[methIdx];
3210 int j;
3211
3212 IF_LOGVV() {
3213 char* desc = dexProtoCopyMethodDescriptor(&imeth->prototype);
3214 LOGVV("INTF: matching '%s' '%s'\n", imeth->name, desc);
3215 free(desc);
3216 }
3217
3218 for (j = clazz->vtableCount-1; j >= 0; j--) {
3219 if (dvmCompareMethodNamesAndProtos(imeth, clazz->vtable[j])
3220 == 0)
3221 {
3222 LOGVV("INTF: matched at %d\n", j);
3223 if (!dvmIsPublicMethod(clazz->vtable[j])) {
3224 LOGW("Implementation of %s.%s is not public\n",
3225 clazz->descriptor, clazz->vtable[j]->name);
3226 dvmThrowException("Ljava/lang/IllegalAccessError;",
3227 "interface implementation not public");
3228 goto bail;
3229 }
3230 clazz->iftable[i].methodIndexArray[methIdx] = j;
3231 break;
3232 }
3233 }
3234 if (j < 0) {
3235 IF_LOGV() {
3236 char* desc =
3237 dexProtoCopyMethodDescriptor(&imeth->prototype);
3238 LOGV("No match for '%s' '%s' in '%s' (creating miranda)\n",
3239 imeth->name, desc, clazz->descriptor);
3240 free(desc);
3241 }
3242 //dvmThrowException("Ljava/lang/RuntimeException;", "Miranda!");
3243 //return false;
3244
3245 if (mirandaCount == mirandaAlloc) {
3246 mirandaAlloc += 8;
3247 if (mirandaList == NULL) {
3248 mirandaList = dvmLinearAlloc(clazz->classLoader,
3249 mirandaAlloc * sizeof(Method*));
3250 } else {
3251 dvmLinearReadOnly(clazz->classLoader, mirandaList);
3252 mirandaList = dvmLinearRealloc(clazz->classLoader,
3253 mirandaList, mirandaAlloc * sizeof(Method*));
3254 }
3255 assert(mirandaList != NULL); // mem failed + we leaked
3256 }
3257
3258 /*
3259 * These may be redundant (e.g. method with same name and
3260 * signature declared in two interfaces implemented by the
3261 * same abstract class). We can squeeze the duplicates
3262 * out here.
3263 */
3264 int mir;
3265 for (mir = 0; mir < mirandaCount; mir++) {
3266 if (dvmCompareMethodNamesAndProtos(
3267 mirandaList[mir], imeth) == 0)
3268 {
3269 IF_LOGVV() {
3270 char* desc = dexProtoCopyMethodDescriptor(
3271 &imeth->prototype);
3272 LOGVV("MIRANDA dupe: %s and %s %s%s\n",
3273 mirandaList[mir]->clazz->descriptor,
3274 imeth->clazz->descriptor,
3275 imeth->name, desc);
3276 free(desc);
3277 }
3278 break;
3279 }
3280 }
3281
3282 /* point the iftable at a phantom slot index */
3283 clazz->iftable[i].methodIndexArray[methIdx] =
3284 clazz->vtableCount + mir;
3285 LOGVV("MIRANDA: %s points at slot %d\n",
3286 imeth->name, clazz->vtableCount + mir);
3287
3288 /* if non-duplicate among Mirandas, add to Miranda list */
3289 if (mir == mirandaCount) {
3290 //LOGV("MIRANDA: holding '%s' in slot %d\n",
3291 // imeth->name, mir);
3292 mirandaList[mirandaCount++] = imeth;
3293 }
3294 }
3295 }
3296 }
3297
3298 if (mirandaCount != 0) {
Andy McFadden68825972009-05-08 11:25:35 -07003299 static const int kManyMirandas = 150; /* arbitrary */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003300 Method* newVirtualMethods;
3301 Method* meth;
3302 int oldMethodCount, oldVtableCount;
3303
3304 for (i = 0; i < mirandaCount; i++) {
3305 LOGVV("MIRANDA %d: %s.%s\n", i,
3306 mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
3307 }
Andy McFadden68825972009-05-08 11:25:35 -07003308 if (mirandaCount > kManyMirandas) {
3309 /*
3310 * Some obfuscators like to create an interface with a huge
3311 * pile of methods, declare classes as implementing it, and then
3312 * only define a couple of methods. This leads to a rather
3313 * massive collection of Miranda methods and a lot of wasted
3314 * space, sometimes enough to blow out the LinearAlloc cap.
3315 */
3316 LOGD("Note: class %s has %d unimplemented (abstract) methods\n",
3317 clazz->descriptor, mirandaCount);
3318 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003319
3320 /*
3321 * We found methods in one or more interfaces for which we do not
3322 * have vtable entries. We have to expand our virtualMethods
3323 * table (which might be empty) to hold some new entries.
3324 */
3325 if (clazz->virtualMethods == NULL) {
3326 newVirtualMethods = (Method*) dvmLinearAlloc(clazz->classLoader,
3327 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3328 } else {
3329 //dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3330 newVirtualMethods = (Method*) dvmLinearRealloc(clazz->classLoader,
3331 clazz->virtualMethods,
3332 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3333 }
3334 if (newVirtualMethods != clazz->virtualMethods) {
3335 /*
3336 * Table was moved in memory. We have to run through the
3337 * vtable and fix the pointers. The vtable entries might be
3338 * pointing at superclasses, so we flip it around: run through
3339 * all locally-defined virtual methods, and fix their entries
3340 * in the vtable. (This would get really messy if sub-classes
3341 * had already been loaded.)
3342 *
3343 * Reminder: clazz->virtualMethods and clazz->virtualMethodCount
3344 * hold the virtual methods declared by this class. The
3345 * method's methodIndex is the vtable index, and is the same
3346 * for all sub-classes (and all super classes in which it is
3347 * defined). We're messing with these because the Miranda
3348 * stuff makes it look like the class actually has an abstract
3349 * method declaration in it.
3350 */
3351 LOGVV("MIRANDA fixing vtable pointers\n");
3352 dvmLinearReadWrite(clazz->classLoader, clazz->vtable);
3353 Method* meth = newVirtualMethods;
3354 for (i = 0; i < clazz->virtualMethodCount; i++, meth++)
3355 clazz->vtable[meth->methodIndex] = meth;
3356 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3357 }
3358
3359 oldMethodCount = clazz->virtualMethodCount;
3360 clazz->virtualMethods = newVirtualMethods;
3361 clazz->virtualMethodCount += mirandaCount;
3362
3363 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3364
3365 /*
3366 * We also have to expand the vtable.
3367 */
3368 assert(clazz->vtable != NULL);
3369 clazz->vtable = (Method**) dvmLinearRealloc(clazz->classLoader,
3370 clazz->vtable,
3371 sizeof(Method*) * (clazz->vtableCount + mirandaCount));
3372 if (clazz->vtable == NULL) {
3373 assert(false);
3374 goto bail;
3375 }
3376 zapVtable = true;
3377
3378 oldVtableCount = clazz->vtableCount;
3379 clazz->vtableCount += mirandaCount;
3380
3381 /*
3382 * Now we need to create the fake methods. We clone the abstract
3383 * method definition from the interface and then replace a few
3384 * things.
Andy McFadden68825972009-05-08 11:25:35 -07003385 *
3386 * The Method will be an "abstract native", with nativeFunc set to
3387 * dvmAbstractMethodStub().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003388 */
3389 meth = clazz->virtualMethods + oldMethodCount;
3390 for (i = 0; i < mirandaCount; i++, meth++) {
3391 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3392 cloneMethod(meth, mirandaList[i]);
3393 meth->clazz = clazz;
3394 meth->accessFlags |= ACC_MIRANDA;
3395 meth->methodIndex = (u2) (oldVtableCount + i);
3396 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3397
3398 /* point the new vtable entry at the new method */
3399 clazz->vtable[oldVtableCount + i] = meth;
3400 }
3401
3402 dvmLinearReadOnly(clazz->classLoader, mirandaList);
3403 dvmLinearFree(clazz->classLoader, mirandaList);
3404
3405 }
3406
3407 /*
3408 * TODO?
3409 * Sort the interfaces by number of declared methods. All we really
3410 * want is to get the interfaces with zero methods at the end of the
3411 * list, so that when we walk through the list during invoke-interface
3412 * we don't examine interfaces that can't possibly be useful.
3413 *
3414 * The set will usually be small, so a simple insertion sort works.
3415 *
3416 * We have to be careful not to change the order of two interfaces
3417 * that define the same method. (Not a problem if we only move the
3418 * zero-method interfaces to the end.)
3419 *
3420 * PROBLEM:
3421 * If we do this, we will no longer be able to identify super vs.
3422 * current class interfaces by comparing clazz->super->iftableCount. This
3423 * breaks anything that only wants to find interfaces declared directly
3424 * by the class (dvmFindStaticFieldHier, ReferenceType.Interfaces,
3425 * dvmDbgOutputAllInterfaces, etc). Need to provide a workaround.
3426 *
3427 * We can sort just the interfaces implemented directly by this class,
3428 * but that doesn't seem like it would provide much of an advantage. I'm
3429 * not sure this is worthwhile.
3430 *
3431 * (This has been made largely obsolete by the interface cache mechanism.)
3432 */
3433
3434 //dvmDumpClass(clazz);
3435
3436 result = true;
3437
3438bail:
3439 if (zapIftable)
3440 dvmLinearReadOnly(clazz->classLoader, clazz->iftable);
3441 if (zapVtable)
3442 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3443 if (zapIfvipool)
3444 dvmLinearReadOnly(clazz->classLoader, clazz->ifviPool);
3445 return result;
3446}
3447
3448
3449/*
3450 * Provide "stub" implementations for methods without them.
3451 *
3452 * Currently we provide an implementation for all abstract methods that
3453 * throws an AbstractMethodError exception. This allows us to avoid an
3454 * explicit check for abstract methods in every virtual call.
3455 *
3456 * NOTE: for Miranda methods, the method declaration is a clone of what
3457 * was found in the interface class. That copy may already have had the
3458 * function pointer filled in, so don't be surprised if it's not NULL.
3459 *
3460 * NOTE: this sets the "native" flag, giving us an "abstract native" method,
3461 * which is nonsensical. Need to make sure that this doesn't escape the
3462 * VM. We can either mask it out in reflection calls, or copy "native"
3463 * into the high 16 bits of accessFlags and check that internally.
3464 */
3465static bool insertMethodStubs(ClassObject* clazz)
3466{
3467 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3468
3469 Method* meth;
3470 int i;
3471
3472 meth = clazz->virtualMethods;
3473 for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
3474 if (dvmIsAbstractMethod(meth)) {
3475 assert(meth->insns == NULL);
3476 assert(meth->nativeFunc == NULL ||
3477 meth->nativeFunc == (DalvikBridgeFunc)dvmAbstractMethodStub);
3478
3479 meth->accessFlags |= ACC_NATIVE;
3480 meth->nativeFunc = (DalvikBridgeFunc) dvmAbstractMethodStub;
3481 }
3482 }
3483
3484 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3485 return true;
3486}
3487
3488
3489/*
3490 * Swap two instance fields.
3491 */
3492static inline void swapField(InstField* pOne, InstField* pTwo)
3493{
3494 InstField swap;
3495
3496 LOGVV(" --- swap '%s' and '%s'\n", pOne->field.name, pTwo->field.name);
3497 swap = *pOne;
3498 *pOne = *pTwo;
3499 *pTwo = swap;
3500}
3501
3502/*
3503 * Assign instance fields to u4 slots.
3504 *
3505 * The top portion of the instance field area is occupied by the superclass
3506 * fields, the bottom by the fields for this class.
3507 *
3508 * "long" and "double" fields occupy two adjacent slots. On some
3509 * architectures, 64-bit quantities must be 64-bit aligned, so we need to
3510 * arrange fields (or introduce padding) to ensure this. We assume the
3511 * fields of the topmost superclass (i.e. Object) are 64-bit aligned, so
3512 * we can just ensure that the offset is "even". To avoid wasting space,
3513 * we want to move non-reference 32-bit fields into gaps rather than
3514 * creating pad words.
3515 *
3516 * In the worst case we will waste 4 bytes, but because objects are
3517 * allocated on >= 64-bit boundaries, those bytes may well be wasted anyway
3518 * (assuming this is the most-derived class).
3519 *
3520 * Pad words are not represented in the field table, so the field table
3521 * itself does not change size.
3522 *
3523 * The number of field slots determines the size of the object, so we
3524 * set that here too.
3525 *
3526 * This function feels a little more complicated than I'd like, but it
3527 * has the property of moving the smallest possible set of fields, which
3528 * should reduce the time required to load a class.
3529 *
3530 * NOTE: reference fields *must* come first, or precacheReferenceOffsets()
3531 * will break.
3532 */
3533static bool computeFieldOffsets(ClassObject* clazz)
3534{
3535 int fieldOffset;
3536 int i, j;
3537
3538 dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
3539
3540 if (clazz->super != NULL)
3541 fieldOffset = clazz->super->objectSize;
3542 else
3543 fieldOffset = offsetof(DataObject, instanceData);
3544
3545 LOGVV("--- computeFieldOffsets '%s'\n", clazz->descriptor);
3546
3547 //LOGI("OFFSETS fieldCount=%d\n", clazz->ifieldCount);
3548 //LOGI("dataobj, instance: %d\n", offsetof(DataObject, instanceData));
3549 //LOGI("classobj, access: %d\n", offsetof(ClassObject, accessFlags));
3550 //LOGI("super=%p, fieldOffset=%d\n", clazz->super, fieldOffset);
3551
3552 /*
3553 * Start by moving all reference fields to the front.
3554 */
3555 clazz->ifieldRefCount = 0;
3556 j = clazz->ifieldCount - 1;
3557 for (i = 0; i < clazz->ifieldCount; i++) {
3558 InstField* pField = &clazz->ifields[i];
3559 char c = pField->field.signature[0];
3560
3561 if (c != '[' && c != 'L') {
3562 /* This isn't a reference field; see if any reference fields
3563 * follow this one. If so, we'll move it to this position.
3564 * (quicksort-style partitioning)
3565 */
3566 while (j > i) {
3567 InstField* refField = &clazz->ifields[j--];
3568 char rc = refField->field.signature[0];
3569
3570 if (rc == '[' || rc == 'L') {
3571 /* Here's a reference field that follows at least one
3572 * non-reference field. Swap it with the current field.
3573 * (When this returns, "pField" points to the reference
3574 * field, and "refField" points to the non-ref field.)
3575 */
3576 swapField(pField, refField);
3577
3578 /* Fix the signature.
3579 */
3580 c = rc;
3581
3582 clazz->ifieldRefCount++;
3583 break;
3584 }
3585 }
3586 /* We may or may not have swapped a field.
3587 */
3588 } else {
3589 /* This is a reference field.
3590 */
3591 clazz->ifieldRefCount++;
3592 }
3593
3594 /*
3595 * If we've hit the end of the reference fields, break.
3596 */
3597 if (c != '[' && c != 'L')
3598 break;
3599
3600 pField->byteOffset = fieldOffset;
3601 fieldOffset += sizeof(u4);
3602 LOGVV(" --- offset1 '%s'=%d\n", pField->field.name,pField->byteOffset);
3603 }
3604
3605 /*
3606 * Now we want to pack all of the double-wide fields together. If we're
3607 * not aligned, though, we want to shuffle one 32-bit field into place.
3608 * If we can't find one, we'll have to pad it.
3609 */
3610 if (i != clazz->ifieldCount && (fieldOffset & 0x04) != 0) {
3611 LOGVV(" +++ not aligned\n");
3612
3613 InstField* pField = &clazz->ifields[i];
3614 char c = pField->field.signature[0];
3615
3616 if (c != 'J' && c != 'D') {
3617 /*
3618 * The field that comes next is 32-bit, so just advance past it.
3619 */
3620 assert(c != '[' && c != 'L');
3621 pField->byteOffset = fieldOffset;
3622 fieldOffset += sizeof(u4);
3623 i++;
3624 LOGVV(" --- offset2 '%s'=%d\n",
3625 pField->field.name, pField->byteOffset);
3626 } else {
3627 /*
3628 * Next field is 64-bit, so search for a 32-bit field we can
3629 * swap into it.
3630 */
3631 bool found = false;
3632 j = clazz->ifieldCount - 1;
3633 while (j > i) {
3634 InstField* singleField = &clazz->ifields[j--];
3635 char rc = singleField->field.signature[0];
3636
3637 if (rc != 'J' && rc != 'D') {
3638 swapField(pField, singleField);
3639 //c = rc;
3640 LOGVV(" +++ swapped '%s' for alignment\n",
3641 pField->field.name);
3642 pField->byteOffset = fieldOffset;
3643 fieldOffset += sizeof(u4);
3644 LOGVV(" --- offset3 '%s'=%d\n",
3645 pField->field.name, pField->byteOffset);
3646 found = true;
3647 i++;
3648 break;
3649 }
3650 }
3651 if (!found) {
3652 LOGV(" +++ inserting pad field in '%s'\n", clazz->descriptor);
3653 fieldOffset += sizeof(u4);
3654 }
3655 }
3656 }
3657
3658 /*
3659 * Alignment is good, shuffle any double-wide fields forward, and
3660 * finish assigning field offsets to all fields.
3661 */
3662 assert(i == clazz->ifieldCount || (fieldOffset & 0x04) == 0);
3663 j = clazz->ifieldCount - 1;
3664 for ( ; i < clazz->ifieldCount; i++) {
3665 InstField* pField = &clazz->ifields[i];
3666 char c = pField->field.signature[0];
3667
3668 if (c != 'D' && c != 'J') {
3669 /* This isn't a double-wide field; see if any double fields
3670 * follow this one. If so, we'll move it to this position.
3671 * (quicksort-style partitioning)
3672 */
3673 while (j > i) {
3674 InstField* doubleField = &clazz->ifields[j--];
3675 char rc = doubleField->field.signature[0];
3676
3677 if (rc == 'D' || rc == 'J') {
3678 /* Here's a double-wide field that follows at least one
3679 * non-double field. Swap it with the current field.
3680 * (When this returns, "pField" points to the reference
3681 * field, and "doubleField" points to the non-double field.)
3682 */
3683 swapField(pField, doubleField);
3684 c = rc;
3685
3686 break;
3687 }
3688 }
3689 /* We may or may not have swapped a field.
3690 */
3691 } else {
3692 /* This is a double-wide field, leave it be.
3693 */
3694 }
3695
3696 pField->byteOffset = fieldOffset;
3697 LOGVV(" --- offset4 '%s'=%d\n", pField->field.name,pField->byteOffset);
3698 fieldOffset += sizeof(u4);
3699 if (c == 'J' || c == 'D')
3700 fieldOffset += sizeof(u4);
3701 }
3702
3703#ifndef NDEBUG
3704 /* Make sure that all reference fields appear before
3705 * non-reference fields, and all double-wide fields are aligned.
3706 */
3707 j = 0; // seen non-ref
3708 for (i = 0; i < clazz->ifieldCount; i++) {
3709 InstField *pField = &clazz->ifields[i];
3710 char c = pField->field.signature[0];
3711
3712 if (c == 'D' || c == 'J') {
3713 assert((pField->byteOffset & 0x07) == 0);
3714 }
3715
3716 if (c != '[' && c != 'L') {
3717 if (!j) {
3718 assert(i == clazz->ifieldRefCount);
3719 j = 1;
3720 }
3721 } else if (j) {
3722 assert(false);
3723 }
3724 }
3725 if (!j) {
3726 assert(clazz->ifieldRefCount == clazz->ifieldCount);
3727 }
3728#endif
3729
3730 /*
3731 * We map a C struct directly on top of java/lang/Class objects. Make
3732 * sure we left enough room for the instance fields.
3733 */
3734 assert(clazz != gDvm.classJavaLangClass || (size_t)fieldOffset <
3735 offsetof(ClassObject, instanceData) + sizeof(clazz->instanceData));
3736
3737 clazz->objectSize = fieldOffset;
3738
3739 dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
3740 return true;
3741}
3742
3743/*
3744 * Throw the VM-spec-mandated error when an exception is thrown during
3745 * class initialization.
3746 *
3747 * The safest way to do this is to call the ExceptionInInitializerError
3748 * constructor that takes a Throwable.
3749 *
3750 * [Do we want to wrap it if the original is an Error rather than
3751 * an Exception?]
3752 */
3753static void throwClinitError(void)
3754{
3755 Thread* self = dvmThreadSelf();
3756 Object* exception;
3757 Object* eiie;
3758
3759 exception = dvmGetException(self);
3760 dvmAddTrackedAlloc(exception, self);
3761 dvmClearException(self);
3762
3763 if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3764 /*
3765 * Always resolves to same thing -- no race condition.
3766 */
3767 gDvm.classJavaLangExceptionInInitializerError =
3768 dvmFindSystemClass(
3769 "Ljava/lang/ExceptionInInitializerError;");
3770 if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3771 LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3772 goto fail;
3773 }
3774
3775 gDvm.methJavaLangExceptionInInitializerError_init =
3776 dvmFindDirectMethodByDescriptor(gDvm.classJavaLangExceptionInInitializerError,
3777 "<init>", "(Ljava/lang/Throwable;)V");
3778 if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) {
3779 LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3780 goto fail;
3781 }
3782 }
3783
3784 eiie = dvmAllocObject(gDvm.classJavaLangExceptionInInitializerError,
3785 ALLOC_DEFAULT);
3786 if (eiie == NULL)
3787 goto fail;
3788
3789 /*
3790 * Construct the new object, and replace the exception with it.
3791 */
3792 JValue unused;
3793 dvmCallMethod(self, gDvm.methJavaLangExceptionInInitializerError_init,
3794 eiie, &unused, exception);
3795 dvmSetException(self, eiie);
3796 dvmReleaseTrackedAlloc(eiie, NULL);
3797 dvmReleaseTrackedAlloc(exception, self);
3798 return;
3799
3800fail: /* restore original exception */
3801 dvmSetException(self, exception);
3802 dvmReleaseTrackedAlloc(exception, self);
3803 return;
3804}
3805
3806/*
3807 * The class failed to initialize on a previous attempt, so we want to throw
3808 * a NoClassDefFoundError (v2 2.17.5). The exception to this rule is if we
3809 * failed in verification, in which case v2 5.4.1 says we need to re-throw
3810 * the previous error.
3811 */
3812static void throwEarlierClassFailure(ClassObject* clazz)
3813{
3814 LOGI("Rejecting re-init on previously-failed class %s v=%p\n",
3815 clazz->descriptor, clazz->verifyErrorClass);
3816
3817 if (clazz->verifyErrorClass == NULL) {
3818 dvmThrowExceptionWithClassMessage("Ljava/lang/NoClassDefFoundError;",
3819 clazz->descriptor);
3820 } else {
3821 dvmThrowExceptionByClassWithClassMessage(clazz->verifyErrorClass,
3822 clazz->descriptor);
3823 }
3824}
3825
3826/*
3827 * Initialize any static fields whose values are stored in
3828 * the DEX file. This must be done during class initialization.
3829 */
3830static void initSFields(ClassObject* clazz)
3831{
3832 Thread* self = dvmThreadSelf(); /* for dvmReleaseTrackedAlloc() */
3833 DexFile* pDexFile;
3834 const DexClassDef* pClassDef;
3835 const DexEncodedArray* pValueList;
3836 EncodedArrayIterator iterator;
3837 int i;
3838
3839 if (clazz->sfieldCount == 0) {
3840 return;
3841 }
3842 if (clazz->pDvmDex == NULL) {
3843 /* generated class; any static fields should already be set up */
3844 LOGV("Not initializing static fields in %s\n", clazz->descriptor);
3845 return;
3846 }
3847 pDexFile = clazz->pDvmDex->pDexFile;
3848
3849 pClassDef = dexFindClass(pDexFile, clazz->descriptor);
3850 assert(pClassDef != NULL);
3851
3852 pValueList = dexGetStaticValuesList(pDexFile, pClassDef);
3853 if (pValueList == NULL) {
3854 return;
3855 }
3856
3857 dvmEncodedArrayIteratorInitialize(&iterator, pValueList, clazz);
3858
3859 /*
3860 * Iterate over the initial values array, setting the corresponding
3861 * static field for each array element.
3862 */
3863
3864 for (i = 0; dvmEncodedArrayIteratorHasNext(&iterator); i++) {
3865 AnnotationValue value;
3866 bool parsed = dvmEncodedArrayIteratorGetNext(&iterator, &value);
3867 StaticField* sfield = &clazz->sfields[i];
3868 const char* descriptor = sfield->field.signature;
3869 bool needRelease = false;
3870
3871 if (! parsed) {
3872 /*
3873 * TODO: Eventually verification should attempt to ensure
3874 * that this can't happen at least due to a data integrity
3875 * problem.
3876 */
3877 LOGE("Static initializer parse failed for %s at index %d",
3878 clazz->descriptor, i);
3879 dvmAbort();
3880 }
3881
3882 /* Verify that the value we got was of a valid type. */
3883
3884 switch (descriptor[0]) {
3885 case 'Z': parsed = (value.type == kDexAnnotationBoolean); break;
3886 case 'B': parsed = (value.type == kDexAnnotationByte); break;
3887 case 'C': parsed = (value.type == kDexAnnotationChar); break;
3888 case 'S': parsed = (value.type == kDexAnnotationShort); break;
3889 case 'I': parsed = (value.type == kDexAnnotationInt); break;
3890 case 'J': parsed = (value.type == kDexAnnotationLong); break;
3891 case 'F': parsed = (value.type == kDexAnnotationFloat); break;
3892 case 'D': parsed = (value.type == kDexAnnotationDouble); break;
3893 case '[': parsed = (value.type == kDexAnnotationNull); break;
3894 case 'L': {
3895 switch (value.type) {
3896 case kDexAnnotationNull: {
3897 /* No need for further tests. */
3898 break;
3899 }
3900 case kDexAnnotationString: {
3901 parsed =
3902 (strcmp(descriptor, "Ljava/lang/String;") == 0);
3903 needRelease = true;
3904 break;
3905 }
3906 case kDexAnnotationType: {
3907 parsed =
3908 (strcmp(descriptor, "Ljava/lang/Class;") == 0);
3909 needRelease = true;
3910 break;
3911 }
3912 default: {
3913 parsed = false;
3914 break;
3915 }
3916 }
3917 break;
3918 }
3919 default: {
3920 parsed = false;
3921 break;
3922 }
3923 }
3924
3925 if (parsed) {
3926 /*
3927 * All's well, so store the value. Note: This always
3928 * stores the full width of a JValue, even though most of
3929 * the time only the first word is needed.
3930 */
3931 sfield->value = value.value;
3932 if (needRelease) {
3933 dvmReleaseTrackedAlloc(value.value.l, self);
3934 }
3935 } else {
3936 /*
3937 * Something up above had a problem. TODO: See comment
3938 * above the switch about verfication.
3939 */
3940 LOGE("Bogus static initialization: value type %d in field type "
3941 "%s for %s at index %d",
3942 value.type, descriptor, clazz->descriptor, i);
3943 dvmAbort();
3944 }
3945 }
3946}
3947
3948
3949/*
3950 * Determine whether "descriptor" yields the same class object in the
3951 * context of clazz1 and clazz2.
3952 *
3953 * The caller must hold gDvm.loadedClasses.
3954 *
3955 * Returns "true" if they match.
3956 */
3957static bool compareDescriptorClasses(const char* descriptor,
3958 const ClassObject* clazz1, const ClassObject* clazz2)
3959{
3960 ClassObject* result1;
3961 ClassObject* result2;
3962
3963 /*
3964 * Do the first lookup by name.
3965 */
3966 result1 = dvmFindClassNoInit(descriptor, clazz1->classLoader);
3967
3968 /*
3969 * We can skip a second lookup by name if the second class loader is
3970 * in the initiating loader list of the class object we retrieved.
3971 * (This means that somebody already did a lookup of this class through
3972 * the second loader, and it resolved to the same class.) If it's not
3973 * there, we may simply not have had an opportunity to add it yet, so
3974 * we do the full lookup.
3975 *
3976 * The initiating loader test should catch the majority of cases
3977 * (in particular, the zillions of references to String/Object).
3978 *
3979 * Unfortunately we're still stuck grabbing a mutex to do the lookup.
3980 *
3981 * For this to work, the superclass/interface should be the first
3982 * argument, so that way if it's from the bootstrap loader this test
3983 * will work. (The bootstrap loader, by definition, never shows up
3984 * as the initiating loader of a class defined by some other loader.)
3985 */
3986 dvmHashTableLock(gDvm.loadedClasses);
3987 bool isInit = dvmLoaderInInitiatingList(result1, clazz2->classLoader);
3988 dvmHashTableUnlock(gDvm.loadedClasses);
3989
3990 if (isInit) {
3991 //printf("%s(obj=%p) / %s(cl=%p): initiating\n",
3992 // result1->descriptor, result1,
3993 // clazz2->descriptor, clazz2->classLoader);
3994 return true;
3995 } else {
3996 //printf("%s(obj=%p) / %s(cl=%p): RAW\n",
3997 // result1->descriptor, result1,
3998 // clazz2->descriptor, clazz2->classLoader);
3999 result2 = dvmFindClassNoInit(descriptor, clazz2->classLoader);
4000 }
4001
4002 if (result1 == NULL || result2 == NULL) {
4003 dvmClearException(dvmThreadSelf());
4004 if (result1 == result2) {
4005 /*
4006 * Neither class loader could find this class. Apparently it
4007 * doesn't exist.
4008 *
4009 * We can either throw some sort of exception now, or just
4010 * assume that it'll fail later when something actually tries
4011 * to use the class. For strict handling we should throw now,
4012 * because a "tricky" class loader could start returning
4013 * something later, and a pair of "tricky" loaders could set
4014 * us up for confusion.
4015 *
4016 * I'm not sure if we're allowed to complain about nonexistent
4017 * classes in method signatures during class init, so for now
4018 * this will just return "true" and let nature take its course.
4019 */
4020 return true;
4021 } else {
4022 /* only one was found, so clearly they're not the same */
4023 return false;
4024 }
4025 }
4026
4027 return result1 == result2;
4028}
4029
4030/*
4031 * For every component in the method descriptor, resolve the class in the
4032 * context of the two classes and compare the results.
4033 *
4034 * For best results, the "superclass" class should be first.
4035 *
4036 * Returns "true" if the classes match, "false" otherwise.
4037 */
4038static bool checkMethodDescriptorClasses(const Method* meth,
4039 const ClassObject* clazz1, const ClassObject* clazz2)
4040{
4041 DexParameterIterator iterator;
4042 const char* descriptor;
4043
4044 /* walk through the list of parameters */
4045 dexParameterIteratorInit(&iterator, &meth->prototype);
4046 while (true) {
4047 descriptor = dexParameterIteratorNextDescriptor(&iterator);
4048
4049 if (descriptor == NULL)
4050 break;
4051
4052 if (descriptor[0] == 'L' || descriptor[0] == '[') {
4053 /* non-primitive type */
4054 if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4055 return false;
4056 }
4057 }
4058
4059 /* check the return type */
4060 descriptor = dexProtoGetReturnType(&meth->prototype);
4061 if (descriptor[0] == 'L' || descriptor[0] == '[') {
4062 if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4063 return false;
4064 }
4065 return true;
4066}
4067
4068/*
4069 * Validate the descriptors in the superclass and interfaces.
4070 *
4071 * What we need to do is ensure that the classes named in the method
4072 * descriptors in our ancestors and ourselves resolve to the same class
Andy McFaddencab8be02009-05-26 13:39:57 -07004073 * objects. We can get conflicts when the classes come from different
4074 * class loaders, and the resolver comes up with different results for
4075 * the same class name in different contexts.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004076 *
Andy McFaddencab8be02009-05-26 13:39:57 -07004077 * An easy way to cause the problem is to declare a base class that uses
4078 * class Foo in a method signature (e.g. as the return type). Then,
4079 * define a subclass and a different version of Foo, and load them from a
4080 * different class loader. If the subclass overrides the method, it will
4081 * have a different concept of what Foo is than its parent does, so even
4082 * though the method signature strings are identical, they actually mean
4083 * different things.
4084 *
4085 * A call to the method through a base-class reference would be treated
4086 * differently than a call to the method through a subclass reference, which
4087 * isn't the way polymorphism works, so we have to reject the subclass.
4088 * If the subclass doesn't override the base method, then there's no
4089 * problem, because calls through base-class references and subclass
4090 * references end up in the same place.
4091 *
4092 * We don't need to check to see if an interface's methods match with its
4093 * superinterface's methods, because you can't instantiate an interface
4094 * and do something inappropriate with it. If interface I1 extends I2
4095 * and is implemented by C, and I1 and I2 are in separate class loaders
4096 * and have conflicting views of other classes, we will catch the conflict
4097 * when we process C. Anything that implements I1 is doomed to failure,
4098 * but we don't need to catch that while processing I1.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004099 *
4100 * On failure, throws an exception and returns "false".
4101 */
4102static bool validateSuperDescriptors(const ClassObject* clazz)
4103{
4104 int i;
4105
4106 if (dvmIsInterfaceClass(clazz))
4107 return true;
4108
4109 /*
4110 * Start with the superclass-declared methods.
4111 */
4112 if (clazz->super != NULL &&
4113 clazz->classLoader != clazz->super->classLoader)
4114 {
4115 /*
Andy McFaddencab8be02009-05-26 13:39:57 -07004116 * Walk through every overridden method and compare resolved
4117 * descriptor components. We pull the Method structs out of
4118 * the vtable. It doesn't matter whether we get the struct from
4119 * the parent or child, since we just need the UTF-8 descriptor,
4120 * which must match.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004121 *
4122 * We need to do this even for the stuff inherited from Object,
4123 * because it's possible that the new class loader has redefined
4124 * a basic class like String.
Andy McFaddene7b30942009-05-27 12:42:38 -07004125 *
4126 * We don't need to check stuff defined in a superclass because
4127 * it was checked when the superclass was loaded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004128 */
4129 const Method* meth;
4130
4131 //printf("Checking %s %p vs %s %p\n",
4132 // clazz->descriptor, clazz->classLoader,
4133 // clazz->super->descriptor, clazz->super->classLoader);
4134 for (i = clazz->super->vtableCount - 1; i >= 0; i--) {
4135 meth = clazz->vtable[i];
Andy McFaddencab8be02009-05-26 13:39:57 -07004136 if (meth != clazz->super->vtable[i] &&
4137 !checkMethodDescriptorClasses(meth, clazz->super, clazz))
4138 {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004139 LOGW("Method mismatch: %s in %s (cl=%p) and super %s (cl=%p)\n",
4140 meth->name, clazz->descriptor, clazz->classLoader,
4141 clazz->super->descriptor, clazz->super->classLoader);
4142 dvmThrowException("Ljava/lang/LinkageError;",
4143 "Classes resolve differently in superclass");
4144 return false;
4145 }
4146 }
4147 }
4148
4149 /*
Andy McFaddene7b30942009-05-27 12:42:38 -07004150 * Check the methods defined by this class against the interfaces it
4151 * implements. If we inherited the implementation from a superclass,
4152 * we have to check it against the superclass (which might be in a
4153 * different class loader). If the superclass also implements the
4154 * interface, we could skip the check since by definition it was
4155 * performed when the class was loaded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004156 */
4157 for (i = 0; i < clazz->iftableCount; i++) {
4158 const InterfaceEntry* iftable = &clazz->iftable[i];
4159
4160 if (clazz->classLoader != iftable->clazz->classLoader) {
4161 const ClassObject* iface = iftable->clazz;
4162 int j;
4163
4164 for (j = 0; j < iface->virtualMethodCount; j++) {
4165 const Method* meth;
4166 int vtableIndex;
4167
4168 vtableIndex = iftable->methodIndexArray[j];
4169 meth = clazz->vtable[vtableIndex];
4170
Andy McFaddene7b30942009-05-27 12:42:38 -07004171 if (!checkMethodDescriptorClasses(meth, iface, meth->clazz)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004172 LOGW("Method mismatch: %s in %s (cl=%p) and "
4173 "iface %s (cl=%p)\n",
4174 meth->name, clazz->descriptor, clazz->classLoader,
4175 iface->descriptor, iface->classLoader);
4176 dvmThrowException("Ljava/lang/LinkageError;",
4177 "Classes resolve differently in interface");
4178 return false;
4179 }
4180 }
4181 }
4182 }
4183
4184 return true;
4185}
4186
4187/*
4188 * Returns true if the class is being initialized by us (which means that
4189 * calling dvmInitClass will return immediately after fiddling with locks).
4190 *
4191 * There isn't a race here, because either clazz->initThreadId won't match
4192 * us, or it will and it was set in the same thread.
4193 */
4194bool dvmIsClassInitializing(const ClassObject* clazz)
4195{
4196 return (clazz->status == CLASS_INITIALIZING &&
4197 clazz->initThreadId == dvmThreadSelf()->threadId);
4198}
4199
4200/*
4201 * If a class has not been initialized, do so by executing the code in
4202 * <clinit>. The sequence is described in the VM spec v2 2.17.5.
4203 *
4204 * It is possible for multiple threads to arrive here simultaneously, so
4205 * we need to lock the class while we check stuff. We know that no
4206 * interpreted code has access to the class yet, so we can use the class's
4207 * monitor lock.
4208 *
4209 * We will often be called recursively, e.g. when the <clinit> code resolves
4210 * one of its fields, the field resolution will try to initialize the class.
4211 *
4212 * This can get very interesting if a class has a static field initialized
4213 * to a new instance of itself. <clinit> will end up calling <init> on
4214 * the members it is initializing, which is fine unless it uses the contents
4215 * of static fields to initialize instance fields. This will leave the
4216 * static-referenced objects in a partially initialized state. This is
4217 * reasonably rare and can sometimes be cured with proper field ordering.
4218 *
4219 * On failure, returns "false" with an exception raised.
4220 *
4221 * -----
4222 *
4223 * It is possible to cause a deadlock by having a situation like this:
4224 * class A { static { sleep(10000); new B(); } }
4225 * class B { static { sleep(10000); new A(); } }
4226 * new Thread() { public void run() { new A(); } }.start();
4227 * new Thread() { public void run() { new B(); } }.start();
4228 * This appears to be expected under the spec.
4229 *
4230 * The interesting question is what to do if somebody calls Thread.interrupt()
4231 * on one of the deadlocked threads. According to the VM spec, they're both
4232 * sitting in "wait". Should the interrupt code quietly raise the
4233 * "interrupted" flag, or should the "wait" return immediately with an
4234 * exception raised?
4235 *
4236 * This gets a little murky. The VM spec says we call "wait", and the
4237 * spec for Thread.interrupt says Object.wait is interruptible. So it
4238 * seems that, if we get unlucky and interrupt class initialization, we
4239 * are expected to throw (which gets converted to ExceptionInInitializerError
4240 * since InterruptedException is checked).
4241 *
4242 * There are a couple of problems here. First, all threads are expected to
4243 * present a consistent view of class initialization, so we can't have it
4244 * fail in one thread and succeed in another. Second, once a class fails
4245 * to initialize, it must *always* fail. This means that a stray interrupt()
4246 * call could render a class unusable for the lifetime of the VM.
4247 *
4248 * In most cases -- the deadlock example above being a counter-example --
4249 * the interrupting thread can't tell whether the target thread handled
4250 * the initialization itself or had to wait while another thread did the
4251 * work. Refusing to interrupt class initialization is, in most cases,
4252 * not something that a program can reliably detect.
4253 *
4254 * On the assumption that interrupting class initialization is highly
4255 * undesirable in most circumstances, and that failing to do so does not
4256 * deviate from the spec in a meaningful way, we don't allow class init
4257 * to be interrupted by Thread.interrupt().
4258 */
4259bool dvmInitClass(ClassObject* clazz)
4260{
4261#if LOG_CLASS_LOADING
4262 bool initializedByUs = false;
4263#endif
4264
4265 Thread* self = dvmThreadSelf();
4266 const Method* method;
4267
4268 dvmLockObject(self, (Object*) clazz);
4269 assert(dvmIsClassLinked(clazz) || clazz->status == CLASS_ERROR);
4270
4271 /*
4272 * If the class hasn't been verified yet, do so now.
4273 */
4274 if (clazz->status < CLASS_VERIFIED) {
4275 /*
4276 * If we're in an "erroneous" state, throw an exception and bail.
4277 */
4278 if (clazz->status == CLASS_ERROR) {
4279 throwEarlierClassFailure(clazz);
4280 goto bail_unlock;
4281 }
4282
4283 assert(clazz->status == CLASS_RESOLVED);
4284 assert(!IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4285
4286 if (gDvm.classVerifyMode == VERIFY_MODE_NONE ||
4287 (gDvm.classVerifyMode == VERIFY_MODE_REMOTE &&
4288 clazz->classLoader == NULL))
4289 {
4290 LOGV("+++ not verifying class %s (cl=%p)\n",
4291 clazz->descriptor, clazz->classLoader);
4292 goto noverify;
4293 }
4294
4295 if (!gDvm.optimizing)
4296 LOGV("+++ late verify on %s\n", clazz->descriptor);
4297
4298 /*
4299 * We're not supposed to optimize an unverified class, but during
4300 * development this mode was useful. We can't verify an optimized
4301 * class because the optimization process discards information.
4302 */
4303 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) {
4304 LOGW("Class '%s' was optimized without verification; "
4305 "not verifying now\n",
4306 clazz->descriptor);
4307 LOGW(" ('rm /data/dalvik-cache/*' and restart to fix this)");
4308 goto verify_failed;
4309 }
4310
4311 clazz->status = CLASS_VERIFYING;
4312 if (!dvmVerifyClass(clazz, VERIFY_DEFAULT)) {
4313verify_failed:
4314 dvmThrowExceptionWithClassMessage("Ljava/lang/VerifyError;",
4315 clazz->descriptor);
4316 clazz->verifyErrorClass = dvmGetException(self)->clazz;
4317 clazz->status = CLASS_ERROR;
4318 goto bail_unlock;
4319 }
4320
4321 clazz->status = CLASS_VERIFIED;
4322 }
4323noverify:
4324
4325 if (clazz->status == CLASS_INITIALIZED)
4326 goto bail_unlock;
4327
4328 while (clazz->status == CLASS_INITIALIZING) {
4329 /* we caught somebody else in the act; was it us? */
4330 if (clazz->initThreadId == self->threadId) {
4331 //LOGV("HEY: found a recursive <clinit>\n");
4332 goto bail_unlock;
4333 }
4334
4335 if (dvmCheckException(self)) {
4336 LOGW("GLITCH: exception pending at start of class init\n");
4337 dvmAbort();
4338 }
4339
4340 /*
4341 * Wait for the other thread to finish initialization. We pass
4342 * "false" for the "interruptShouldThrow" arg so it doesn't throw
4343 * an exception on interrupt.
4344 */
4345 dvmObjectWait(self, (Object*) clazz, 0, 0, false);
4346
4347 /*
4348 * When we wake up, repeat the test for init-in-progress. If there's
4349 * an exception pending (only possible if "interruptShouldThrow"
4350 * was set), bail out.
4351 */
4352 if (dvmCheckException(self)) {
4353 LOGI("Class init of '%s' failing with wait() exception\n",
4354 clazz->descriptor);
4355 /*
4356 * TODO: this is bogus, because it means the two threads have a
4357 * different idea of the class status. We need to flag the
4358 * class as bad and ensure that the initializer thread respects
4359 * our notice. If we get lucky and wake up after the class has
4360 * finished initialization but before being woken, we have to
4361 * swallow the exception, perhaps raising thread->interrupted
4362 * to preserve semantics.
4363 *
4364 * Since we're not currently allowing interrupts, this should
4365 * never happen and we don't need to fix this.
4366 */
4367 assert(false);
4368 throwClinitError();
4369 clazz->status = CLASS_ERROR;
4370 goto bail_unlock;
4371 }
4372 if (clazz->status == CLASS_INITIALIZING) {
4373 LOGI("Waiting again for class init\n");
4374 continue;
4375 }
4376 assert(clazz->status == CLASS_INITIALIZED ||
4377 clazz->status == CLASS_ERROR);
4378 if (clazz->status == CLASS_ERROR) {
4379 /*
4380 * The caller wants an exception, but it was thrown in a
4381 * different thread. Synthesize one here.
4382 */
4383 dvmThrowException("Ljava/lang/UnsatisfiedLinkError;",
4384 "(<clinit> failed, see exception in other thread)");
4385 }
4386 goto bail_unlock;
4387 }
4388
4389 /* see if we failed previously */
4390 if (clazz->status == CLASS_ERROR) {
4391 // might be wise to unlock before throwing; depends on which class
4392 // it is that we have locked
4393 dvmUnlockObject(self, (Object*) clazz);
4394 throwEarlierClassFailure(clazz);
4395 return false;
4396 }
4397
Andy McFaddene15a8eb2010-02-22 17:07:23 -08004398 u8 startWhen = 0;
4399 if (gDvm.allocProf.enabled) {
4400 startWhen = dvmGetRelativeTimeNsec();
4401 }
4402
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004403 /*
4404 * We're ready to go, and have exclusive access to the class.
4405 *
4406 * Before we start initialization, we need to do one extra bit of
4407 * validation: make sure that the methods declared here match up
4408 * with our superclass and interfaces. We know that the UTF-8
4409 * descriptors match, but classes from different class loaders can
4410 * have the same name.
4411 *
4412 * We do this now, rather than at load/link time, for the same reason
4413 * that we defer verification.
4414 *
4415 * It's unfortunate that we need to do this at all, but we risk
4416 * mixing reference types with identical names (see Dalvik test 068).
4417 */
4418 if (!validateSuperDescriptors(clazz)) {
4419 assert(dvmCheckException(self));
4420 clazz->status = CLASS_ERROR;
4421 goto bail_unlock;
4422 }
4423
4424 /*
4425 * Let's initialize this thing.
4426 *
4427 * We unlock the object so that other threads can politely sleep on
4428 * our mutex with Object.wait(), instead of hanging or spinning trying
4429 * to grab our mutex.
4430 */
4431 assert(clazz->status < CLASS_INITIALIZING);
4432
4433#if LOG_CLASS_LOADING
4434 // We started initializing.
4435 logClassLoad('+', clazz);
4436 initializedByUs = true;
4437#endif
4438
4439 clazz->status = CLASS_INITIALIZING;
4440 clazz->initThreadId = self->threadId;
4441 dvmUnlockObject(self, (Object*) clazz);
4442
4443 /* init our superclass */
4444 if (clazz->super != NULL && clazz->super->status != CLASS_INITIALIZED) {
4445 assert(!dvmIsInterfaceClass(clazz));
4446 if (!dvmInitClass(clazz->super)) {
4447 assert(dvmCheckException(self));
4448 clazz->status = CLASS_ERROR;
4449 /* wake up anybody who started waiting while we were unlocked */
4450 dvmLockObject(self, (Object*) clazz);
4451 goto bail_notify;
4452 }
4453 }
4454
4455 /* Initialize any static fields whose values are
4456 * stored in the Dex file. This should include all of the
4457 * simple "final static" fields, which are required to
4458 * be initialized first. (vmspec 2 sec 2.17.5 item 8)
4459 * More-complicated final static fields should be set
4460 * at the beginning of <clinit>; all we can do is trust
4461 * that the compiler did the right thing.
4462 */
4463 initSFields(clazz);
4464
4465 /* Execute any static initialization code.
4466 */
4467 method = dvmFindDirectMethodByDescriptor(clazz, "<clinit>", "()V");
4468 if (method == NULL) {
4469 LOGVV("No <clinit> found for %s\n", clazz->descriptor);
4470 } else {
4471 LOGVV("Invoking %s.<clinit>\n", clazz->descriptor);
4472 JValue unused;
4473 dvmCallMethod(self, method, NULL, &unused);
4474 }
4475
4476 if (dvmCheckException(self)) {
4477 /*
4478 * We've had an exception thrown during static initialization. We
4479 * need to throw an ExceptionInInitializerError, but we want to
4480 * tuck the original exception into the "cause" field.
4481 */
4482 LOGW("Exception %s thrown during %s.<clinit>\n",
4483 (dvmGetException(self)->clazz)->descriptor, clazz->descriptor);
4484 throwClinitError();
4485 //LOGW("+++ replaced\n");
4486
4487 dvmLockObject(self, (Object*) clazz);
4488 clazz->status = CLASS_ERROR;
4489 } else {
4490 /* success! */
4491 dvmLockObject(self, (Object*) clazz);
4492 clazz->status = CLASS_INITIALIZED;
4493 LOGVV("Initialized class: %s\n", clazz->descriptor);
Andy McFaddene15a8eb2010-02-22 17:07:23 -08004494
4495 /*
4496 * Update alloc counters. TODO: guard with mutex.
4497 */
4498 if (gDvm.allocProf.enabled && startWhen != 0) {
4499 u8 initDuration = dvmGetRelativeTimeNsec() - startWhen;
4500 gDvm.allocProf.classInitTime += initDuration;
4501 self->allocProf.classInitTime += initDuration;
4502 gDvm.allocProf.classInitCount++;
4503 self->allocProf.classInitCount++;
4504 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004505 }
4506
4507bail_notify:
4508 /*
4509 * Notify anybody waiting on the object.
4510 */
4511 dvmObjectNotifyAll(self, (Object*) clazz);
4512
4513bail_unlock:
4514
4515#if LOG_CLASS_LOADING
4516 if (initializedByUs) {
4517 // We finished initializing.
4518 logClassLoad('-', clazz);
4519 }
4520#endif
4521
4522 dvmUnlockObject(self, (Object*) clazz);
4523
4524 return (clazz->status != CLASS_ERROR);
4525}
4526
4527/*
4528 * Replace method->nativeFunc and method->insns with new values. This is
4529 * performed on resolution of a native method.
4530 */
4531void dvmSetNativeFunc(const Method* method, DalvikBridgeFunc func,
4532 const u2* insns)
4533{
4534 ClassObject* clazz = method->clazz;
4535
4536 /* just open up both; easier that way */
4537 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4538 dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4539
4540 ((Method*)method)->nativeFunc = func;
4541 ((Method*)method)->insns = insns;
4542
4543 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4544 dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4545}
4546
4547/*
4548 * Add a RegisterMap to a Method. This is done when we verify the class
The Android Open Source Project99409882009-03-18 22:20:24 -07004549 * and compute the register maps at class initialization time (i.e. when
4550 * we don't have a pre-generated map). This means "pMap" is on the heap
4551 * and should be freed when the Method is discarded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004552 */
4553void dvmSetRegisterMap(Method* method, const RegisterMap* pMap)
4554{
4555 ClassObject* clazz = method->clazz;
4556
4557 if (method->registerMap != NULL) {
Andy McFaddend45a8872009-03-24 20:41:52 -07004558 /* unexpected during class loading, okay on first use (uncompress) */
Andy McFadden9faa9e62009-04-08 00:35:55 -07004559 LOGV("NOTE: registerMap already set for %s.%s\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004560 method->clazz->descriptor, method->name);
4561 /* keep going */
4562 }
The Android Open Source Project99409882009-03-18 22:20:24 -07004563 assert(!dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004564
4565 /* might be virtual or direct */
4566 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4567 dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4568
4569 method->registerMap = pMap;
4570
4571 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4572 dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4573}
4574
4575/*
4576 * dvmHashForeach callback. A nonzero return value causes foreach to
4577 * bail out.
4578 */
4579static int findClassCallback(void* vclazz, void* arg)
4580{
4581 ClassObject* clazz = vclazz;
4582 const char* descriptor = (const char*) arg;
4583
4584 if (strcmp(clazz->descriptor, descriptor) == 0)
4585 return (int) clazz;
4586 return 0;
4587}
4588
4589/*
4590 * Find a loaded class by descriptor. Returns the first one found.
4591 * Because there can be more than one if class loaders are involved,
4592 * this is not an especially good API. (Currently only used by the
4593 * debugger and "checking" JNI.)
4594 *
4595 * "descriptor" should have the form "Ljava/lang/Class;" or
4596 * "[Ljava/lang/Class;", i.e. a descriptor and not an internal-form
4597 * class name.
4598 */
4599ClassObject* dvmFindLoadedClass(const char* descriptor)
4600{
4601 int result;
4602
4603 dvmHashTableLock(gDvm.loadedClasses);
4604 result = dvmHashForeach(gDvm.loadedClasses, findClassCallback,
4605 (void*) descriptor);
4606 dvmHashTableUnlock(gDvm.loadedClasses);
4607
4608 return (ClassObject*) result;
4609}
4610
4611/*
4612 * Retrieve the system (a/k/a application) class loader.
4613 */
4614Object* dvmGetSystemClassLoader(void)
4615{
4616 ClassObject* clazz;
4617 Method* getSysMeth;
4618 Object* loader;
4619
4620 clazz = dvmFindSystemClass("Ljava/lang/ClassLoader;");
4621 if (clazz == NULL)
4622 return NULL;
4623
4624 getSysMeth = dvmFindDirectMethodByDescriptor(clazz, "getSystemClassLoader",
4625 "()Ljava/lang/ClassLoader;");
4626 if (getSysMeth == NULL)
4627 return NULL;
4628
4629 JValue result;
4630 dvmCallMethod(dvmThreadSelf(), getSysMeth, NULL, &result);
4631 loader = (Object*)result.l;
4632 return loader;
4633}
4634
4635
4636/*
4637 * This is a dvmHashForeach callback.
4638 */
4639static int dumpClass(void* vclazz, void* varg)
4640{
4641 const ClassObject* clazz = (const ClassObject*) vclazz;
4642 const ClassObject* super;
4643 int flags = (int) varg;
4644 char* desc;
4645 int i;
4646
4647 if (clazz == NULL) {
4648 LOGI("dumpClass: ignoring request to dump null class\n");
4649 return 0;
4650 }
4651
4652 if ((flags & kDumpClassFullDetail) == 0) {
4653 bool showInit = (flags & kDumpClassInitialized) != 0;
4654 bool showLoader = (flags & kDumpClassClassLoader) != 0;
4655 const char* initStr;
4656
4657 initStr = dvmIsClassInitialized(clazz) ? "true" : "false";
4658
4659 if (showInit && showLoader)
4660 LOGI("%s %p %s\n", clazz->descriptor, clazz->classLoader, initStr);
4661 else if (showInit)
4662 LOGI("%s %s\n", clazz->descriptor, initStr);
4663 else if (showLoader)
4664 LOGI("%s %p\n", clazz->descriptor, clazz->classLoader);
4665 else
4666 LOGI("%s\n", clazz->descriptor);
4667
4668 return 0;
4669 }
4670
4671 /* clazz->super briefly holds the superclass index during class prep */
4672 if ((u4)clazz->super > 0x10000 && (u4) clazz->super != (u4)-1)
4673 super = clazz->super;
4674 else
4675 super = NULL;
4676
4677 LOGI("----- %s '%s' cl=%p ser=0x%08x -----\n",
4678 dvmIsInterfaceClass(clazz) ? "interface" : "class",
4679 clazz->descriptor, clazz->classLoader, clazz->serialNumber);
4680 LOGI(" objectSize=%d (%d from super)\n", (int) clazz->objectSize,
4681 super != NULL ? (int) super->objectSize : -1);
4682 LOGI(" access=0x%04x.%04x\n", clazz->accessFlags >> 16,
4683 clazz->accessFlags & JAVA_FLAGS_MASK);
4684 if (super != NULL)
4685 LOGI(" super='%s' (cl=%p)\n", super->descriptor, super->classLoader);
4686 if (dvmIsArrayClass(clazz)) {
4687 LOGI(" dimensions=%d elementClass=%s\n",
4688 clazz->arrayDim, clazz->elementClass->descriptor);
4689 }
4690 if (clazz->iftableCount > 0) {
4691 LOGI(" interfaces (%d):\n", clazz->iftableCount);
4692 for (i = 0; i < clazz->iftableCount; i++) {
4693 InterfaceEntry* ent = &clazz->iftable[i];
4694 int j;
4695
4696 LOGI(" %2d: %s (cl=%p)\n",
4697 i, ent->clazz->descriptor, ent->clazz->classLoader);
4698
4699 /* enable when needed */
4700 if (false && ent->methodIndexArray != NULL) {
4701 for (j = 0; j < ent->clazz->virtualMethodCount; j++)
4702 LOGI(" %2d: %d %s %s\n",
4703 j, ent->methodIndexArray[j],
4704 ent->clazz->virtualMethods[j].name,
4705 clazz->vtable[ent->methodIndexArray[j]]->name);
4706 }
4707 }
4708 }
4709 if (!dvmIsInterfaceClass(clazz)) {
4710 LOGI(" vtable (%d entries, %d in super):\n", clazz->vtableCount,
4711 super != NULL ? super->vtableCount : 0);
4712 for (i = 0; i < clazz->vtableCount; i++) {
4713 desc = dexProtoCopyMethodDescriptor(&clazz->vtable[i]->prototype);
4714 LOGI(" %s%2d: %p %20s %s\n",
4715 (i != clazz->vtable[i]->methodIndex) ? "*** " : "",
4716 (u4) clazz->vtable[i]->methodIndex, clazz->vtable[i],
4717 clazz->vtable[i]->name, desc);
4718 free(desc);
4719 }
4720 LOGI(" direct methods (%d entries):\n", clazz->directMethodCount);
4721 for (i = 0; i < clazz->directMethodCount; i++) {
4722 desc = dexProtoCopyMethodDescriptor(
4723 &clazz->directMethods[i].prototype);
4724 LOGI(" %2d: %20s %s\n", i, clazz->directMethods[i].name,
4725 desc);
4726 free(desc);
4727 }
4728 } else {
4729 LOGI(" interface methods (%d):\n", clazz->virtualMethodCount);
4730 for (i = 0; i < clazz->virtualMethodCount; i++) {
4731 desc = dexProtoCopyMethodDescriptor(
4732 &clazz->virtualMethods[i].prototype);
4733 LOGI(" %2d: %2d %20s %s\n", i,
4734 (u4) clazz->virtualMethods[i].methodIndex,
4735 clazz->virtualMethods[i].name,
4736 desc);
4737 free(desc);
4738 }
4739 }
4740 if (clazz->sfieldCount > 0) {
4741 LOGI(" static fields (%d entries):\n", clazz->sfieldCount);
4742 for (i = 0; i < clazz->sfieldCount; i++) {
4743 LOGI(" %2d: %20s %s\n", i, clazz->sfields[i].field.name,
4744 clazz->sfields[i].field.signature);
4745 }
4746 }
4747 if (clazz->ifieldCount > 0) {
4748 LOGI(" instance fields (%d entries):\n", clazz->ifieldCount);
4749 for (i = 0; i < clazz->ifieldCount; i++) {
4750 LOGI(" %2d: %20s %s\n", i, clazz->ifields[i].field.name,
4751 clazz->ifields[i].field.signature);
4752 }
4753 }
4754 return 0;
4755}
4756
4757/*
4758 * Dump the contents of a single class.
4759 *
4760 * Pass kDumpClassFullDetail into "flags" to get lots of detail.
4761 */
4762void dvmDumpClass(const ClassObject* clazz, int flags)
4763{
4764 dumpClass((void*) clazz, (void*) flags);
4765}
4766
4767/*
4768 * Dump the contents of all classes.
4769 */
4770void dvmDumpAllClasses(int flags)
4771{
4772 dvmHashTableLock(gDvm.loadedClasses);
4773 dvmHashForeach(gDvm.loadedClasses, dumpClass, (void*) flags);
4774 dvmHashTableUnlock(gDvm.loadedClasses);
4775}
4776
4777/*
4778 * Get the number of loaded classes
4779 */
4780int dvmGetNumLoadedClasses()
4781{
4782 int count;
4783 dvmHashTableLock(gDvm.loadedClasses);
4784 count = dvmHashTableNumEntries(gDvm.loadedClasses);
4785 dvmHashTableUnlock(gDvm.loadedClasses);
4786 return count;
4787}
4788
4789/*
4790 * Write some statistics to the log file.
4791 */
4792void dvmDumpLoaderStats(const char* msg)
4793{
4794 LOGV("VM stats (%s): cls=%d/%d meth=%d ifld=%d sfld=%d linear=%d\n",
4795 msg, gDvm.numLoadedClasses, dvmHashTableNumEntries(gDvm.loadedClasses),
4796 gDvm.numDeclaredMethods, gDvm.numDeclaredInstFields,
4797 gDvm.numDeclaredStaticFields, gDvm.pBootLoaderAlloc->curOffset);
4798#ifdef COUNT_PRECISE_METHODS
4799 LOGI("GC precise methods: %d\n",
4800 dvmPointerSetGetCount(gDvm.preciseMethods));
4801#endif
4802}
4803
4804#ifdef PROFILE_FIELD_ACCESS
4805/*
4806 * Dump the field access counts for all fields in this method.
4807 */
4808static int dumpAccessCounts(void* vclazz, void* varg)
4809{
4810 const ClassObject* clazz = (const ClassObject*) vclazz;
4811 int i;
4812
4813 for (i = 0; i < clazz->ifieldCount; i++) {
4814 Field* field = &clazz->ifields[i].field;
4815
4816 if (field->gets != 0)
4817 printf("GI %d %s.%s\n", field->gets,
4818 field->clazz->descriptor, field->name);
4819 if (field->puts != 0)
4820 printf("PI %d %s.%s\n", field->puts,
4821 field->clazz->descriptor, field->name);
4822 }
4823 for (i = 0; i < clazz->sfieldCount; i++) {
4824 Field* field = &clazz->sfields[i].field;
4825
4826 if (field->gets != 0)
4827 printf("GS %d %s.%s\n", field->gets,
4828 field->clazz->descriptor, field->name);
4829 if (field->puts != 0)
4830 printf("PS %d %s.%s\n", field->puts,
4831 field->clazz->descriptor, field->name);
4832 }
4833
4834 return 0;
4835}
4836
4837/*
4838 * Dump the field access counts for all loaded classes.
4839 */
4840void dvmDumpFieldAccessCounts(void)
4841{
4842 dvmHashTableLock(gDvm.loadedClasses);
4843 dvmHashForeach(gDvm.loadedClasses, dumpAccessCounts, NULL);
4844 dvmHashTableUnlock(gDvm.loadedClasses);
4845}
4846#endif
4847
4848
4849/*
4850 * Mark all classes associated with the built-in loader.
4851 */
4852static int markClassObject(void *clazz, void *arg)
4853{
4854 UNUSED_PARAMETER(arg);
4855
4856 dvmMarkObjectNonNull((Object *)clazz);
4857 return 0;
4858}
4859
4860/*
4861 * The garbage collector calls this to mark the class objects for all
4862 * loaded classes.
4863 */
4864void dvmGcScanRootClassLoader()
4865{
4866 /* dvmClassStartup() may not have been called before the first GC.
4867 */
Barry Hayes4dc2ab92010-03-01 09:27:59 -08004868 if (gDvm.unlinkedJavaLangClass != NULL) {
4869 dvmMarkObjectNonNull((Object *)gDvm.unlinkedJavaLangClass);
4870 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004871 if (gDvm.loadedClasses != NULL) {
4872 dvmHashTableLock(gDvm.loadedClasses);
4873 dvmHashForeach(gDvm.loadedClasses, markClassObject, NULL);
4874 dvmHashTableUnlock(gDvm.loadedClasses);
4875 }
4876}
4877
4878
4879/*
4880 * ===========================================================================
4881 * Method Prototypes and Descriptors
4882 * ===========================================================================
4883 */
4884
4885/*
4886 * Compare the two method names and prototypes, a la strcmp(). The
4887 * name is considered the "major" order and the prototype the "minor"
4888 * order. The prototypes are compared as if by dvmCompareMethodProtos().
4889 */
4890int dvmCompareMethodNamesAndProtos(const Method* method1,
4891 const Method* method2)
4892{
4893 int result = strcmp(method1->name, method2->name);
4894
4895 if (result != 0) {
4896 return result;
4897 }
4898
4899 return dvmCompareMethodProtos(method1, method2);
4900}
4901
4902/*
4903 * Compare the two method names and prototypes, a la strcmp(), ignoring
4904 * the return value. The name is considered the "major" order and the
4905 * prototype the "minor" order. The prototypes are compared as if by
4906 * dvmCompareMethodArgProtos().
4907 */
4908int dvmCompareMethodNamesAndParameterProtos(const Method* method1,
4909 const Method* method2)
4910{
4911 int result = strcmp(method1->name, method2->name);
4912
4913 if (result != 0) {
4914 return result;
4915 }
4916
4917 return dvmCompareMethodParameterProtos(method1, method2);
4918}
4919
4920/*
4921 * Compare a (name, prototype) pair with the (name, prototype) of
4922 * a method, a la strcmp(). The name is considered the "major" order and
4923 * the prototype the "minor" order. The descriptor and prototype are
4924 * compared as if by dvmCompareDescriptorAndMethodProto().
4925 */
4926int dvmCompareNameProtoAndMethod(const char* name,
4927 const DexProto* proto, const Method* method)
4928{
4929 int result = strcmp(name, method->name);
4930
4931 if (result != 0) {
4932 return result;
4933 }
4934
4935 return dexProtoCompare(proto, &method->prototype);
4936}
4937
4938/*
4939 * Compare a (name, method descriptor) pair with the (name, prototype) of
4940 * a method, a la strcmp(). The name is considered the "major" order and
4941 * the prototype the "minor" order. The descriptor and prototype are
4942 * compared as if by dvmCompareDescriptorAndMethodProto().
4943 */
4944int dvmCompareNameDescriptorAndMethod(const char* name,
4945 const char* descriptor, const Method* method)
4946{
4947 int result = strcmp(name, method->name);
4948
4949 if (result != 0) {
4950 return result;
4951 }
4952
4953 return dvmCompareDescriptorAndMethodProto(descriptor, method);
4954}