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