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