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