blob: cf38f6e60113f603af61a496f5a151621c99c1ef [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{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001126 assert(clazz->serialNumber == 0);
Andy McFaddenfc3d3162010-08-05 14:34:26 -07001127 clazz->serialNumber = android_atomic_inc(&gDvm.classSerialNumber);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001128}
1129
1130
1131/*
1132 * Find the named class (by descriptor), using the specified
1133 * initiating ClassLoader.
1134 *
1135 * The class will be loaded and initialized if it has not already been.
1136 * If necessary, the superclass will be loaded.
1137 *
1138 * If the class can't be found, returns NULL with an appropriate exception
1139 * raised.
1140 */
1141ClassObject* dvmFindClass(const char* descriptor, Object* loader)
1142{
1143 ClassObject* clazz;
1144
1145 clazz = dvmFindClassNoInit(descriptor, loader);
1146 if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1147 /* initialize class */
1148 if (!dvmInitClass(clazz)) {
1149 /* init failed; leave it in the list, marked as bad */
1150 assert(dvmCheckException(dvmThreadSelf()));
1151 assert(clazz->status == CLASS_ERROR);
1152 return NULL;
1153 }
1154 }
1155
1156 return clazz;
1157}
1158
1159/*
1160 * Find the named class (by descriptor), using the specified
1161 * initiating ClassLoader.
1162 *
1163 * The class will be loaded if it has not already been, as will its
1164 * superclass. It will not be initialized.
1165 *
1166 * If the class can't be found, returns NULL with an appropriate exception
1167 * raised.
1168 */
1169ClassObject* dvmFindClassNoInit(const char* descriptor,
1170 Object* loader)
1171{
1172 assert(descriptor != NULL);
1173 //assert(loader != NULL);
1174
1175 LOGVV("FindClassNoInit '%s' %p\n", descriptor, loader);
1176
1177 if (*descriptor == '[') {
1178 /*
1179 * Array class. Find in table, generate if not found.
1180 */
1181 return dvmFindArrayClass(descriptor, loader);
1182 } else {
1183 /*
1184 * Regular class. Find in table, load if not found.
1185 */
1186 if (loader != NULL) {
1187 return findClassFromLoaderNoInit(descriptor, loader);
1188 } else {
1189 return dvmFindSystemClassNoInit(descriptor);
1190 }
1191 }
1192}
1193
1194/*
1195 * Load the named class (by descriptor) from the specified class
1196 * loader. This calls out to let the ClassLoader object do its thing.
1197 *
1198 * Returns with NULL and an exception raised on error.
1199 */
1200static ClassObject* findClassFromLoaderNoInit(const char* descriptor,
1201 Object* loader)
1202{
1203 //LOGI("##### findClassFromLoaderNoInit (%s,%p)\n",
1204 // descriptor, loader);
1205
1206 Thread* self = dvmThreadSelf();
1207 ClassObject* clazz;
1208
1209 assert(loader != NULL);
1210
1211 /*
1212 * Do we already have it?
1213 *
1214 * The class loader code does the "is it already loaded" check as
1215 * well. However, this call is much faster than calling through
1216 * interpreted code. Doing this does mean that in the common case
1217 * (365 out of 420 calls booting the sim) we're doing the
1218 * lookup-by-descriptor twice. It appears this is still a win, so
1219 * I'm keeping it in.
1220 */
1221 clazz = dvmLookupClass(descriptor, loader, false);
1222 if (clazz != NULL) {
1223 LOGVV("Already loaded: %s %p\n", descriptor, loader);
1224 return clazz;
1225 } else {
1226 LOGVV("Not already loaded: %s %p\n", descriptor, loader);
1227 }
1228
1229 char* dotName = NULL;
1230 StringObject* nameObj = NULL;
1231 Object* excep;
1232 Method* loadClass;
1233
1234 /* convert "Landroid/debug/Stuff;" to "android.debug.Stuff" */
1235 dotName = dvmDescriptorToDot(descriptor);
1236 if (dotName == NULL) {
1237 dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL);
1238 goto bail;
1239 }
Barry Hayes81f3ebe2010-06-15 16:17:37 -07001240 nameObj = dvmCreateStringFromCstr(dotName);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001241 if (nameObj == NULL) {
1242 assert(dvmCheckException(self));
1243 goto bail;
1244 }
1245
1246 // TODO: cache the vtable offset
1247 loadClass = dvmFindVirtualMethodHierByDescriptor(loader->clazz, "loadClass",
1248 "(Ljava/lang/String;)Ljava/lang/Class;");
1249 if (loadClass == NULL) {
1250 LOGW("Couldn't find loadClass in ClassLoader\n");
1251 goto bail;
1252 }
1253
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001254 dvmMethodTraceClassPrepBegin();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001255
1256 /*
1257 * Invoke loadClass(). This will probably result in a couple of
1258 * exceptions being thrown, because the ClassLoader.loadClass()
1259 * implementation eventually calls VMClassLoader.loadClass to see if
1260 * the bootstrap class loader can find it before doing its own load.
1261 */
1262 LOGVV("--- Invoking loadClass(%s, %p)\n", dotName, loader);
1263 JValue result;
1264 dvmCallMethod(self, loadClass, loader, &result, nameObj);
1265 clazz = (ClassObject*) result.l;
1266
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001267 dvmMethodTraceClassPrepEnd();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001268
1269 excep = dvmGetException(self);
1270 if (excep != NULL) {
1271#if DVM_SHOW_EXCEPTION >= 2
1272 LOGD("NOTE: loadClass '%s' %p threw exception %s\n",
1273 dotName, loader, excep->clazz->descriptor);
1274#endif
1275 dvmAddTrackedAlloc(excep, self);
1276 dvmClearException(self);
1277 dvmThrowChainedExceptionWithClassMessage(
1278 "Ljava/lang/NoClassDefFoundError;", descriptor, excep);
1279 dvmReleaseTrackedAlloc(excep, self);
1280 clazz = NULL;
1281 goto bail;
Andy McFaddend0f0ee62010-07-09 10:52:19 -07001282 } else if (clazz == NULL) {
1283 LOGW("ClassLoader returned NULL w/o exception pending\n");
1284 dvmThrowException("Ljava/lang/NullPointerException;",
1285 "ClassLoader returned null");
1286 goto bail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001287 }
1288
1289 dvmAddInitiatingLoader(clazz, loader);
1290
1291 LOGVV("--- Successfully loaded %s %p (thisldr=%p clazz=%p)\n",
1292 descriptor, clazz->classLoader, loader, clazz);
1293
1294bail:
1295 dvmReleaseTrackedAlloc((Object*)nameObj, NULL);
1296 free(dotName);
1297 return clazz;
1298}
1299
1300/*
1301 * Load the named class (by descriptor) from the specified DEX file.
1302 * Used by class loaders to instantiate a class object from a
1303 * VM-managed DEX.
1304 */
1305ClassObject* dvmDefineClass(DvmDex* pDvmDex, const char* descriptor,
1306 Object* classLoader)
1307{
1308 assert(pDvmDex != NULL);
1309
1310 return findClassNoInit(descriptor, classLoader, pDvmDex);
1311}
1312
1313
1314/*
1315 * Find the named class (by descriptor), scanning through the
1316 * bootclasspath if it hasn't already been loaded.
1317 *
1318 * "descriptor" looks like "Landroid/debug/Stuff;".
1319 *
1320 * Uses NULL as the defining class loader.
1321 */
1322ClassObject* dvmFindSystemClass(const char* descriptor)
1323{
1324 ClassObject* clazz;
1325
1326 clazz = dvmFindSystemClassNoInit(descriptor);
1327 if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1328 /* initialize class */
1329 if (!dvmInitClass(clazz)) {
1330 /* init failed; leave it in the list, marked as bad */
1331 assert(dvmCheckException(dvmThreadSelf()));
1332 assert(clazz->status == CLASS_ERROR);
1333 return NULL;
1334 }
1335 }
1336
1337 return clazz;
1338}
1339
1340/*
1341 * Find the named class (by descriptor), searching for it in the
1342 * bootclasspath.
1343 *
1344 * On failure, this returns NULL with an exception raised.
1345 */
1346ClassObject* dvmFindSystemClassNoInit(const char* descriptor)
1347{
1348 return findClassNoInit(descriptor, NULL, NULL);
1349}
1350
1351/*
1352 * Find the named class (by descriptor). If it's not already loaded,
1353 * we load it and link it, but don't execute <clinit>. (The VM has
1354 * specific limitations on which events can cause initialization.)
1355 *
1356 * If "pDexFile" is NULL, we will search the bootclasspath for an entry.
1357 *
1358 * On failure, this returns NULL with an exception raised.
1359 *
1360 * TODO: we need to return an indication of whether we loaded the class or
1361 * used an existing definition. If somebody deliberately tries to load a
1362 * class twice in the same class loader, they should get a LinkageError,
1363 * but inadvertent simultaneous class references should "just work".
1364 */
1365static ClassObject* findClassNoInit(const char* descriptor, Object* loader,
1366 DvmDex* pDvmDex)
1367{
1368 Thread* self = dvmThreadSelf();
1369 ClassObject* clazz;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001370 bool profilerNotified = false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001371
1372 if (loader != NULL) {
1373 LOGVV("#### findClassNoInit(%s,%p,%p)\n", descriptor, loader,
1374 pDvmDex->pDexFile);
1375 }
1376
1377 /*
1378 * We don't expect an exception to be raised at this point. The
1379 * exception handling code is good about managing this. This *can*
1380 * happen if a JNI lookup fails and the JNI code doesn't do any
1381 * error checking before doing another class lookup, so we may just
1382 * want to clear this and restore it on exit. If we don't, some kinds
1383 * of failures can't be detected without rearranging other stuff.
1384 *
1385 * Most often when we hit this situation it means that something is
1386 * broken in the VM or in JNI code, so I'm keeping it in place (and
1387 * making it an informative abort rather than an assert).
1388 */
1389 if (dvmCheckException(self)) {
Andy McFadden504e9f42009-09-15 20:01:40 -07001390 LOGE("Class lookup %s attempted while exception %s pending\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001391 descriptor, dvmGetException(self)->clazz->descriptor);
1392 dvmDumpAllThreads(false);
1393 dvmAbort();
1394 }
1395
1396 clazz = dvmLookupClass(descriptor, loader, true);
1397 if (clazz == NULL) {
1398 const DexClassDef* pClassDef;
1399
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001400 dvmMethodTraceClassPrepBegin();
1401 profilerNotified = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001402
1403#if LOG_CLASS_LOADING
1404 u8 startTime = dvmGetThreadCpuTimeNsec();
1405#endif
1406
1407 if (pDvmDex == NULL) {
1408 assert(loader == NULL); /* shouldn't be here otherwise */
1409 pDvmDex = searchBootPathForClass(descriptor, &pClassDef);
1410 } else {
1411 pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
1412 }
1413
1414 if (pDvmDex == NULL || pClassDef == NULL) {
Andy McFadden7fc3ce82009-07-14 15:57:23 -07001415 if (gDvm.noClassDefFoundErrorObj != NULL) {
1416 /* usual case -- use prefabricated object */
1417 dvmSetException(self, gDvm.noClassDefFoundErrorObj);
1418 } else {
1419 /* dexopt case -- can't guarantee prefab (core.jar) */
1420 dvmThrowExceptionWithClassMessage(
1421 "Ljava/lang/NoClassDefFoundError;", descriptor);
1422 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001423 goto bail;
1424 }
1425
1426 /* found a match, try to load it */
1427 clazz = loadClassFromDex(pDvmDex, pClassDef, loader);
1428 if (dvmCheckException(self)) {
1429 /* class was found but had issues */
Andy McFaddena0b525d2010-08-04 12:47:21 -07001430 if (clazz != NULL) {
1431 dvmFreeClassInnards(clazz);
1432 dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1433 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001434 goto bail;
1435 }
1436
1437 /*
1438 * Lock the class while we link it so other threads must wait for us
1439 * to finish. Set the "initThreadId" so we can identify recursive
1440 * invocation.
1441 */
1442 dvmLockObject(self, (Object*) clazz);
1443 clazz->initThreadId = self->threadId;
1444
1445 /*
1446 * Add to hash table so lookups succeed.
1447 *
1448 * [Are circular references possible when linking a class?]
1449 */
1450 assert(clazz->classLoader == loader);
1451 if (!dvmAddClassToHash(clazz)) {
1452 /*
1453 * Another thread must have loaded the class after we
1454 * started but before we finished. Discard what we've
1455 * done and leave some hints for the GC.
1456 *
1457 * (Yes, this happens.)
1458 */
1459 //LOGW("WOW: somebody loaded %s simultaneously\n", descriptor);
1460 clazz->initThreadId = 0;
1461 dvmUnlockObject(self, (Object*) clazz);
1462
1463 /* Let the GC free the class.
1464 */
Andy McFaddena0b525d2010-08-04 12:47:21 -07001465 dvmFreeClassInnards(clazz);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001466 dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1467
1468 /* Grab the winning class.
1469 */
1470 clazz = dvmLookupClass(descriptor, loader, true);
1471 assert(clazz != NULL);
1472 goto got_class;
1473 }
1474 dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1475
1476#if LOG_CLASS_LOADING
1477 logClassLoadWithTime('>', clazz, startTime);
1478#endif
1479 /*
1480 * Prepare and resolve.
1481 */
Barry Hayesc49db852010-05-14 13:43:34 -07001482 if (!dvmLinkClass(clazz)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001483 assert(dvmCheckException(self));
1484
1485 /* Make note of the error and clean up the class.
1486 */
1487 removeClassFromHash(clazz);
1488 clazz->status = CLASS_ERROR;
1489 dvmFreeClassInnards(clazz);
1490
1491 /* Let any waiters know.
1492 */
1493 clazz->initThreadId = 0;
1494 dvmObjectNotifyAll(self, (Object*) clazz);
1495 dvmUnlockObject(self, (Object*) clazz);
1496
1497#if LOG_CLASS_LOADING
1498 LOG(LOG_INFO, "DVMLINK FAILED FOR CLASS ", "%s in %s\n",
1499 clazz->descriptor, get_process_name());
1500
1501 /*
1502 * TODO: It would probably be better to use a new type code here (instead of '<') to
1503 * indicate the failure. This change would require a matching change in the parser
1504 * and analysis code in frameworks/base/tools/preload.
1505 */
1506 logClassLoad('<', clazz);
1507#endif
1508 clazz = NULL;
1509 if (gDvm.optimizing) {
1510 /* happens with "external" libs */
1511 LOGV("Link of class '%s' failed\n", descriptor);
1512 } else {
1513 LOGW("Link of class '%s' failed\n", descriptor);
1514 }
1515 goto bail;
1516 }
1517 dvmObjectNotifyAll(self, (Object*) clazz);
1518 dvmUnlockObject(self, (Object*) clazz);
1519
1520 /*
1521 * Add class stats to global counters.
1522 *
1523 * TODO: these should probably be atomic ops.
1524 */
1525 gDvm.numLoadedClasses++;
1526 gDvm.numDeclaredMethods +=
1527 clazz->virtualMethodCount + clazz->directMethodCount;
1528 gDvm.numDeclaredInstFields += clazz->ifieldCount;
1529 gDvm.numDeclaredStaticFields += clazz->sfieldCount;
1530
1531 /*
1532 * Cache pointers to basic classes. We want to use these in
1533 * various places, and it's easiest to initialize them on first
1534 * use rather than trying to force them to initialize (startup
1535 * ordering makes it weird).
1536 */
1537 if (gDvm.classJavaLangObject == NULL &&
1538 strcmp(descriptor, "Ljava/lang/Object;") == 0)
1539 {
1540 /* It should be impossible to get here with anything
1541 * but the bootclasspath loader.
1542 */
1543 assert(loader == NULL);
1544 gDvm.classJavaLangObject = clazz;
1545 }
1546
1547#if LOG_CLASS_LOADING
1548 logClassLoad('<', clazz);
1549#endif
1550
1551 } else {
1552got_class:
1553 if (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1554 /*
1555 * We can race with other threads for class linking. We should
1556 * never get here recursively; doing so indicates that two
1557 * classes have circular dependencies.
1558 *
1559 * One exception: we force discovery of java.lang.Class in
1560 * dvmLinkClass(), and Class has Object as its superclass. So
1561 * if the first thing we ever load is Object, we will init
1562 * Object->Class->Object. The easiest way to avoid this is to
1563 * ensure that Object is never the first thing we look up, so
1564 * we get Foo->Class->Object instead.
1565 */
1566 dvmLockObject(self, (Object*) clazz);
1567 if (!dvmIsClassLinked(clazz) &&
1568 clazz->initThreadId == self->threadId)
1569 {
1570 LOGW("Recursive link on class %s\n", clazz->descriptor);
1571 dvmUnlockObject(self, (Object*) clazz);
1572 dvmThrowExceptionWithClassMessage(
1573 "Ljava/lang/ClassCircularityError;", clazz->descriptor);
1574 clazz = NULL;
1575 goto bail;
1576 }
1577 //LOGI("WAITING for '%s' (owner=%d)\n",
1578 // clazz->descriptor, clazz->initThreadId);
1579 while (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1580 dvmObjectWait(self, (Object*) clazz, 0, 0, false);
1581 }
1582 dvmUnlockObject(self, (Object*) clazz);
1583 }
1584 if (clazz->status == CLASS_ERROR) {
1585 /*
1586 * Somebody else tried to load this and failed. We need to raise
1587 * an exception and report failure.
1588 */
1589 throwEarlierClassFailure(clazz);
1590 clazz = NULL;
1591 goto bail;
1592 }
1593 }
1594
1595 /* check some invariants */
1596 assert(dvmIsClassLinked(clazz));
1597 assert(gDvm.classJavaLangClass != NULL);
1598 assert(clazz->obj.clazz == gDvm.classJavaLangClass);
1599 if (clazz != gDvm.classJavaLangObject) {
1600 if (clazz->super == NULL) {
1601 LOGE("Non-Object has no superclass (gDvm.classJavaLangObject=%p)\n",
1602 gDvm.classJavaLangObject);
1603 dvmAbort();
1604 }
1605 }
1606 if (!dvmIsInterfaceClass(clazz)) {
1607 //LOGI("class=%s vtableCount=%d, virtualMeth=%d\n",
1608 // clazz->descriptor, clazz->vtableCount,
1609 // clazz->virtualMethodCount);
1610 assert(clazz->vtableCount >= clazz->virtualMethodCount);
1611 }
1612
1613 /*
1614 * Normally class objects are initialized before we instantiate them,
1615 * but we can't do that with java.lang.Class (chicken, meet egg). We
1616 * do it explicitly here.
1617 *
1618 * The verifier could call here to find Class while verifying Class,
1619 * so we need to check for CLASS_VERIFYING as well as !initialized.
1620 */
1621 if (clazz == gDvm.classJavaLangClass && !dvmIsClassInitialized(clazz) &&
1622 !(clazz->status == CLASS_VERIFYING))
1623 {
1624 LOGV("+++ explicitly initializing %s\n", clazz->descriptor);
1625 dvmInitClass(clazz);
1626 }
1627
1628bail:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001629 if (profilerNotified)
1630 dvmMethodTraceClassPrepEnd();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001631 assert(clazz != NULL || dvmCheckException(self));
1632 return clazz;
1633}
1634
1635/*
1636 * Helper for loadClassFromDex, which takes a DexClassDataHeader and
1637 * encoded data pointer in addition to the other arguments.
1638 */
1639static ClassObject* loadClassFromDex0(DvmDex* pDvmDex,
1640 const DexClassDef* pClassDef, const DexClassDataHeader* pHeader,
1641 const u1* pEncodedData, Object* classLoader)
1642{
1643 ClassObject* newClass = NULL;
1644 const DexFile* pDexFile;
1645 const char* descriptor;
1646 int i;
1647
1648 pDexFile = pDvmDex->pDexFile;
1649 descriptor = dexGetClassDescriptor(pDexFile, pClassDef);
1650
1651 /*
1652 * Make sure the aren't any "bonus" flags set, since we use them for
1653 * runtime state.
1654 */
1655 if ((pClassDef->accessFlags & ~EXPECTED_FILE_FLAGS) != 0) {
1656 LOGW("Invalid file flags in class %s: %04x\n",
1657 descriptor, pClassDef->accessFlags);
1658 return NULL;
1659 }
1660
1661 /*
1662 * Allocate storage for the class object on the GC heap, so that other
1663 * objects can have references to it. We bypass the usual mechanism
1664 * (allocObject), because we don't have all the bits and pieces yet.
1665 *
1666 * Note that we assume that java.lang.Class does not override
1667 * finalize().
1668 */
Barry Hayesc49db852010-05-14 13:43:34 -07001669 /* TODO: Can there be fewer special checks in the usual path? */
1670 assert(descriptor != NULL);
1671 if (classLoader == NULL &&
1672 strcmp(descriptor, "Ljava/lang/Class;") == 0) {
1673 assert(gDvm.classJavaLangClass != NULL);
1674 newClass = gDvm.classJavaLangClass;
1675 } else {
1676 size_t size = classObjectSize(pHeader->staticFieldsSize);
1677 newClass = (ClassObject*) dvmMalloc(size, ALLOC_DEFAULT);
1678 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001679 if (newClass == NULL)
1680 return NULL;
1681
Barry Hayesc49db852010-05-14 13:43:34 -07001682 DVM_OBJECT_INIT(&newClass->obj, gDvm.classJavaLangClass);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001683 dvmSetClassSerialNumber(newClass);
1684 newClass->descriptor = descriptor;
1685 assert(newClass->descriptorAlloc == NULL);
1686 newClass->accessFlags = pClassDef->accessFlags;
Barry Hayes364f9d92010-06-11 16:12:47 -07001687 dvmSetFieldObject((Object *)newClass,
1688 offsetof(ClassObject, classLoader),
1689 (Object *)classLoader);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001690 newClass->pDvmDex = pDvmDex;
1691 newClass->primitiveType = PRIM_NOT;
Barry Hayesc49db852010-05-14 13:43:34 -07001692 newClass->status = CLASS_IDX;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001693
1694 /*
1695 * Stuff the superclass index into the object pointer field. The linker
1696 * pulls it out and replaces it with a resolved ClassObject pointer.
1697 * I'm doing it this way (rather than having a dedicated superclassIdx
1698 * field) to save a few bytes of overhead per class.
1699 *
1700 * newClass->super is not traversed or freed by dvmFreeClassInnards, so
1701 * this is safe.
1702 */
Barry Hayesc49db852010-05-14 13:43:34 -07001703 assert(sizeof(u4) == sizeof(ClassObject*)); /* 32-bit check */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001704 newClass->super = (ClassObject*) pClassDef->superclassIdx;
1705
1706 /*
1707 * Stuff class reference indices into the pointer fields.
1708 *
1709 * The elements of newClass->interfaces are not traversed or freed by
1710 * dvmFreeClassInnards, so this is GC-safe.
1711 */
1712 const DexTypeList* pInterfacesList;
1713 pInterfacesList = dexGetInterfacesList(pDexFile, pClassDef);
1714 if (pInterfacesList != NULL) {
1715 newClass->interfaceCount = pInterfacesList->size;
1716 newClass->interfaces = (ClassObject**) dvmLinearAlloc(classLoader,
1717 newClass->interfaceCount * sizeof(ClassObject*));
1718
1719 for (i = 0; i < newClass->interfaceCount; i++) {
1720 const DexTypeItem* pType = dexGetTypeItem(pInterfacesList, i);
1721 newClass->interfaces[i] = (ClassObject*)(u4) pType->typeIdx;
1722 }
1723 dvmLinearReadOnly(classLoader, newClass->interfaces);
1724 }
1725
1726 /* load field definitions */
1727
1728 /*
Barry Hayes03aa70a2010-03-01 15:49:41 -08001729 * Over-allocate the class object and append static field info
1730 * onto the end. It's fixed-size and known at alloc time. This
1731 * seems to increase zygote sharing. Heap compaction will have to
1732 * be careful if it ever tries to move ClassObject instances,
1733 * because we pass Field pointers around internally. But at least
1734 * now these Field pointers are in the object heap.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001735 */
1736
1737 if (pHeader->staticFieldsSize != 0) {
1738 /* static fields stay on system heap; field data isn't "write once" */
1739 int count = (int) pHeader->staticFieldsSize;
1740 u4 lastIndex = 0;
1741 DexField field;
1742
1743 newClass->sfieldCount = count;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001744 for (i = 0; i < count; i++) {
1745 dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1746 loadSFieldFromDex(newClass, &field, &newClass->sfields[i]);
1747 }
1748 }
1749
1750 if (pHeader->instanceFieldsSize != 0) {
1751 int count = (int) pHeader->instanceFieldsSize;
1752 u4 lastIndex = 0;
1753 DexField field;
1754
1755 newClass->ifieldCount = count;
1756 newClass->ifields = (InstField*) dvmLinearAlloc(classLoader,
1757 count * sizeof(InstField));
1758 for (i = 0; i < count; i++) {
1759 dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1760 loadIFieldFromDex(newClass, &field, &newClass->ifields[i]);
1761 }
1762 dvmLinearReadOnly(classLoader, newClass->ifields);
1763 }
1764
The Android Open Source Project99409882009-03-18 22:20:24 -07001765 /*
1766 * Load method definitions. We do this in two batches, direct then
1767 * virtual.
1768 *
1769 * If register maps have already been generated for this class, and
1770 * precise GC is enabled, we pull out pointers to them. We know that
1771 * they were streamed to the DEX file in the same order in which the
1772 * methods appear.
1773 *
1774 * If the class wasn't pre-verified, the maps will be generated when
1775 * the class is verified during class initialization.
1776 */
1777 u4 classDefIdx = dexGetIndexForClassDef(pDexFile, pClassDef);
1778 const void* classMapData;
1779 u4 numMethods;
1780
1781 if (gDvm.preciseGc) {
1782 classMapData =
Andy McFaddend45a8872009-03-24 20:41:52 -07001783 dvmRegisterMapGetClassData(pDexFile, classDefIdx, &numMethods);
The Android Open Source Project99409882009-03-18 22:20:24 -07001784
1785 /* sanity check */
1786 if (classMapData != NULL &&
1787 pHeader->directMethodsSize + pHeader->virtualMethodsSize != numMethods)
1788 {
1789 LOGE("ERROR: in %s, direct=%d virtual=%d, maps have %d\n",
1790 newClass->descriptor, pHeader->directMethodsSize,
1791 pHeader->virtualMethodsSize, numMethods);
1792 assert(false);
1793 classMapData = NULL; /* abandon */
1794 }
1795 } else {
1796 classMapData = NULL;
1797 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001798
1799 if (pHeader->directMethodsSize != 0) {
1800 int count = (int) pHeader->directMethodsSize;
1801 u4 lastIndex = 0;
1802 DexMethod method;
1803
1804 newClass->directMethodCount = count;
1805 newClass->directMethods = (Method*) dvmLinearAlloc(classLoader,
1806 count * sizeof(Method));
1807 for (i = 0; i < count; i++) {
1808 dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1809 loadMethodFromDex(newClass, &method, &newClass->directMethods[i]);
The Android Open Source Project99409882009-03-18 22:20:24 -07001810 if (classMapData != NULL) {
Andy McFaddend45a8872009-03-24 20:41:52 -07001811 const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
1812 if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
The Android Open Source Project99409882009-03-18 22:20:24 -07001813 newClass->directMethods[i].registerMap = pMap;
1814 /* TODO: add rigorous checks */
1815 assert((newClass->directMethods[i].registersSize+7) / 8 ==
1816 newClass->directMethods[i].registerMap->regWidth);
1817 }
1818 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001819 }
1820 dvmLinearReadOnly(classLoader, newClass->directMethods);
1821 }
1822
1823 if (pHeader->virtualMethodsSize != 0) {
1824 int count = (int) pHeader->virtualMethodsSize;
1825 u4 lastIndex = 0;
1826 DexMethod method;
1827
1828 newClass->virtualMethodCount = count;
1829 newClass->virtualMethods = (Method*) dvmLinearAlloc(classLoader,
1830 count * sizeof(Method));
1831 for (i = 0; i < count; i++) {
1832 dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1833 loadMethodFromDex(newClass, &method, &newClass->virtualMethods[i]);
The Android Open Source Project99409882009-03-18 22:20:24 -07001834 if (classMapData != NULL) {
Andy McFaddend45a8872009-03-24 20:41:52 -07001835 const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
1836 if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
The Android Open Source Project99409882009-03-18 22:20:24 -07001837 newClass->virtualMethods[i].registerMap = pMap;
1838 /* TODO: add rigorous checks */
1839 assert((newClass->virtualMethods[i].registersSize+7) / 8 ==
1840 newClass->virtualMethods[i].registerMap->regWidth);
1841 }
1842 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001843 }
1844 dvmLinearReadOnly(classLoader, newClass->virtualMethods);
1845 }
1846
1847 newClass->sourceFile = dexGetSourceFile(pDexFile, pClassDef);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001848
1849 /* caller must call dvmReleaseTrackedAlloc */
1850 return newClass;
1851}
1852
1853/*
1854 * Try to load the indicated class from the specified DEX file.
1855 *
1856 * This is effectively loadClass()+defineClass() for a DexClassDef. The
1857 * loading was largely done when we crunched through the DEX.
1858 *
1859 * Returns NULL on failure. If we locate the class but encounter an error
1860 * while processing it, an appropriate exception is thrown.
1861 */
1862static ClassObject* loadClassFromDex(DvmDex* pDvmDex,
1863 const DexClassDef* pClassDef, Object* classLoader)
1864{
1865 ClassObject* result;
1866 DexClassDataHeader header;
1867 const u1* pEncodedData;
1868 const DexFile* pDexFile;
1869
1870 assert((pDvmDex != NULL) && (pClassDef != NULL));
1871 pDexFile = pDvmDex->pDexFile;
1872
1873 if (gDvm.verboseClass) {
1874 LOGV("CLASS: loading '%s'...\n",
1875 dexGetClassDescriptor(pDexFile, pClassDef));
1876 }
1877
1878 pEncodedData = dexGetClassData(pDexFile, pClassDef);
1879
1880 if (pEncodedData != NULL) {
1881 dexReadClassDataHeader(&pEncodedData, &header);
1882 } else {
1883 // Provide an all-zeroes header for the rest of the loading.
1884 memset(&header, 0, sizeof(header));
1885 }
1886
1887 result = loadClassFromDex0(pDvmDex, pClassDef, &header, pEncodedData,
1888 classLoader);
1889
1890 if (gDvm.verboseClass && (result != NULL)) {
1891 LOGI("[Loaded %s from DEX %p (cl=%p)]\n",
1892 result->descriptor, pDvmDex, classLoader);
1893 }
1894
1895 return result;
1896}
1897
1898/*
1899 * Free anything in a ClassObject that was allocated on the system heap.
1900 *
1901 * The ClassObject itself is allocated on the GC heap, so we leave it for
1902 * the garbage collector.
1903 *
1904 * NOTE: this may be called with a partially-constructed object.
1905 * NOTE: there is no particular ordering imposed, so don't go poking at
1906 * superclasses.
1907 */
1908void dvmFreeClassInnards(ClassObject* clazz)
1909{
1910 void *tp;
1911 int i;
1912
1913 if (clazz == NULL)
1914 return;
1915
Barry Hayesc49db852010-05-14 13:43:34 -07001916 assert(clazz->obj.clazz == gDvm.classJavaLangClass);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001917
1918 /* Guarantee that dvmFreeClassInnards can be called on a given
1919 * class multiple times by clearing things out as we free them.
1920 * We don't make any attempt at real atomicity here; higher
1921 * levels need to make sure that no two threads can free the
1922 * same ClassObject at the same time.
1923 *
1924 * TODO: maybe just make it so the GC will never free the
1925 * innards of an already-freed class.
1926 *
1927 * TODO: this #define isn't MT-safe -- the compiler could rearrange it.
1928 */
1929#define NULL_AND_FREE(p) \
1930 do { \
1931 if ((p) != NULL) { \
1932 tp = (p); \
1933 (p) = NULL; \
1934 free(tp); \
1935 } \
1936 } while (0)
1937#define NULL_AND_LINEAR_FREE(p) \
1938 do { \
1939 if ((p) != NULL) { \
1940 tp = (p); \
1941 (p) = NULL; \
1942 dvmLinearFree(clazz->classLoader, tp); \
1943 } \
1944 } while (0)
1945
1946 /* arrays just point at Object's vtable; don't free vtable in this case.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001947 */
1948 clazz->vtableCount = -1;
Barry Hayes33a192e2010-06-29 11:14:20 -07001949 if (clazz->vtable == gDvm.classJavaLangObject->vtable) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001950 clazz->vtable = NULL;
1951 } else {
1952 NULL_AND_LINEAR_FREE(clazz->vtable);
1953 }
1954
1955 clazz->descriptor = NULL;
1956 NULL_AND_FREE(clazz->descriptorAlloc);
1957
1958 if (clazz->directMethods != NULL) {
1959 Method *directMethods = clazz->directMethods;
1960 int directMethodCount = clazz->directMethodCount;
1961 clazz->directMethods = NULL;
1962 clazz->directMethodCount = -1;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001963 dvmLinearReadWrite(clazz->classLoader, directMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001964 for (i = 0; i < directMethodCount; i++) {
1965 freeMethodInnards(&directMethods[i]);
1966 }
Andy McFaddenb51ea112009-05-08 16:50:17 -07001967 dvmLinearReadOnly(clazz->classLoader, directMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001968 dvmLinearFree(clazz->classLoader, directMethods);
1969 }
1970 if (clazz->virtualMethods != NULL) {
1971 Method *virtualMethods = clazz->virtualMethods;
1972 int virtualMethodCount = clazz->virtualMethodCount;
1973 clazz->virtualMethodCount = -1;
1974 clazz->virtualMethods = NULL;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001975 dvmLinearReadWrite(clazz->classLoader, virtualMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001976 for (i = 0; i < virtualMethodCount; i++) {
1977 freeMethodInnards(&virtualMethods[i]);
1978 }
Andy McFaddenb51ea112009-05-08 16:50:17 -07001979 dvmLinearReadOnly(clazz->classLoader, virtualMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001980 dvmLinearFree(clazz->classLoader, virtualMethods);
1981 }
1982
Barry Hayes2c987472009-04-06 10:03:48 -07001983 InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz);
1984 loaderList->initiatingLoaderCount = -1;
1985 NULL_AND_FREE(loaderList->initiatingLoaders);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001986
1987 clazz->interfaceCount = -1;
1988 NULL_AND_LINEAR_FREE(clazz->interfaces);
1989
1990 clazz->iftableCount = -1;
1991 NULL_AND_LINEAR_FREE(clazz->iftable);
1992
1993 clazz->ifviPoolCount = -1;
1994 NULL_AND_LINEAR_FREE(clazz->ifviPool);
1995
1996 clazz->sfieldCount = -1;
Barry Hayes03aa70a2010-03-01 15:49:41 -08001997 /* The sfields are attached to the ClassObject, and will be freed
1998 * with it. */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001999
2000 clazz->ifieldCount = -1;
2001 NULL_AND_LINEAR_FREE(clazz->ifields);
2002
2003#undef NULL_AND_FREE
2004#undef NULL_AND_LINEAR_FREE
2005}
2006
2007/*
2008 * Free anything in a Method that was allocated on the system heap.
The Android Open Source Project99409882009-03-18 22:20:24 -07002009 *
2010 * The containing class is largely torn down by this point.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002011 */
2012static void freeMethodInnards(Method* meth)
2013{
2014#if 0
2015 free(meth->exceptions);
2016 free(meth->lines);
2017 free(meth->locals);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002018#endif
The Android Open Source Project99409882009-03-18 22:20:24 -07002019
2020 /*
2021 * Some register maps are allocated on the heap, either because of late
2022 * verification or because we're caching an uncompressed form.
2023 */
2024 const RegisterMap* pMap = meth->registerMap;
Andy McFaddend45a8872009-03-24 20:41:52 -07002025 if (pMap != NULL && dvmRegisterMapGetOnHeap(pMap)) {
The Android Open Source Project99409882009-03-18 22:20:24 -07002026 dvmFreeRegisterMap((RegisterMap*) pMap);
2027 meth->registerMap = NULL;
2028 }
Andy McFaddenb51ea112009-05-08 16:50:17 -07002029
2030 /*
2031 * We may have copied the instructions.
2032 */
2033 if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
2034 DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2035 dvmLinearFree(meth->clazz->classLoader, methodDexCode);
2036 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002037}
2038
2039/*
2040 * Clone a Method, making new copies of anything that will be freed up
The Android Open Source Project99409882009-03-18 22:20:24 -07002041 * by freeMethodInnards(). This is used for "miranda" methods.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002042 */
2043static void cloneMethod(Method* dst, const Method* src)
2044{
The Android Open Source Project99409882009-03-18 22:20:24 -07002045 if (src->registerMap != NULL) {
2046 LOGE("GLITCH: only expected abstract methods here\n");
2047 LOGE(" cloning %s.%s\n", src->clazz->descriptor, src->name);
2048 dvmAbort();
2049 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002050 memcpy(dst, src, sizeof(Method));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002051}
2052
2053/*
2054 * Pull the interesting pieces out of a DexMethod.
2055 *
2056 * The DEX file isn't going anywhere, so we don't need to make copies of
2057 * the code area.
2058 */
2059static void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,
2060 Method* meth)
2061{
2062 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2063 const DexMethodId* pMethodId;
2064 const DexCode* pDexCode;
2065
2066 pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
2067
2068 meth->name = dexStringById(pDexFile, pMethodId->nameIdx);
2069 dexProtoSetFromMethodId(&meth->prototype, pDexFile, pMethodId);
2070 meth->shorty = dexProtoGetShorty(&meth->prototype);
2071 meth->accessFlags = pDexMethod->accessFlags;
2072 meth->clazz = clazz;
2073 meth->jniArgInfo = 0;
2074
2075 if (dvmCompareNameDescriptorAndMethod("finalize", "()V", meth) == 0) {
2076 SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2077 }
2078
2079 pDexCode = dexGetCode(pDexFile, pDexMethod);
2080 if (pDexCode != NULL) {
2081 /* integer constants, copy over for faster access */
2082 meth->registersSize = pDexCode->registersSize;
2083 meth->insSize = pDexCode->insSize;
2084 meth->outsSize = pDexCode->outsSize;
2085
2086 /* pointer to code area */
2087 meth->insns = pDexCode->insns;
2088 } else {
2089 /*
2090 * We don't have a DexCode block, but we still want to know how
2091 * much space is needed for the arguments (so we don't have to
2092 * compute it later). We also take this opportunity to compute
2093 * JNI argument info.
2094 *
2095 * We do this for abstract methods as well, because we want to
2096 * be able to substitute our exception-throwing "stub" in.
2097 */
2098 int argsSize = dvmComputeMethodArgsSize(meth);
2099 if (!dvmIsStaticMethod(meth))
2100 argsSize++;
2101 meth->registersSize = meth->insSize = argsSize;
2102 assert(meth->outsSize == 0);
2103 assert(meth->insns == NULL);
2104
2105 if (dvmIsNativeMethod(meth)) {
2106 meth->nativeFunc = dvmResolveNativeMethod;
2107 meth->jniArgInfo = computeJniArgInfo(&meth->prototype);
2108 }
2109 }
2110}
2111
Andy McFadden96516932009-10-28 17:39:02 -07002112#if 0 /* replaced with private/read-write mapping */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002113/*
Andy McFaddenb51ea112009-05-08 16:50:17 -07002114 * We usually map bytecode directly out of the DEX file, which is mapped
2115 * shared read-only. If we want to be able to modify it, we have to make
2116 * a new copy.
2117 *
2118 * Once copied, the code will be in the LinearAlloc region, which may be
2119 * marked read-only.
2120 *
2121 * The bytecode instructions are embedded inside a DexCode structure, so we
2122 * need to copy all of that. (The dvmGetMethodCode function backs up the
2123 * instruction pointer to find the start of the DexCode.)
2124 */
2125void dvmMakeCodeReadWrite(Method* meth)
2126{
2127 DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2128
2129 if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
2130 dvmLinearReadWrite(meth->clazz->classLoader, methodDexCode);
2131 return;
2132 }
2133
2134 assert(!dvmIsNativeMethod(meth) && !dvmIsAbstractMethod(meth));
2135
2136 size_t dexCodeSize = dexGetDexCodeSize(methodDexCode);
2137 LOGD("Making a copy of %s.%s code (%d bytes)\n",
2138 meth->clazz->descriptor, meth->name, dexCodeSize);
2139
2140 DexCode* newCode =
2141 (DexCode*) dvmLinearAlloc(meth->clazz->classLoader, dexCodeSize);
2142 memcpy(newCode, methodDexCode, dexCodeSize);
2143
2144 meth->insns = newCode->insns;
2145 SET_METHOD_FLAG(meth, METHOD_ISWRITABLE);
2146}
2147
2148/*
2149 * Mark the bytecode read-only.
2150 *
2151 * If the contents of the DexCode haven't actually changed, we could revert
2152 * to the original shared page.
2153 */
2154void dvmMakeCodeReadOnly(Method* meth)
2155{
2156 DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2157 LOGV("+++ marking %p read-only\n", methodDexCode);
2158 dvmLinearReadOnly(meth->clazz->classLoader, methodDexCode);
2159}
Andy McFadden96516932009-10-28 17:39:02 -07002160#endif
Andy McFaddenb51ea112009-05-08 16:50:17 -07002161
2162
2163/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002164 * jniArgInfo (32-bit int) layout:
2165 * SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
2166 *
2167 * S - if set, do things the hard way (scan the signature)
2168 * R - return-type enumeration
2169 * H - target-specific hints
2170 *
2171 * This info is used at invocation time by dvmPlatformInvoke. In most
2172 * cases, the target-specific hints allow dvmPlatformInvoke to avoid
2173 * having to fully parse the signature.
2174 *
2175 * The return-type bits are always set, even if target-specific hint bits
2176 * are unavailable.
2177 */
2178static int computeJniArgInfo(const DexProto* proto)
2179{
2180 const char* sig = dexProtoGetShorty(proto);
Carl Shapiroe3c01da2010-05-20 22:54:18 -07002181 int returnType, jniArgInfo;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002182 u4 hints;
2183
2184 /* The first shorty character is the return type. */
2185 switch (*(sig++)) {
2186 case 'V':
2187 returnType = DALVIK_JNI_RETURN_VOID;
2188 break;
2189 case 'F':
2190 returnType = DALVIK_JNI_RETURN_FLOAT;
2191 break;
2192 case 'D':
2193 returnType = DALVIK_JNI_RETURN_DOUBLE;
2194 break;
2195 case 'J':
2196 returnType = DALVIK_JNI_RETURN_S8;
2197 break;
Bill Buzbeee2557512009-07-27 15:51:54 -07002198 case 'Z':
2199 case 'B':
2200 returnType = DALVIK_JNI_RETURN_S1;
2201 break;
2202 case 'C':
2203 returnType = DALVIK_JNI_RETURN_U2;
2204 break;
2205 case 'S':
2206 returnType = DALVIK_JNI_RETURN_S2;
2207 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002208 default:
2209 returnType = DALVIK_JNI_RETURN_S4;
2210 break;
2211 }
2212
2213 jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT;
2214
2215 hints = dvmPlatformInvokeHints(proto);
2216
2217 if (hints & DALVIK_JNI_NO_ARG_INFO) {
2218 jniArgInfo |= DALVIK_JNI_NO_ARG_INFO;
2219 } else {
2220 assert((hints & DALVIK_JNI_RETURN_MASK) == 0);
2221 jniArgInfo |= hints;
2222 }
2223
2224 return jniArgInfo;
2225}
2226
2227/*
2228 * Load information about a static field.
2229 *
2230 * This also "prepares" static fields by initializing them
2231 * to their "standard default values".
2232 */
2233static void loadSFieldFromDex(ClassObject* clazz,
2234 const DexField* pDexSField, StaticField* sfield)
2235{
2236 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2237 const DexFieldId* pFieldId;
2238
2239 pFieldId = dexGetFieldId(pDexFile, pDexSField->fieldIdx);
2240
2241 sfield->field.clazz = clazz;
2242 sfield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2243 sfield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2244 sfield->field.accessFlags = pDexSField->accessFlags;
2245
2246 /* Static object field values are set to "standard default values"
2247 * (null or 0) until the class is initialized. We delay loading
2248 * constant values from the class until that time.
2249 */
2250 //sfield->value.j = 0;
2251 assert(sfield->value.j == 0LL); // cleared earlier with calloc
2252
2253#ifdef PROFILE_FIELD_ACCESS
2254 sfield->field.gets = sfield->field.puts = 0;
2255#endif
2256}
2257
2258/*
2259 * Load information about an instance field.
2260 */
2261static void loadIFieldFromDex(ClassObject* clazz,
2262 const DexField* pDexIField, InstField* ifield)
2263{
2264 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2265 const DexFieldId* pFieldId;
2266
2267 pFieldId = dexGetFieldId(pDexFile, pDexIField->fieldIdx);
2268
2269 ifield->field.clazz = clazz;
2270 ifield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2271 ifield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2272 ifield->field.accessFlags = pDexIField->accessFlags;
2273#ifndef NDEBUG
2274 assert(ifield->byteOffset == 0); // cleared earlier with calloc
2275 ifield->byteOffset = -1; // make it obvious if we fail to set later
2276#endif
2277
2278#ifdef PROFILE_FIELD_ACCESS
2279 ifield->field.gets = ifield->field.puts = 0;
2280#endif
2281}
2282
2283/*
2284 * Cache java.lang.ref.Reference fields and methods.
2285 */
Barry Hayes6daaac12009-07-08 10:01:56 -07002286static bool precacheReferenceOffsets(ClassObject* clazz)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002287{
2288 Method *meth;
2289 int i;
2290
2291 /* We trick the GC object scanner by not counting
2292 * java.lang.ref.Reference.referent as an object
2293 * field. It will get explicitly scanned as part
2294 * of the reference-walking process.
2295 *
2296 * Find the object field named "referent" and put it
2297 * just after the list of object reference fields.
2298 */
2299 dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
2300 for (i = 0; i < clazz->ifieldRefCount; i++) {
2301 InstField *pField = &clazz->ifields[i];
2302 if (strcmp(pField->field.name, "referent") == 0) {
2303 int targetIndex;
2304
2305 /* Swap this field with the last object field.
2306 */
2307 targetIndex = clazz->ifieldRefCount - 1;
2308 if (i != targetIndex) {
2309 InstField *swapField = &clazz->ifields[targetIndex];
2310 InstField tmpField;
2311 int tmpByteOffset;
2312
2313 /* It's not currently strictly necessary
2314 * for the fields to be in byteOffset order,
2315 * but it's more predictable that way.
2316 */
2317 tmpByteOffset = swapField->byteOffset;
2318 swapField->byteOffset = pField->byteOffset;
2319 pField->byteOffset = tmpByteOffset;
2320
2321 tmpField = *swapField;
2322 *swapField = *pField;
2323 *pField = tmpField;
2324 }
2325
2326 /* One fewer object field (wink wink).
2327 */
2328 clazz->ifieldRefCount--;
2329 i--; /* don't trip "didn't find it" test if field was last */
2330 break;
2331 }
2332 }
2333 dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
2334 if (i == clazz->ifieldRefCount) {
2335 LOGE("Unable to reorder 'referent' in %s\n", clazz->descriptor);
2336 return false;
2337 }
2338
2339 /* Cache pretty much everything about Reference so that
2340 * we don't need to call interpreted code when clearing/enqueueing
2341 * references. This is fragile, so we'll be paranoid.
2342 */
2343 gDvm.classJavaLangRefReference = clazz;
2344
2345 gDvm.offJavaLangRefReference_referent =
2346 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2347 "referent", "Ljava/lang/Object;");
2348 assert(gDvm.offJavaLangRefReference_referent >= 0);
2349
2350 gDvm.offJavaLangRefReference_queue =
2351 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2352 "queue", "Ljava/lang/ref/ReferenceQueue;");
2353 assert(gDvm.offJavaLangRefReference_queue >= 0);
2354
2355 gDvm.offJavaLangRefReference_queueNext =
2356 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2357 "queueNext", "Ljava/lang/ref/Reference;");
2358 assert(gDvm.offJavaLangRefReference_queueNext >= 0);
2359
Carl Shapiro2a6f4842010-07-09 16:50:54 -07002360 gDvm.offJavaLangRefReference_pendingNext =
2361 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2362 "pendingNext", "Ljava/lang/ref/Reference;");
2363 assert(gDvm.offJavaLangRefReference_pendingNext >= 0);
2364
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002365 /* enqueueInternal() is private and thus a direct method. */
2366 meth = dvmFindDirectMethodByDescriptor(clazz, "enqueueInternal", "()Z");
2367 assert(meth != NULL);
2368 gDvm.methJavaLangRefReference_enqueueInternal = meth;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002369
2370 return true;
2371}
2372
2373
2374/*
Barry Hayes6daaac12009-07-08 10:01:56 -07002375 * Set the bitmap of reference offsets, refOffsets, from the ifields
2376 * list.
2377 */
2378static void computeRefOffsets(ClassObject* clazz)
2379{
2380 if (clazz->super != NULL) {
2381 clazz->refOffsets = clazz->super->refOffsets;
2382 } else {
2383 clazz->refOffsets = 0;
2384 }
2385 /*
2386 * If our superclass overflowed, we don't stand a chance.
2387 */
2388 if (clazz->refOffsets != CLASS_WALK_SUPER) {
2389 InstField *f;
2390 int i;
2391
2392 /* All of the fields that contain object references
2393 * are guaranteed to be at the beginning of the ifields list.
2394 */
2395 f = clazz->ifields;
2396 const int ifieldRefCount = clazz->ifieldRefCount;
2397 for (i = 0; i < ifieldRefCount; i++) {
2398 /*
2399 * Note that, per the comment on struct InstField,
2400 * f->byteOffset is the offset from the beginning of
2401 * obj, not the offset into obj->instanceData.
2402 */
Andy McFadden2fbe6d12009-09-04 15:38:13 -07002403 assert(f->byteOffset >= (int) CLASS_SMALLEST_OFFSET);
Barry Hayes6daaac12009-07-08 10:01:56 -07002404 assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
2405 if (CLASS_CAN_ENCODE_OFFSET(f->byteOffset)) {
2406 u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
2407 assert(newBit != 0);
2408 clazz->refOffsets |= newBit;
2409 } else {
2410 clazz->refOffsets = CLASS_WALK_SUPER;
2411 break;
2412 }
2413 f++;
2414 }
2415 }
2416}
2417
2418
2419/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002420 * Link (prepare and resolve). Verification is deferred until later.
2421 *
2422 * This converts symbolic references into pointers. It's independent of
2423 * the source file format.
2424 *
Barry Hayesc49db852010-05-14 13:43:34 -07002425 * If clazz->status is CLASS_IDX, then clazz->super and interfaces[] are
2426 * holding class reference indices rather than pointers. The class
2427 * references will be resolved during link. (This is done when
2428 * loading from DEX to avoid having to create additional storage to
2429 * pass the indices around.)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002430 *
2431 * Returns "false" with an exception pending on failure.
2432 */
Barry Hayesc49db852010-05-14 13:43:34 -07002433bool dvmLinkClass(ClassObject* clazz)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002434{
2435 u4 superclassIdx = 0;
Barry Hayesc49db852010-05-14 13:43:34 -07002436 u4 *interfaceIdxArray = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002437 bool okay = false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002438 int i;
2439
Barry Hayesc49db852010-05-14 13:43:34 -07002440 assert(clazz != NULL);
2441 assert(clazz->descriptor != NULL);
2442 assert(clazz->status == CLASS_IDX || clazz->status == CLASS_LOADED);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002443 if (gDvm.verboseClass)
2444 LOGV("CLASS: linking '%s'...\n", clazz->descriptor);
2445
Barry Hayesc49db852010-05-14 13:43:34 -07002446 assert(gDvm.classJavaLangClass != NULL);
2447 assert(clazz->obj.clazz == gDvm.classJavaLangClass);
2448 if (clazz->classLoader == NULL &&
2449 (strcmp(clazz->descriptor, "Ljava/lang/Class;") == 0))
2450 {
2451 if (gDvm.classJavaLangClass->ifieldCount > CLASS_FIELD_SLOTS) {
2452 LOGE("java.lang.Class has %d instance fields (expected at most %d)",
2453 gDvm.classJavaLangClass->ifieldCount, CLASS_FIELD_SLOTS);
2454 dvmAbort();
2455 }
2456 if (gDvm.classJavaLangClass->sfieldCount != CLASS_SFIELD_SLOTS) {
2457 LOGE("java.lang.Class has %d static fields (expected %d)",
2458 gDvm.classJavaLangClass->sfieldCount, CLASS_SFIELD_SLOTS);
2459 dvmAbort();
2460 }
2461 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002462 /* "Resolve" the class.
2463 *
Barry Hayesc49db852010-05-14 13:43:34 -07002464 * At this point, clazz's reference fields may contain Dex file
2465 * indices instead of direct object references. Proxy objects are
2466 * an exception, and may be the only exception. We need to
2467 * translate those indices into real references, and let the GC
2468 * look inside this ClassObject.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002469 */
Barry Hayesc49db852010-05-14 13:43:34 -07002470 if (clazz->status == CLASS_IDX) {
2471 if (clazz->interfaceCount > 0) {
2472 /* Copy u4 DEX idx values out of the ClassObject* array
2473 * where we stashed them.
2474 */
2475 assert(sizeof(*interfaceIdxArray) == sizeof(*clazz->interfaces));
2476 size_t len = clazz->interfaceCount * sizeof(*interfaceIdxArray);
2477 interfaceIdxArray = malloc(len);
2478 if (interfaceIdxArray == NULL) {
2479 LOGW("Unable to allocate memory to link %s", clazz->descriptor);
2480 goto bail;
Barry Hayes3595a092010-05-24 12:13:30 -07002481 }
Barry Hayesc49db852010-05-14 13:43:34 -07002482 memcpy(interfaceIdxArray, clazz->interfaces, len);
Andy McFadden1145f222010-06-21 12:58:20 -07002483
2484 dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
Barry Hayesc49db852010-05-14 13:43:34 -07002485 memset(clazz->interfaces, 0, len);
Andy McFadden1145f222010-06-21 12:58:20 -07002486 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
Barry Hayesc49db852010-05-14 13:43:34 -07002487 }
2488
2489 assert(sizeof(superclassIdx) == sizeof(clazz->super));
2490 superclassIdx = (u4) clazz->super;
2491 clazz->super = NULL;
2492 /* After this line, clazz will be fair game for the GC. The
2493 * superclass and interfaces are all NULL.
2494 */
2495 clazz->status = CLASS_LOADED;
2496
2497 if (superclassIdx != kDexNoIndex) {
Barry Hayes364f9d92010-06-11 16:12:47 -07002498 ClassObject* super = dvmResolveClass(clazz, superclassIdx, false);
2499 if (super == NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002500 assert(dvmCheckException(dvmThreadSelf()));
Barry Hayesc49db852010-05-14 13:43:34 -07002501 if (gDvm.optimizing) {
2502 /* happens with "external" libs */
2503 LOGV("Unable to resolve superclass of %s (%d)\n",
2504 clazz->descriptor, superclassIdx);
2505 } else {
2506 LOGW("Unable to resolve superclass of %s (%d)\n",
2507 clazz->descriptor, superclassIdx);
2508 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002509 goto bail;
2510 }
Barry Hayes364f9d92010-06-11 16:12:47 -07002511 dvmSetFieldObject((Object *)clazz,
2512 offsetof(ClassObject, super),
2513 (Object *)super);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002514 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002515
Barry Hayesc49db852010-05-14 13:43:34 -07002516 if (clazz->interfaceCount > 0) {
2517 /* Resolve the interfaces implemented directly by this class. */
2518 assert(interfaceIdxArray != NULL);
2519 dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
2520 for (i = 0; i < clazz->interfaceCount; i++) {
2521 assert(interfaceIdxArray[i] != kDexNoIndex);
2522 clazz->interfaces[i] =
2523 dvmResolveClass(clazz, interfaceIdxArray[i], false);
2524 if (clazz->interfaces[i] == NULL) {
2525 const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2526
2527 assert(dvmCheckException(dvmThreadSelf()));
2528 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2529
2530 const char* classDescriptor;
2531 classDescriptor =
2532 dexStringByTypeIdx(pDexFile, interfaceIdxArray[i]);
2533 if (gDvm.optimizing) {
2534 /* happens with "external" libs */
2535 LOGV("Failed resolving %s interface %d '%s'\n",
2536 clazz->descriptor, interfaceIdxArray[i],
2537 classDescriptor);
2538 } else {
2539 LOGI("Failed resolving %s interface %d '%s'\n",
2540 clazz->descriptor, interfaceIdxArray[i],
2541 classDescriptor);
2542 }
2543 goto bail;
2544 }
2545
2546 /* are we allowed to implement this interface? */
2547 if (!dvmCheckClassAccess(clazz, clazz->interfaces[i])) {
2548 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2549 LOGW("Interface '%s' is not accessible to '%s'\n",
2550 clazz->interfaces[i]->descriptor, clazz->descriptor);
2551 dvmThrowException("Ljava/lang/IllegalAccessError;",
2552 "interface not accessible");
2553 goto bail;
2554 }
2555 LOGVV("+++ found interface '%s'\n",
2556 clazz->interfaces[i]->descriptor);
2557 }
2558 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2559 }
2560 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002561 /*
Barry Hayesc49db852010-05-14 13:43:34 -07002562 * There are now Class references visible to the GC in super and
2563 * interfaces.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002564 */
2565
2566 /*
Barry Hayesc49db852010-05-14 13:43:34 -07002567 * All classes have a direct superclass, except for
2568 * java/lang/Object and primitive classes. Primitive classes are
2569 * are created CLASS_INITIALIZED, so won't get here.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002570 */
Barry Hayesc49db852010-05-14 13:43:34 -07002571 assert(clazz->primitiveType == PRIM_NOT);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002572 if (strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0) {
Barry Hayesc49db852010-05-14 13:43:34 -07002573 if (clazz->super != NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002574 /* TODO: is this invariant true for all java/lang/Objects,
2575 * regardless of the class loader? For now, assume it is.
2576 */
2577 dvmThrowException("Ljava/lang/ClassFormatError;",
2578 "java.lang.Object has a superclass");
2579 goto bail;
2580 }
2581
2582 /* Don't finalize objects whose classes use the
2583 * default (empty) Object.finalize().
2584 */
2585 CLEAR_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2586 } else {
Barry Hayesc49db852010-05-14 13:43:34 -07002587 if (clazz->super == NULL) {
2588 dvmThrowException("Ljava/lang/LinkageError;",
2589 "no superclass defined");
2590 goto bail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002591 }
2592 /* verify */
2593 if (dvmIsFinalClass(clazz->super)) {
2594 LOGW("Superclass of '%s' is final '%s'\n",
2595 clazz->descriptor, clazz->super->descriptor);
2596 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2597 "superclass is final");
2598 goto bail;
2599 } else if (dvmIsInterfaceClass(clazz->super)) {
2600 LOGW("Superclass of '%s' is interface '%s'\n",
2601 clazz->descriptor, clazz->super->descriptor);
2602 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2603 "superclass is an interface");
2604 goto bail;
2605 } else if (!dvmCheckClassAccess(clazz, clazz->super)) {
2606 LOGW("Superclass of '%s' (%s) is not accessible\n",
2607 clazz->descriptor, clazz->super->descriptor);
2608 dvmThrowException("Ljava/lang/IllegalAccessError;",
2609 "superclass not accessible");
2610 goto bail;
2611 }
2612
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002613 /* Inherit finalizability from the superclass. If this
2614 * class also overrides finalize(), its CLASS_ISFINALIZABLE
2615 * bit will already be set.
2616 */
2617 if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISFINALIZABLE)) {
2618 SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2619 }
2620
2621 /* See if this class descends from java.lang.Reference
2622 * and set the class flags appropriately.
2623 */
2624 if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISREFERENCE)) {
2625 u4 superRefFlags;
2626
2627 /* We've already determined the reference type of this
2628 * inheritance chain. Inherit reference-ness from the superclass.
2629 */
2630 superRefFlags = GET_CLASS_FLAG_GROUP(clazz->super,
2631 CLASS_ISREFERENCE |
2632 CLASS_ISWEAKREFERENCE |
2633 CLASS_ISPHANTOMREFERENCE);
2634 SET_CLASS_FLAG(clazz, superRefFlags);
2635 } else if (clazz->classLoader == NULL &&
2636 clazz->super->classLoader == NULL &&
2637 strcmp(clazz->super->descriptor,
2638 "Ljava/lang/ref/Reference;") == 0)
2639 {
2640 u4 refFlags;
2641
2642 /* This class extends Reference, which means it should
2643 * be one of the magic Soft/Weak/PhantomReference classes.
2644 */
2645 refFlags = CLASS_ISREFERENCE;
2646 if (strcmp(clazz->descriptor,
2647 "Ljava/lang/ref/SoftReference;") == 0)
2648 {
2649 /* Only CLASS_ISREFERENCE is set for soft references.
2650 */
2651 } else if (strcmp(clazz->descriptor,
2652 "Ljava/lang/ref/WeakReference;") == 0)
2653 {
2654 refFlags |= CLASS_ISWEAKREFERENCE;
2655 } else if (strcmp(clazz->descriptor,
2656 "Ljava/lang/ref/PhantomReference;") == 0)
2657 {
2658 refFlags |= CLASS_ISPHANTOMREFERENCE;
2659 } else {
2660 /* No-one else is allowed to inherit directly
2661 * from Reference.
2662 */
2663//xxx is this the right exception? better than an assertion.
2664 dvmThrowException("Ljava/lang/LinkageError;",
2665 "illegal inheritance from Reference");
2666 goto bail;
2667 }
2668
2669 /* The class should not have any reference bits set yet.
2670 */
2671 assert(GET_CLASS_FLAG_GROUP(clazz,
2672 CLASS_ISREFERENCE |
2673 CLASS_ISWEAKREFERENCE |
2674 CLASS_ISPHANTOMREFERENCE) == 0);
2675
2676 SET_CLASS_FLAG(clazz, refFlags);
2677 }
2678 }
2679
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002680 /*
2681 * Populate vtable.
2682 */
2683 if (dvmIsInterfaceClass(clazz)) {
2684 /* no vtable; just set the method indices */
2685 int count = clazz->virtualMethodCount;
2686
2687 if (count != (u2) count) {
2688 LOGE("Too many methods (%d) in interface '%s'\n", count,
2689 clazz->descriptor);
2690 goto bail;
2691 }
2692
2693 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2694
2695 for (i = 0; i < count; i++)
2696 clazz->virtualMethods[i].methodIndex = (u2) i;
2697
2698 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2699 } else {
2700 if (!createVtable(clazz)) {
2701 LOGW("failed creating vtable\n");
2702 goto bail;
2703 }
2704 }
2705
2706 /*
2707 * Populate interface method tables. Can alter the vtable.
2708 */
2709 if (!createIftable(clazz))
2710 goto bail;
2711
2712 /*
2713 * Insert special-purpose "stub" method implementations.
2714 */
2715 if (!insertMethodStubs(clazz))
2716 goto bail;
2717
2718 /*
2719 * Compute instance field offsets and, hence, the size of the object.
2720 */
2721 if (!computeFieldOffsets(clazz))
2722 goto bail;
2723
2724 /*
2725 * Cache fields and methods from java/lang/ref/Reference and
2726 * java/lang/Class. This has to happen after computeFieldOffsets().
2727 */
2728 if (clazz->classLoader == NULL) {
2729 if (strcmp(clazz->descriptor, "Ljava/lang/ref/Reference;") == 0) {
2730 if (!precacheReferenceOffsets(clazz)) {
2731 LOGE("failed pre-caching Reference offsets\n");
2732 dvmThrowException("Ljava/lang/InternalError;", NULL);
2733 goto bail;
2734 }
2735 } else if (clazz == gDvm.classJavaLangClass) {
2736 gDvm.offJavaLangClass_pd = dvmFindFieldOffset(clazz, "pd",
2737 "Ljava/security/ProtectionDomain;");
2738 if (gDvm.offJavaLangClass_pd <= 0) {
2739 LOGE("ERROR: unable to find 'pd' field in Class\n");
2740 dvmAbort(); /* we're not going to get much farther */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002741 }
2742 }
2743 }
2744
2745 /*
Barry Hayes6daaac12009-07-08 10:01:56 -07002746 * Compact the offsets the GC has to examine into a bitmap, if
2747 * possible. (This has to happen after Reference.referent is
2748 * massaged in precacheReferenceOffsets.)
2749 */
2750 computeRefOffsets(clazz);
2751
2752 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002753 * Done!
2754 */
2755 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED))
2756 clazz->status = CLASS_VERIFIED;
2757 else
2758 clazz->status = CLASS_RESOLVED;
2759 okay = true;
2760 if (gDvm.verboseClass)
2761 LOGV("CLASS: linked '%s'\n", clazz->descriptor);
2762
2763 /*
2764 * We send CLASS_PREPARE events to the debugger from here. The
2765 * definition of "preparation" is creating the static fields for a
2766 * class and initializing them to the standard default values, but not
2767 * executing any code (that comes later, during "initialization").
2768 *
2769 * We did the static prep in loadSFieldFromDex() while loading the class.
2770 *
2771 * The class has been prepared and resolved but possibly not yet verified
2772 * at this point.
2773 */
2774 if (gDvm.debuggerActive) {
2775 dvmDbgPostClassPrepare(clazz);
2776 }
2777
2778bail:
2779 if (!okay) {
2780 clazz->status = CLASS_ERROR;
2781 if (!dvmCheckException(dvmThreadSelf())) {
2782 dvmThrowException("Ljava/lang/VirtualMachineError;", NULL);
2783 }
2784 }
Barry Hayesc49db852010-05-14 13:43:34 -07002785 if (interfaceIdxArray != NULL) {
2786 free(interfaceIdxArray);
2787 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002788 return okay;
2789}
2790
2791/*
2792 * Create the virtual method table.
2793 *
2794 * The top part of the table is a copy of the table from our superclass,
2795 * with our local methods overriding theirs. The bottom part of the table
2796 * has any new methods we defined.
2797 */
2798static bool createVtable(ClassObject* clazz)
2799{
2800 bool result = false;
2801 int maxCount;
2802 int i;
2803
2804 if (clazz->super != NULL) {
2805 //LOGI("SUPER METHODS %d %s->%s\n", clazz->super->vtableCount,
2806 // clazz->descriptor, clazz->super->descriptor);
2807 }
2808
2809 /* the virtual methods we define, plus the superclass vtable size */
2810 maxCount = clazz->virtualMethodCount;
2811 if (clazz->super != NULL) {
2812 maxCount += clazz->super->vtableCount;
2813 } else {
2814 /* TODO: is this invariant true for all java/lang/Objects,
2815 * regardless of the class loader? For now, assume it is.
2816 */
2817 assert(strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0);
2818 }
2819 //LOGD("+++ max vmethods for '%s' is %d\n", clazz->descriptor, maxCount);
2820
2821 /*
2822 * Over-allocate the table, then realloc it down if necessary. So
2823 * long as we don't allocate anything in between we won't cause
2824 * fragmentation, and reducing the size should be unlikely to cause
2825 * a buffer copy.
2826 */
2827 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2828 clazz->vtable = (Method**) dvmLinearAlloc(clazz->classLoader,
2829 sizeof(Method*) * maxCount);
2830 if (clazz->vtable == NULL)
2831 goto bail;
2832
2833 if (clazz->super != NULL) {
2834 int actualCount;
2835
2836 memcpy(clazz->vtable, clazz->super->vtable,
2837 sizeof(*(clazz->vtable)) * clazz->super->vtableCount);
2838 actualCount = clazz->super->vtableCount;
2839
2840 /*
2841 * See if any of our virtual methods override the superclass.
2842 */
2843 for (i = 0; i < clazz->virtualMethodCount; i++) {
2844 Method* localMeth = &clazz->virtualMethods[i];
2845 int si;
2846
2847 for (si = 0; si < clazz->super->vtableCount; si++) {
2848 Method* superMeth = clazz->vtable[si];
2849
2850 if (dvmCompareMethodNamesAndProtos(localMeth, superMeth) == 0)
2851 {
2852 /* verify */
2853 if (dvmIsFinalMethod(superMeth)) {
2854 LOGW("Method %s.%s overrides final %s.%s\n",
2855 localMeth->clazz->descriptor, localMeth->name,
2856 superMeth->clazz->descriptor, superMeth->name);
2857 goto bail;
2858 }
2859 clazz->vtable[si] = localMeth;
2860 localMeth->methodIndex = (u2) si;
2861 //LOGV("+++ override %s.%s (slot %d)\n",
2862 // clazz->descriptor, localMeth->name, si);
2863 break;
2864 }
2865 }
2866
2867 if (si == clazz->super->vtableCount) {
2868 /* not an override, add to end */
2869 clazz->vtable[actualCount] = localMeth;
2870 localMeth->methodIndex = (u2) actualCount;
2871 actualCount++;
2872
2873 //LOGV("+++ add method %s.%s\n",
2874 // clazz->descriptor, localMeth->name);
2875 }
2876 }
2877
2878 if (actualCount != (u2) actualCount) {
2879 LOGE("Too many methods (%d) in class '%s'\n", actualCount,
2880 clazz->descriptor);
2881 goto bail;
2882 }
2883
2884 assert(actualCount <= maxCount);
2885
2886 if (actualCount < maxCount) {
2887 assert(clazz->vtable != NULL);
2888 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2889 clazz->vtable = dvmLinearRealloc(clazz->classLoader, clazz->vtable,
2890 sizeof(*(clazz->vtable)) * actualCount);
2891 if (clazz->vtable == NULL) {
2892 LOGE("vtable realloc failed\n");
2893 goto bail;
2894 } else {
2895 LOGVV("+++ reduced vtable from %d to %d\n",
2896 maxCount, actualCount);
2897 }
2898 }
2899
2900 clazz->vtableCount = actualCount;
2901 } else {
2902 /* java/lang/Object case */
2903 int count = clazz->virtualMethodCount;
2904 if (count != (u2) count) {
2905 LOGE("Too many methods (%d) in base class '%s'\n", count,
2906 clazz->descriptor);
2907 goto bail;
2908 }
2909
2910 for (i = 0; i < count; i++) {
2911 clazz->vtable[i] = &clazz->virtualMethods[i];
2912 clazz->virtualMethods[i].methodIndex = (u2) i;
2913 }
2914 clazz->vtableCount = clazz->virtualMethodCount;
2915 }
2916
2917 result = true;
2918
2919bail:
2920 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2921 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2922 return result;
2923}
2924
2925/*
2926 * Create and populate "iftable".
2927 *
2928 * The set of interfaces we support is the combination of the interfaces
2929 * we implement directly and those implemented by our superclass. Each
2930 * interface can have one or more "superinterfaces", which we must also
2931 * support. For speed we flatten the tree out.
2932 *
2933 * We might be able to speed this up when there are lots of interfaces
2934 * by merge-sorting the class pointers and binary-searching when removing
2935 * duplicates. We could also drop the duplicate removal -- it's only
2936 * there to reduce the memory footprint.
2937 *
2938 * Because of "Miranda methods", this may reallocate clazz->virtualMethods.
2939 *
2940 * Returns "true" on success.
2941 */
2942static bool createIftable(ClassObject* clazz)
2943{
2944 bool result = false;
2945 bool zapIftable = false;
2946 bool zapVtable = false;
2947 bool zapIfvipool = false;
2948 int ifCount, superIfCount, idx;
2949 int i;
2950
2951 if (clazz->super != NULL)
2952 superIfCount = clazz->super->iftableCount;
2953 else
2954 superIfCount = 0;
2955
2956 ifCount = superIfCount;
2957 ifCount += clazz->interfaceCount;
2958 for (i = 0; i < clazz->interfaceCount; i++)
2959 ifCount += clazz->interfaces[i]->iftableCount;
2960
2961 LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d\n",
2962 clazz->descriptor, ifCount - superIfCount, superIfCount, ifCount);
2963
2964 if (ifCount == 0) {
2965 assert(clazz->iftableCount == 0);
2966 assert(clazz->iftable == NULL);
2967 result = true;
2968 goto bail;
2969 }
2970
2971 /*
2972 * Create a table with enough space for all interfaces, and copy the
2973 * superclass' table in.
2974 */
2975 clazz->iftable = (InterfaceEntry*) dvmLinearAlloc(clazz->classLoader,
2976 sizeof(InterfaceEntry) * ifCount);
2977 zapIftable = true;
2978 memset(clazz->iftable, 0x00, sizeof(InterfaceEntry) * ifCount);
2979 if (superIfCount != 0) {
2980 memcpy(clazz->iftable, clazz->super->iftable,
2981 sizeof(InterfaceEntry) * superIfCount);
2982 }
2983
2984 /*
2985 * Create a flattened interface hierarchy of our immediate interfaces.
2986 */
2987 idx = superIfCount;
2988
2989 for (i = 0; i < clazz->interfaceCount; i++) {
2990 ClassObject* interf;
2991 int j;
2992
2993 interf = clazz->interfaces[i];
2994 assert(interf != NULL);
2995
2996 /* make sure this is still an interface class */
2997 if (!dvmIsInterfaceClass(interf)) {
2998 LOGW("Class '%s' implements non-interface '%s'\n",
2999 clazz->descriptor, interf->descriptor);
3000 dvmThrowExceptionWithClassMessage(
3001 "Ljava/lang/IncompatibleClassChangeError;",
3002 clazz->descriptor);
3003 goto bail;
3004 }
3005
3006 /* add entry for this interface */
3007 clazz->iftable[idx++].clazz = interf;
3008
3009 /* add entries for the interface's superinterfaces */
3010 for (j = 0; j < interf->iftableCount; j++) {
3011 clazz->iftable[idx++].clazz = interf->iftable[j].clazz;
3012 }
3013 }
3014
3015 assert(idx == ifCount);
3016
3017 if (false) {
3018 /*
3019 * Remove anything redundant from our recent additions. Note we have
3020 * to traverse the recent adds when looking for duplicates, because
3021 * it's possible the recent additions are self-redundant. This
3022 * reduces the memory footprint of classes with lots of inherited
3023 * interfaces.
3024 *
3025 * (I don't know if this will cause problems later on when we're trying
3026 * to find a static field. It looks like the proper search order is
3027 * (1) current class, (2) interfaces implemented by current class,
3028 * (3) repeat with superclass. A field implemented by an interface
3029 * and by a superclass might come out wrong if the superclass also
3030 * implements the interface. The javac compiler will reject the
3031 * situation as ambiguous, so the concern is somewhat artificial.)
3032 *
3033 * UPDATE: this makes ReferenceType.Interfaces difficult to implement,
3034 * because it wants to return just the interfaces declared to be
3035 * implemented directly by the class. I'm excluding this code for now.
3036 */
3037 for (i = superIfCount; i < ifCount; i++) {
3038 int j;
3039
3040 for (j = 0; j < ifCount; j++) {
3041 if (i == j)
3042 continue;
3043 if (clazz->iftable[i].clazz == clazz->iftable[j].clazz) {
3044 LOGVV("INTF: redundant interface %s in %s\n",
3045 clazz->iftable[i].clazz->descriptor,
3046 clazz->descriptor);
3047
3048 if (i != ifCount-1)
3049 memmove(&clazz->iftable[i], &clazz->iftable[i+1],
3050 (ifCount - i -1) * sizeof(InterfaceEntry));
3051 ifCount--;
3052 i--; // adjust for i++ above
3053 break;
3054 }
3055 }
3056 }
3057 LOGVV("INTF: class '%s' nodupes=%d\n", clazz->descriptor, ifCount);
3058 } // if (false)
3059
3060 clazz->iftableCount = ifCount;
3061
3062 /*
3063 * If we're an interface, we don't need the vtable pointers, so
3064 * we're done. If this class doesn't implement an interface that our
3065 * superclass doesn't have, then we again have nothing to do.
3066 */
3067 if (dvmIsInterfaceClass(clazz) || superIfCount == ifCount) {
3068 //dvmDumpClass(clazz, kDumpClassFullDetail);
3069 result = true;
3070 goto bail;
3071 }
3072
3073 /*
3074 * When we're handling invokeinterface, we probably have an object
3075 * whose type is an interface class rather than a concrete class. We
3076 * need to convert the method reference into a vtable index. So, for
3077 * every entry in "iftable", we create a list of vtable indices.
3078 *
3079 * Because our vtable encompasses the superclass vtable, we can use
3080 * the vtable indices from our superclass for all of the interfaces
3081 * that weren't directly implemented by us.
3082 *
3083 * Each entry in "iftable" has a pointer to the start of its set of
3084 * vtable offsets. The iftable entries in the superclass point to
3085 * storage allocated in the superclass, and the iftable entries added
3086 * for this class point to storage allocated in this class. "iftable"
3087 * is flat for fast access in a class and all of its subclasses, but
3088 * "ifviPool" is only created for the topmost implementor.
3089 */
3090 int poolSize = 0;
3091 for (i = superIfCount; i < ifCount; i++) {
3092 /*
3093 * Note it's valid for an interface to have no methods (e.g.
3094 * java/io/Serializable).
3095 */
3096 LOGVV("INTF: pool: %d from %s\n",
3097 clazz->iftable[i].clazz->virtualMethodCount,
3098 clazz->iftable[i].clazz->descriptor);
3099 poolSize += clazz->iftable[i].clazz->virtualMethodCount;
3100 }
3101
3102 if (poolSize == 0) {
3103 LOGVV("INTF: didn't find any new interfaces with methods\n");
3104 result = true;
3105 goto bail;
3106 }
3107
3108 clazz->ifviPoolCount = poolSize;
3109 clazz->ifviPool = (int*) dvmLinearAlloc(clazz->classLoader,
3110 poolSize * sizeof(int*));
3111 zapIfvipool = true;
3112
3113 /*
3114 * Fill in the vtable offsets for the interfaces that weren't part of
3115 * our superclass.
3116 */
3117 int poolOffset = 0;
3118 Method** mirandaList = NULL;
3119 int mirandaCount = 0, mirandaAlloc = 0;
3120
3121 for (i = superIfCount; i < ifCount; i++) {
3122 ClassObject* interface;
3123 int methIdx;
3124
3125 clazz->iftable[i].methodIndexArray = clazz->ifviPool + poolOffset;
3126 interface = clazz->iftable[i].clazz;
3127 poolOffset += interface->virtualMethodCount; // end here
3128
3129 /*
3130 * For each method listed in the interface's method list, find the
3131 * matching method in our class's method list. We want to favor the
3132 * subclass over the superclass, which just requires walking
3133 * back from the end of the vtable. (This only matters if the
3134 * superclass defines a private method and this class redefines
3135 * it -- otherwise it would use the same vtable slot. In Dalvik
3136 * those don't end up in the virtual method table, so it shouldn't
3137 * matter which direction we go. We walk it backward anyway.)
3138 *
3139 *
3140 * Suppose we have the following arrangement:
3141 * public interface MyInterface
3142 * public boolean inInterface();
3143 * public abstract class MirandaAbstract implements MirandaInterface
3144 * //public abstract boolean inInterface(); // not declared!
3145 * public boolean inAbstract() { stuff } // in vtable
3146 * public class MirandClass extends MirandaAbstract
3147 * public boolean inInterface() { stuff }
3148 * public boolean inAbstract() { stuff } // in vtable
3149 *
3150 * The javac compiler happily compiles MirandaAbstract even though
3151 * it doesn't declare all methods from its interface. When we try
3152 * to set up a vtable for MirandaAbstract, we find that we don't
3153 * have an slot for inInterface. To prevent this, we synthesize
3154 * abstract method declarations in MirandaAbstract.
3155 *
3156 * We have to expand vtable and update some things that point at it,
3157 * so we accumulate the method list and do it all at once below.
3158 */
3159 for (methIdx = 0; methIdx < interface->virtualMethodCount; methIdx++) {
3160 Method* imeth = &interface->virtualMethods[methIdx];
3161 int j;
3162
3163 IF_LOGVV() {
3164 char* desc = dexProtoCopyMethodDescriptor(&imeth->prototype);
3165 LOGVV("INTF: matching '%s' '%s'\n", imeth->name, desc);
3166 free(desc);
3167 }
3168
3169 for (j = clazz->vtableCount-1; j >= 0; j--) {
3170 if (dvmCompareMethodNamesAndProtos(imeth, clazz->vtable[j])
3171 == 0)
3172 {
3173 LOGVV("INTF: matched at %d\n", j);
3174 if (!dvmIsPublicMethod(clazz->vtable[j])) {
3175 LOGW("Implementation of %s.%s is not public\n",
3176 clazz->descriptor, clazz->vtable[j]->name);
3177 dvmThrowException("Ljava/lang/IllegalAccessError;",
3178 "interface implementation not public");
3179 goto bail;
3180 }
3181 clazz->iftable[i].methodIndexArray[methIdx] = j;
3182 break;
3183 }
3184 }
3185 if (j < 0) {
3186 IF_LOGV() {
3187 char* desc =
3188 dexProtoCopyMethodDescriptor(&imeth->prototype);
3189 LOGV("No match for '%s' '%s' in '%s' (creating miranda)\n",
3190 imeth->name, desc, clazz->descriptor);
3191 free(desc);
3192 }
3193 //dvmThrowException("Ljava/lang/RuntimeException;", "Miranda!");
3194 //return false;
3195
3196 if (mirandaCount == mirandaAlloc) {
3197 mirandaAlloc += 8;
3198 if (mirandaList == NULL) {
3199 mirandaList = dvmLinearAlloc(clazz->classLoader,
3200 mirandaAlloc * sizeof(Method*));
3201 } else {
3202 dvmLinearReadOnly(clazz->classLoader, mirandaList);
3203 mirandaList = dvmLinearRealloc(clazz->classLoader,
3204 mirandaList, mirandaAlloc * sizeof(Method*));
3205 }
3206 assert(mirandaList != NULL); // mem failed + we leaked
3207 }
3208
3209 /*
3210 * These may be redundant (e.g. method with same name and
3211 * signature declared in two interfaces implemented by the
3212 * same abstract class). We can squeeze the duplicates
3213 * out here.
3214 */
3215 int mir;
3216 for (mir = 0; mir < mirandaCount; mir++) {
3217 if (dvmCompareMethodNamesAndProtos(
3218 mirandaList[mir], imeth) == 0)
3219 {
3220 IF_LOGVV() {
3221 char* desc = dexProtoCopyMethodDescriptor(
3222 &imeth->prototype);
3223 LOGVV("MIRANDA dupe: %s and %s %s%s\n",
3224 mirandaList[mir]->clazz->descriptor,
3225 imeth->clazz->descriptor,
3226 imeth->name, desc);
3227 free(desc);
3228 }
3229 break;
3230 }
3231 }
3232
3233 /* point the iftable at a phantom slot index */
3234 clazz->iftable[i].methodIndexArray[methIdx] =
3235 clazz->vtableCount + mir;
3236 LOGVV("MIRANDA: %s points at slot %d\n",
3237 imeth->name, clazz->vtableCount + mir);
3238
3239 /* if non-duplicate among Mirandas, add to Miranda list */
3240 if (mir == mirandaCount) {
3241 //LOGV("MIRANDA: holding '%s' in slot %d\n",
3242 // imeth->name, mir);
3243 mirandaList[mirandaCount++] = imeth;
3244 }
3245 }
3246 }
3247 }
3248
3249 if (mirandaCount != 0) {
Andy McFadden68825972009-05-08 11:25:35 -07003250 static const int kManyMirandas = 150; /* arbitrary */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003251 Method* newVirtualMethods;
3252 Method* meth;
3253 int oldMethodCount, oldVtableCount;
3254
3255 for (i = 0; i < mirandaCount; i++) {
3256 LOGVV("MIRANDA %d: %s.%s\n", i,
3257 mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
3258 }
Andy McFadden68825972009-05-08 11:25:35 -07003259 if (mirandaCount > kManyMirandas) {
3260 /*
3261 * Some obfuscators like to create an interface with a huge
3262 * pile of methods, declare classes as implementing it, and then
3263 * only define a couple of methods. This leads to a rather
3264 * massive collection of Miranda methods and a lot of wasted
3265 * space, sometimes enough to blow out the LinearAlloc cap.
3266 */
3267 LOGD("Note: class %s has %d unimplemented (abstract) methods\n",
3268 clazz->descriptor, mirandaCount);
3269 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003270
3271 /*
3272 * We found methods in one or more interfaces for which we do not
3273 * have vtable entries. We have to expand our virtualMethods
3274 * table (which might be empty) to hold some new entries.
3275 */
3276 if (clazz->virtualMethods == NULL) {
3277 newVirtualMethods = (Method*) dvmLinearAlloc(clazz->classLoader,
3278 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3279 } else {
3280 //dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3281 newVirtualMethods = (Method*) dvmLinearRealloc(clazz->classLoader,
3282 clazz->virtualMethods,
3283 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3284 }
3285 if (newVirtualMethods != clazz->virtualMethods) {
3286 /*
3287 * Table was moved in memory. We have to run through the
3288 * vtable and fix the pointers. The vtable entries might be
3289 * pointing at superclasses, so we flip it around: run through
3290 * all locally-defined virtual methods, and fix their entries
3291 * in the vtable. (This would get really messy if sub-classes
3292 * had already been loaded.)
3293 *
3294 * Reminder: clazz->virtualMethods and clazz->virtualMethodCount
3295 * hold the virtual methods declared by this class. The
3296 * method's methodIndex is the vtable index, and is the same
3297 * for all sub-classes (and all super classes in which it is
3298 * defined). We're messing with these because the Miranda
3299 * stuff makes it look like the class actually has an abstract
3300 * method declaration in it.
3301 */
3302 LOGVV("MIRANDA fixing vtable pointers\n");
3303 dvmLinearReadWrite(clazz->classLoader, clazz->vtable);
3304 Method* meth = newVirtualMethods;
3305 for (i = 0; i < clazz->virtualMethodCount; i++, meth++)
3306 clazz->vtable[meth->methodIndex] = meth;
3307 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3308 }
3309
3310 oldMethodCount = clazz->virtualMethodCount;
3311 clazz->virtualMethods = newVirtualMethods;
3312 clazz->virtualMethodCount += mirandaCount;
3313
3314 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3315
3316 /*
3317 * We also have to expand the vtable.
3318 */
3319 assert(clazz->vtable != NULL);
3320 clazz->vtable = (Method**) dvmLinearRealloc(clazz->classLoader,
3321 clazz->vtable,
3322 sizeof(Method*) * (clazz->vtableCount + mirandaCount));
3323 if (clazz->vtable == NULL) {
3324 assert(false);
3325 goto bail;
3326 }
3327 zapVtable = true;
3328
3329 oldVtableCount = clazz->vtableCount;
3330 clazz->vtableCount += mirandaCount;
3331
3332 /*
3333 * Now we need to create the fake methods. We clone the abstract
3334 * method definition from the interface and then replace a few
3335 * things.
Andy McFadden68825972009-05-08 11:25:35 -07003336 *
3337 * The Method will be an "abstract native", with nativeFunc set to
3338 * dvmAbstractMethodStub().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003339 */
3340 meth = clazz->virtualMethods + oldMethodCount;
3341 for (i = 0; i < mirandaCount; i++, meth++) {
3342 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3343 cloneMethod(meth, mirandaList[i]);
3344 meth->clazz = clazz;
3345 meth->accessFlags |= ACC_MIRANDA;
3346 meth->methodIndex = (u2) (oldVtableCount + i);
3347 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3348
3349 /* point the new vtable entry at the new method */
3350 clazz->vtable[oldVtableCount + i] = meth;
3351 }
3352
3353 dvmLinearReadOnly(clazz->classLoader, mirandaList);
3354 dvmLinearFree(clazz->classLoader, mirandaList);
3355
3356 }
3357
3358 /*
3359 * TODO?
3360 * Sort the interfaces by number of declared methods. All we really
3361 * want is to get the interfaces with zero methods at the end of the
3362 * list, so that when we walk through the list during invoke-interface
3363 * we don't examine interfaces that can't possibly be useful.
3364 *
3365 * The set will usually be small, so a simple insertion sort works.
3366 *
3367 * We have to be careful not to change the order of two interfaces
3368 * that define the same method. (Not a problem if we only move the
3369 * zero-method interfaces to the end.)
3370 *
3371 * PROBLEM:
3372 * If we do this, we will no longer be able to identify super vs.
3373 * current class interfaces by comparing clazz->super->iftableCount. This
3374 * breaks anything that only wants to find interfaces declared directly
3375 * by the class (dvmFindStaticFieldHier, ReferenceType.Interfaces,
3376 * dvmDbgOutputAllInterfaces, etc). Need to provide a workaround.
3377 *
3378 * We can sort just the interfaces implemented directly by this class,
3379 * but that doesn't seem like it would provide much of an advantage. I'm
3380 * not sure this is worthwhile.
3381 *
3382 * (This has been made largely obsolete by the interface cache mechanism.)
3383 */
3384
3385 //dvmDumpClass(clazz);
3386
3387 result = true;
3388
3389bail:
3390 if (zapIftable)
3391 dvmLinearReadOnly(clazz->classLoader, clazz->iftable);
3392 if (zapVtable)
3393 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3394 if (zapIfvipool)
3395 dvmLinearReadOnly(clazz->classLoader, clazz->ifviPool);
3396 return result;
3397}
3398
3399
3400/*
3401 * Provide "stub" implementations for methods without them.
3402 *
3403 * Currently we provide an implementation for all abstract methods that
3404 * throws an AbstractMethodError exception. This allows us to avoid an
3405 * explicit check for abstract methods in every virtual call.
3406 *
3407 * NOTE: for Miranda methods, the method declaration is a clone of what
3408 * was found in the interface class. That copy may already have had the
3409 * function pointer filled in, so don't be surprised if it's not NULL.
3410 *
3411 * NOTE: this sets the "native" flag, giving us an "abstract native" method,
3412 * which is nonsensical. Need to make sure that this doesn't escape the
3413 * VM. We can either mask it out in reflection calls, or copy "native"
3414 * into the high 16 bits of accessFlags and check that internally.
3415 */
3416static bool insertMethodStubs(ClassObject* clazz)
3417{
3418 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3419
3420 Method* meth;
3421 int i;
3422
3423 meth = clazz->virtualMethods;
3424 for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
3425 if (dvmIsAbstractMethod(meth)) {
3426 assert(meth->insns == NULL);
3427 assert(meth->nativeFunc == NULL ||
3428 meth->nativeFunc == (DalvikBridgeFunc)dvmAbstractMethodStub);
3429
3430 meth->accessFlags |= ACC_NATIVE;
3431 meth->nativeFunc = (DalvikBridgeFunc) dvmAbstractMethodStub;
3432 }
3433 }
3434
3435 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3436 return true;
3437}
3438
3439
3440/*
3441 * Swap two instance fields.
3442 */
3443static inline void swapField(InstField* pOne, InstField* pTwo)
3444{
3445 InstField swap;
3446
3447 LOGVV(" --- swap '%s' and '%s'\n", pOne->field.name, pTwo->field.name);
3448 swap = *pOne;
3449 *pOne = *pTwo;
3450 *pTwo = swap;
3451}
3452
3453/*
3454 * Assign instance fields to u4 slots.
3455 *
3456 * The top portion of the instance field area is occupied by the superclass
3457 * fields, the bottom by the fields for this class.
3458 *
3459 * "long" and "double" fields occupy two adjacent slots. On some
3460 * architectures, 64-bit quantities must be 64-bit aligned, so we need to
3461 * arrange fields (or introduce padding) to ensure this. We assume the
3462 * fields of the topmost superclass (i.e. Object) are 64-bit aligned, so
3463 * we can just ensure that the offset is "even". To avoid wasting space,
3464 * we want to move non-reference 32-bit fields into gaps rather than
3465 * creating pad words.
3466 *
3467 * In the worst case we will waste 4 bytes, but because objects are
3468 * allocated on >= 64-bit boundaries, those bytes may well be wasted anyway
3469 * (assuming this is the most-derived class).
3470 *
3471 * Pad words are not represented in the field table, so the field table
3472 * itself does not change size.
3473 *
3474 * The number of field slots determines the size of the object, so we
3475 * set that here too.
3476 *
3477 * This function feels a little more complicated than I'd like, but it
3478 * has the property of moving the smallest possible set of fields, which
3479 * should reduce the time required to load a class.
3480 *
3481 * NOTE: reference fields *must* come first, or precacheReferenceOffsets()
3482 * will break.
3483 */
3484static bool computeFieldOffsets(ClassObject* clazz)
3485{
3486 int fieldOffset;
3487 int i, j;
3488
3489 dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
3490
3491 if (clazz->super != NULL)
3492 fieldOffset = clazz->super->objectSize;
3493 else
3494 fieldOffset = offsetof(DataObject, instanceData);
3495
3496 LOGVV("--- computeFieldOffsets '%s'\n", clazz->descriptor);
3497
3498 //LOGI("OFFSETS fieldCount=%d\n", clazz->ifieldCount);
3499 //LOGI("dataobj, instance: %d\n", offsetof(DataObject, instanceData));
3500 //LOGI("classobj, access: %d\n", offsetof(ClassObject, accessFlags));
3501 //LOGI("super=%p, fieldOffset=%d\n", clazz->super, fieldOffset);
3502
3503 /*
3504 * Start by moving all reference fields to the front.
3505 */
3506 clazz->ifieldRefCount = 0;
3507 j = clazz->ifieldCount - 1;
3508 for (i = 0; i < clazz->ifieldCount; i++) {
3509 InstField* pField = &clazz->ifields[i];
3510 char c = pField->field.signature[0];
3511
3512 if (c != '[' && c != 'L') {
3513 /* This isn't a reference field; see if any reference fields
3514 * follow this one. If so, we'll move it to this position.
3515 * (quicksort-style partitioning)
3516 */
3517 while (j > i) {
3518 InstField* refField = &clazz->ifields[j--];
3519 char rc = refField->field.signature[0];
3520
3521 if (rc == '[' || rc == 'L') {
3522 /* Here's a reference field that follows at least one
3523 * non-reference field. Swap it with the current field.
3524 * (When this returns, "pField" points to the reference
3525 * field, and "refField" points to the non-ref field.)
3526 */
3527 swapField(pField, refField);
3528
3529 /* Fix the signature.
3530 */
3531 c = rc;
3532
3533 clazz->ifieldRefCount++;
3534 break;
3535 }
3536 }
3537 /* We may or may not have swapped a field.
3538 */
3539 } else {
3540 /* This is a reference field.
3541 */
3542 clazz->ifieldRefCount++;
3543 }
3544
3545 /*
3546 * If we've hit the end of the reference fields, break.
3547 */
3548 if (c != '[' && c != 'L')
3549 break;
3550
3551 pField->byteOffset = fieldOffset;
3552 fieldOffset += sizeof(u4);
3553 LOGVV(" --- offset1 '%s'=%d\n", pField->field.name,pField->byteOffset);
3554 }
3555
3556 /*
3557 * Now we want to pack all of the double-wide fields together. If we're
3558 * not aligned, though, we want to shuffle one 32-bit field into place.
3559 * If we can't find one, we'll have to pad it.
3560 */
3561 if (i != clazz->ifieldCount && (fieldOffset & 0x04) != 0) {
3562 LOGVV(" +++ not aligned\n");
3563
3564 InstField* pField = &clazz->ifields[i];
3565 char c = pField->field.signature[0];
3566
3567 if (c != 'J' && c != 'D') {
3568 /*
3569 * The field that comes next is 32-bit, so just advance past it.
3570 */
3571 assert(c != '[' && c != 'L');
3572 pField->byteOffset = fieldOffset;
3573 fieldOffset += sizeof(u4);
3574 i++;
3575 LOGVV(" --- offset2 '%s'=%d\n",
3576 pField->field.name, pField->byteOffset);
3577 } else {
3578 /*
3579 * Next field is 64-bit, so search for a 32-bit field we can
3580 * swap into it.
3581 */
3582 bool found = false;
3583 j = clazz->ifieldCount - 1;
3584 while (j > i) {
3585 InstField* singleField = &clazz->ifields[j--];
3586 char rc = singleField->field.signature[0];
3587
3588 if (rc != 'J' && rc != 'D') {
3589 swapField(pField, singleField);
3590 //c = rc;
3591 LOGVV(" +++ swapped '%s' for alignment\n",
3592 pField->field.name);
3593 pField->byteOffset = fieldOffset;
3594 fieldOffset += sizeof(u4);
3595 LOGVV(" --- offset3 '%s'=%d\n",
3596 pField->field.name, pField->byteOffset);
3597 found = true;
3598 i++;
3599 break;
3600 }
3601 }
3602 if (!found) {
3603 LOGV(" +++ inserting pad field in '%s'\n", clazz->descriptor);
3604 fieldOffset += sizeof(u4);
3605 }
3606 }
3607 }
3608
3609 /*
3610 * Alignment is good, shuffle any double-wide fields forward, and
3611 * finish assigning field offsets to all fields.
3612 */
3613 assert(i == clazz->ifieldCount || (fieldOffset & 0x04) == 0);
3614 j = clazz->ifieldCount - 1;
3615 for ( ; i < clazz->ifieldCount; i++) {
3616 InstField* pField = &clazz->ifields[i];
3617 char c = pField->field.signature[0];
3618
3619 if (c != 'D' && c != 'J') {
3620 /* This isn't a double-wide field; see if any double fields
3621 * follow this one. If so, we'll move it to this position.
3622 * (quicksort-style partitioning)
3623 */
3624 while (j > i) {
3625 InstField* doubleField = &clazz->ifields[j--];
3626 char rc = doubleField->field.signature[0];
3627
3628 if (rc == 'D' || rc == 'J') {
3629 /* Here's a double-wide field that follows at least one
3630 * non-double field. Swap it with the current field.
3631 * (When this returns, "pField" points to the reference
3632 * field, and "doubleField" points to the non-double field.)
3633 */
3634 swapField(pField, doubleField);
3635 c = rc;
3636
3637 break;
3638 }
3639 }
3640 /* We may or may not have swapped a field.
3641 */
3642 } else {
3643 /* This is a double-wide field, leave it be.
3644 */
3645 }
3646
3647 pField->byteOffset = fieldOffset;
3648 LOGVV(" --- offset4 '%s'=%d\n", pField->field.name,pField->byteOffset);
3649 fieldOffset += sizeof(u4);
3650 if (c == 'J' || c == 'D')
3651 fieldOffset += sizeof(u4);
3652 }
3653
3654#ifndef NDEBUG
3655 /* Make sure that all reference fields appear before
3656 * non-reference fields, and all double-wide fields are aligned.
3657 */
3658 j = 0; // seen non-ref
3659 for (i = 0; i < clazz->ifieldCount; i++) {
3660 InstField *pField = &clazz->ifields[i];
3661 char c = pField->field.signature[0];
3662
3663 if (c == 'D' || c == 'J') {
3664 assert((pField->byteOffset & 0x07) == 0);
3665 }
3666
3667 if (c != '[' && c != 'L') {
3668 if (!j) {
3669 assert(i == clazz->ifieldRefCount);
3670 j = 1;
3671 }
3672 } else if (j) {
3673 assert(false);
3674 }
3675 }
3676 if (!j) {
3677 assert(clazz->ifieldRefCount == clazz->ifieldCount);
3678 }
3679#endif
3680
3681 /*
3682 * We map a C struct directly on top of java/lang/Class objects. Make
3683 * sure we left enough room for the instance fields.
3684 */
3685 assert(clazz != gDvm.classJavaLangClass || (size_t)fieldOffset <
3686 offsetof(ClassObject, instanceData) + sizeof(clazz->instanceData));
3687
3688 clazz->objectSize = fieldOffset;
3689
3690 dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
3691 return true;
3692}
3693
3694/*
3695 * Throw the VM-spec-mandated error when an exception is thrown during
3696 * class initialization.
3697 *
3698 * The safest way to do this is to call the ExceptionInInitializerError
3699 * constructor that takes a Throwable.
3700 *
3701 * [Do we want to wrap it if the original is an Error rather than
3702 * an Exception?]
3703 */
3704static void throwClinitError(void)
3705{
3706 Thread* self = dvmThreadSelf();
3707 Object* exception;
3708 Object* eiie;
3709
3710 exception = dvmGetException(self);
3711 dvmAddTrackedAlloc(exception, self);
3712 dvmClearException(self);
3713
3714 if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3715 /*
3716 * Always resolves to same thing -- no race condition.
3717 */
3718 gDvm.classJavaLangExceptionInInitializerError =
3719 dvmFindSystemClass(
3720 "Ljava/lang/ExceptionInInitializerError;");
3721 if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3722 LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3723 goto fail;
3724 }
3725
3726 gDvm.methJavaLangExceptionInInitializerError_init =
3727 dvmFindDirectMethodByDescriptor(gDvm.classJavaLangExceptionInInitializerError,
3728 "<init>", "(Ljava/lang/Throwable;)V");
3729 if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) {
3730 LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3731 goto fail;
3732 }
3733 }
3734
3735 eiie = dvmAllocObject(gDvm.classJavaLangExceptionInInitializerError,
3736 ALLOC_DEFAULT);
3737 if (eiie == NULL)
3738 goto fail;
3739
3740 /*
3741 * Construct the new object, and replace the exception with it.
3742 */
3743 JValue unused;
3744 dvmCallMethod(self, gDvm.methJavaLangExceptionInInitializerError_init,
3745 eiie, &unused, exception);
3746 dvmSetException(self, eiie);
3747 dvmReleaseTrackedAlloc(eiie, NULL);
3748 dvmReleaseTrackedAlloc(exception, self);
3749 return;
3750
3751fail: /* restore original exception */
3752 dvmSetException(self, exception);
3753 dvmReleaseTrackedAlloc(exception, self);
3754 return;
3755}
3756
3757/*
3758 * The class failed to initialize on a previous attempt, so we want to throw
3759 * a NoClassDefFoundError (v2 2.17.5). The exception to this rule is if we
3760 * failed in verification, in which case v2 5.4.1 says we need to re-throw
3761 * the previous error.
3762 */
3763static void throwEarlierClassFailure(ClassObject* clazz)
3764{
3765 LOGI("Rejecting re-init on previously-failed class %s v=%p\n",
3766 clazz->descriptor, clazz->verifyErrorClass);
3767
3768 if (clazz->verifyErrorClass == NULL) {
3769 dvmThrowExceptionWithClassMessage("Ljava/lang/NoClassDefFoundError;",
3770 clazz->descriptor);
3771 } else {
3772 dvmThrowExceptionByClassWithClassMessage(clazz->verifyErrorClass,
3773 clazz->descriptor);
3774 }
3775}
3776
3777/*
3778 * Initialize any static fields whose values are stored in
3779 * the DEX file. This must be done during class initialization.
3780 */
3781static void initSFields(ClassObject* clazz)
3782{
3783 Thread* self = dvmThreadSelf(); /* for dvmReleaseTrackedAlloc() */
3784 DexFile* pDexFile;
3785 const DexClassDef* pClassDef;
3786 const DexEncodedArray* pValueList;
3787 EncodedArrayIterator iterator;
3788 int i;
3789
3790 if (clazz->sfieldCount == 0) {
3791 return;
3792 }
3793 if (clazz->pDvmDex == NULL) {
3794 /* generated class; any static fields should already be set up */
3795 LOGV("Not initializing static fields in %s\n", clazz->descriptor);
3796 return;
3797 }
3798 pDexFile = clazz->pDvmDex->pDexFile;
3799
3800 pClassDef = dexFindClass(pDexFile, clazz->descriptor);
3801 assert(pClassDef != NULL);
3802
3803 pValueList = dexGetStaticValuesList(pDexFile, pClassDef);
3804 if (pValueList == NULL) {
3805 return;
3806 }
3807
3808 dvmEncodedArrayIteratorInitialize(&iterator, pValueList, clazz);
3809
3810 /*
3811 * Iterate over the initial values array, setting the corresponding
3812 * static field for each array element.
3813 */
3814
3815 for (i = 0; dvmEncodedArrayIteratorHasNext(&iterator); i++) {
3816 AnnotationValue value;
3817 bool parsed = dvmEncodedArrayIteratorGetNext(&iterator, &value);
3818 StaticField* sfield = &clazz->sfields[i];
3819 const char* descriptor = sfield->field.signature;
Barry Hayes364f9d92010-06-11 16:12:47 -07003820 bool isObj = false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003821
3822 if (! parsed) {
3823 /*
3824 * TODO: Eventually verification should attempt to ensure
3825 * that this can't happen at least due to a data integrity
3826 * problem.
3827 */
3828 LOGE("Static initializer parse failed for %s at index %d",
3829 clazz->descriptor, i);
3830 dvmAbort();
3831 }
3832
3833 /* Verify that the value we got was of a valid type. */
3834
3835 switch (descriptor[0]) {
3836 case 'Z': parsed = (value.type == kDexAnnotationBoolean); break;
3837 case 'B': parsed = (value.type == kDexAnnotationByte); break;
3838 case 'C': parsed = (value.type == kDexAnnotationChar); break;
3839 case 'S': parsed = (value.type == kDexAnnotationShort); break;
3840 case 'I': parsed = (value.type == kDexAnnotationInt); break;
3841 case 'J': parsed = (value.type == kDexAnnotationLong); break;
3842 case 'F': parsed = (value.type == kDexAnnotationFloat); break;
3843 case 'D': parsed = (value.type == kDexAnnotationDouble); break;
3844 case '[': parsed = (value.type == kDexAnnotationNull); break;
3845 case 'L': {
3846 switch (value.type) {
3847 case kDexAnnotationNull: {
3848 /* No need for further tests. */
3849 break;
3850 }
3851 case kDexAnnotationString: {
3852 parsed =
3853 (strcmp(descriptor, "Ljava/lang/String;") == 0);
Barry Hayes364f9d92010-06-11 16:12:47 -07003854 isObj = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003855 break;
3856 }
3857 case kDexAnnotationType: {
3858 parsed =
3859 (strcmp(descriptor, "Ljava/lang/Class;") == 0);
Barry Hayes364f9d92010-06-11 16:12:47 -07003860 isObj = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003861 break;
3862 }
3863 default: {
3864 parsed = false;
3865 break;
3866 }
3867 }
3868 break;
3869 }
3870 default: {
3871 parsed = false;
3872 break;
3873 }
3874 }
3875
3876 if (parsed) {
3877 /*
Barry Hayes364f9d92010-06-11 16:12:47 -07003878 * All's well, so store the value.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003879 */
Barry Hayes364f9d92010-06-11 16:12:47 -07003880 if (isObj) {
3881 dvmSetStaticFieldObject(sfield, value.value.l);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003882 dvmReleaseTrackedAlloc(value.value.l, self);
Barry Hayes364f9d92010-06-11 16:12:47 -07003883 } else {
3884 /*
3885 * Note: This always stores the full width of a
3886 * JValue, even though most of the time only the first
3887 * word is needed.
3888 */
3889 sfield->value = value.value;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003890 }
3891 } else {
3892 /*
3893 * Something up above had a problem. TODO: See comment
3894 * above the switch about verfication.
3895 */
3896 LOGE("Bogus static initialization: value type %d in field type "
3897 "%s for %s at index %d",
3898 value.type, descriptor, clazz->descriptor, i);
3899 dvmAbort();
3900 }
3901 }
3902}
3903
3904
3905/*
3906 * Determine whether "descriptor" yields the same class object in the
3907 * context of clazz1 and clazz2.
3908 *
3909 * The caller must hold gDvm.loadedClasses.
3910 *
3911 * Returns "true" if they match.
3912 */
3913static bool compareDescriptorClasses(const char* descriptor,
3914 const ClassObject* clazz1, const ClassObject* clazz2)
3915{
3916 ClassObject* result1;
3917 ClassObject* result2;
3918
3919 /*
3920 * Do the first lookup by name.
3921 */
3922 result1 = dvmFindClassNoInit(descriptor, clazz1->classLoader);
3923
3924 /*
3925 * We can skip a second lookup by name if the second class loader is
3926 * in the initiating loader list of the class object we retrieved.
3927 * (This means that somebody already did a lookup of this class through
3928 * the second loader, and it resolved to the same class.) If it's not
3929 * there, we may simply not have had an opportunity to add it yet, so
3930 * we do the full lookup.
3931 *
3932 * The initiating loader test should catch the majority of cases
3933 * (in particular, the zillions of references to String/Object).
3934 *
3935 * Unfortunately we're still stuck grabbing a mutex to do the lookup.
3936 *
3937 * For this to work, the superclass/interface should be the first
3938 * argument, so that way if it's from the bootstrap loader this test
3939 * will work. (The bootstrap loader, by definition, never shows up
3940 * as the initiating loader of a class defined by some other loader.)
3941 */
3942 dvmHashTableLock(gDvm.loadedClasses);
3943 bool isInit = dvmLoaderInInitiatingList(result1, clazz2->classLoader);
3944 dvmHashTableUnlock(gDvm.loadedClasses);
3945
3946 if (isInit) {
3947 //printf("%s(obj=%p) / %s(cl=%p): initiating\n",
3948 // result1->descriptor, result1,
3949 // clazz2->descriptor, clazz2->classLoader);
3950 return true;
3951 } else {
3952 //printf("%s(obj=%p) / %s(cl=%p): RAW\n",
3953 // result1->descriptor, result1,
3954 // clazz2->descriptor, clazz2->classLoader);
3955 result2 = dvmFindClassNoInit(descriptor, clazz2->classLoader);
3956 }
3957
3958 if (result1 == NULL || result2 == NULL) {
3959 dvmClearException(dvmThreadSelf());
3960 if (result1 == result2) {
3961 /*
3962 * Neither class loader could find this class. Apparently it
3963 * doesn't exist.
3964 *
3965 * We can either throw some sort of exception now, or just
3966 * assume that it'll fail later when something actually tries
3967 * to use the class. For strict handling we should throw now,
3968 * because a "tricky" class loader could start returning
3969 * something later, and a pair of "tricky" loaders could set
3970 * us up for confusion.
3971 *
3972 * I'm not sure if we're allowed to complain about nonexistent
3973 * classes in method signatures during class init, so for now
3974 * this will just return "true" and let nature take its course.
3975 */
3976 return true;
3977 } else {
3978 /* only one was found, so clearly they're not the same */
3979 return false;
3980 }
3981 }
3982
3983 return result1 == result2;
3984}
3985
3986/*
3987 * For every component in the method descriptor, resolve the class in the
3988 * context of the two classes and compare the results.
3989 *
3990 * For best results, the "superclass" class should be first.
3991 *
3992 * Returns "true" if the classes match, "false" otherwise.
3993 */
3994static bool checkMethodDescriptorClasses(const Method* meth,
3995 const ClassObject* clazz1, const ClassObject* clazz2)
3996{
3997 DexParameterIterator iterator;
3998 const char* descriptor;
3999
4000 /* walk through the list of parameters */
4001 dexParameterIteratorInit(&iterator, &meth->prototype);
4002 while (true) {
4003 descriptor = dexParameterIteratorNextDescriptor(&iterator);
4004
4005 if (descriptor == NULL)
4006 break;
4007
4008 if (descriptor[0] == 'L' || descriptor[0] == '[') {
4009 /* non-primitive type */
4010 if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4011 return false;
4012 }
4013 }
4014
4015 /* check the return type */
4016 descriptor = dexProtoGetReturnType(&meth->prototype);
4017 if (descriptor[0] == 'L' || descriptor[0] == '[') {
4018 if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4019 return false;
4020 }
4021 return true;
4022}
4023
4024/*
4025 * Validate the descriptors in the superclass and interfaces.
4026 *
4027 * What we need to do is ensure that the classes named in the method
4028 * descriptors in our ancestors and ourselves resolve to the same class
Andy McFaddencab8be02009-05-26 13:39:57 -07004029 * objects. We can get conflicts when the classes come from different
4030 * class loaders, and the resolver comes up with different results for
4031 * the same class name in different contexts.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004032 *
Andy McFaddencab8be02009-05-26 13:39:57 -07004033 * An easy way to cause the problem is to declare a base class that uses
4034 * class Foo in a method signature (e.g. as the return type). Then,
4035 * define a subclass and a different version of Foo, and load them from a
4036 * different class loader. If the subclass overrides the method, it will
4037 * have a different concept of what Foo is than its parent does, so even
4038 * though the method signature strings are identical, they actually mean
4039 * different things.
4040 *
4041 * A call to the method through a base-class reference would be treated
4042 * differently than a call to the method through a subclass reference, which
4043 * isn't the way polymorphism works, so we have to reject the subclass.
4044 * If the subclass doesn't override the base method, then there's no
4045 * problem, because calls through base-class references and subclass
4046 * references end up in the same place.
4047 *
4048 * We don't need to check to see if an interface's methods match with its
4049 * superinterface's methods, because you can't instantiate an interface
4050 * and do something inappropriate with it. If interface I1 extends I2
4051 * and is implemented by C, and I1 and I2 are in separate class loaders
4052 * and have conflicting views of other classes, we will catch the conflict
4053 * when we process C. Anything that implements I1 is doomed to failure,
4054 * but we don't need to catch that while processing I1.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004055 *
4056 * On failure, throws an exception and returns "false".
4057 */
4058static bool validateSuperDescriptors(const ClassObject* clazz)
4059{
4060 int i;
4061
4062 if (dvmIsInterfaceClass(clazz))
4063 return true;
4064
4065 /*
4066 * Start with the superclass-declared methods.
4067 */
4068 if (clazz->super != NULL &&
4069 clazz->classLoader != clazz->super->classLoader)
4070 {
4071 /*
Andy McFaddencab8be02009-05-26 13:39:57 -07004072 * Walk through every overridden method and compare resolved
4073 * descriptor components. We pull the Method structs out of
4074 * the vtable. It doesn't matter whether we get the struct from
4075 * the parent or child, since we just need the UTF-8 descriptor,
4076 * which must match.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004077 *
4078 * We need to do this even for the stuff inherited from Object,
4079 * because it's possible that the new class loader has redefined
4080 * a basic class like String.
Andy McFaddene7b30942009-05-27 12:42:38 -07004081 *
4082 * We don't need to check stuff defined in a superclass because
4083 * it was checked when the superclass was loaded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004084 */
4085 const Method* meth;
4086
4087 //printf("Checking %s %p vs %s %p\n",
4088 // clazz->descriptor, clazz->classLoader,
4089 // clazz->super->descriptor, clazz->super->classLoader);
4090 for (i = clazz->super->vtableCount - 1; i >= 0; i--) {
4091 meth = clazz->vtable[i];
Andy McFaddencab8be02009-05-26 13:39:57 -07004092 if (meth != clazz->super->vtable[i] &&
4093 !checkMethodDescriptorClasses(meth, clazz->super, clazz))
4094 {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004095 LOGW("Method mismatch: %s in %s (cl=%p) and super %s (cl=%p)\n",
4096 meth->name, clazz->descriptor, clazz->classLoader,
4097 clazz->super->descriptor, clazz->super->classLoader);
4098 dvmThrowException("Ljava/lang/LinkageError;",
4099 "Classes resolve differently in superclass");
4100 return false;
4101 }
4102 }
4103 }
4104
4105 /*
Andy McFaddene7b30942009-05-27 12:42:38 -07004106 * Check the methods defined by this class against the interfaces it
4107 * implements. If we inherited the implementation from a superclass,
4108 * we have to check it against the superclass (which might be in a
4109 * different class loader). If the superclass also implements the
4110 * interface, we could skip the check since by definition it was
4111 * performed when the class was loaded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004112 */
4113 for (i = 0; i < clazz->iftableCount; i++) {
4114 const InterfaceEntry* iftable = &clazz->iftable[i];
4115
4116 if (clazz->classLoader != iftable->clazz->classLoader) {
4117 const ClassObject* iface = iftable->clazz;
4118 int j;
4119
4120 for (j = 0; j < iface->virtualMethodCount; j++) {
4121 const Method* meth;
4122 int vtableIndex;
4123
4124 vtableIndex = iftable->methodIndexArray[j];
4125 meth = clazz->vtable[vtableIndex];
4126
Andy McFaddene7b30942009-05-27 12:42:38 -07004127 if (!checkMethodDescriptorClasses(meth, iface, meth->clazz)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004128 LOGW("Method mismatch: %s in %s (cl=%p) and "
4129 "iface %s (cl=%p)\n",
4130 meth->name, clazz->descriptor, clazz->classLoader,
4131 iface->descriptor, iface->classLoader);
4132 dvmThrowException("Ljava/lang/LinkageError;",
4133 "Classes resolve differently in interface");
4134 return false;
4135 }
4136 }
4137 }
4138 }
4139
4140 return true;
4141}
4142
4143/*
4144 * Returns true if the class is being initialized by us (which means that
4145 * calling dvmInitClass will return immediately after fiddling with locks).
4146 *
4147 * There isn't a race here, because either clazz->initThreadId won't match
4148 * us, or it will and it was set in the same thread.
4149 */
4150bool dvmIsClassInitializing(const ClassObject* clazz)
4151{
4152 return (clazz->status == CLASS_INITIALIZING &&
4153 clazz->initThreadId == dvmThreadSelf()->threadId);
4154}
4155
4156/*
4157 * If a class has not been initialized, do so by executing the code in
4158 * <clinit>. The sequence is described in the VM spec v2 2.17.5.
4159 *
4160 * It is possible for multiple threads to arrive here simultaneously, so
4161 * we need to lock the class while we check stuff. We know that no
4162 * interpreted code has access to the class yet, so we can use the class's
4163 * monitor lock.
4164 *
4165 * We will often be called recursively, e.g. when the <clinit> code resolves
4166 * one of its fields, the field resolution will try to initialize the class.
Andy McFadden77514ab2010-05-06 13:39:07 -07004167 * In that case we will return "true" even though the class isn't actually
4168 * ready to go. The ambiguity can be resolved with dvmIsClassInitializing().
4169 * (TODO: consider having this return an enum to avoid the extra call --
4170 * return -1 on failure, 0 on success, 1 on still-initializing. Looks like
4171 * dvmIsClassInitializing() is always paired with *Initialized())
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004172 *
4173 * This can get very interesting if a class has a static field initialized
4174 * to a new instance of itself. <clinit> will end up calling <init> on
4175 * the members it is initializing, which is fine unless it uses the contents
4176 * of static fields to initialize instance fields. This will leave the
4177 * static-referenced objects in a partially initialized state. This is
4178 * reasonably rare and can sometimes be cured with proper field ordering.
4179 *
4180 * On failure, returns "false" with an exception raised.
4181 *
4182 * -----
4183 *
4184 * It is possible to cause a deadlock by having a situation like this:
4185 * class A { static { sleep(10000); new B(); } }
4186 * class B { static { sleep(10000); new A(); } }
4187 * new Thread() { public void run() { new A(); } }.start();
4188 * new Thread() { public void run() { new B(); } }.start();
4189 * This appears to be expected under the spec.
4190 *
4191 * The interesting question is what to do if somebody calls Thread.interrupt()
4192 * on one of the deadlocked threads. According to the VM spec, they're both
4193 * sitting in "wait". Should the interrupt code quietly raise the
4194 * "interrupted" flag, or should the "wait" return immediately with an
4195 * exception raised?
4196 *
4197 * This gets a little murky. The VM spec says we call "wait", and the
4198 * spec for Thread.interrupt says Object.wait is interruptible. So it
4199 * seems that, if we get unlucky and interrupt class initialization, we
4200 * are expected to throw (which gets converted to ExceptionInInitializerError
4201 * since InterruptedException is checked).
4202 *
4203 * There are a couple of problems here. First, all threads are expected to
4204 * present a consistent view of class initialization, so we can't have it
4205 * fail in one thread and succeed in another. Second, once a class fails
4206 * to initialize, it must *always* fail. This means that a stray interrupt()
4207 * call could render a class unusable for the lifetime of the VM.
4208 *
4209 * In most cases -- the deadlock example above being a counter-example --
4210 * the interrupting thread can't tell whether the target thread handled
4211 * the initialization itself or had to wait while another thread did the
4212 * work. Refusing to interrupt class initialization is, in most cases,
4213 * not something that a program can reliably detect.
4214 *
4215 * On the assumption that interrupting class initialization is highly
4216 * undesirable in most circumstances, and that failing to do so does not
4217 * deviate from the spec in a meaningful way, we don't allow class init
4218 * to be interrupted by Thread.interrupt().
4219 */
4220bool dvmInitClass(ClassObject* clazz)
4221{
4222#if LOG_CLASS_LOADING
4223 bool initializedByUs = false;
4224#endif
4225
4226 Thread* self = dvmThreadSelf();
4227 const Method* method;
4228
4229 dvmLockObject(self, (Object*) clazz);
4230 assert(dvmIsClassLinked(clazz) || clazz->status == CLASS_ERROR);
4231
4232 /*
4233 * If the class hasn't been verified yet, do so now.
4234 */
4235 if (clazz->status < CLASS_VERIFIED) {
4236 /*
4237 * If we're in an "erroneous" state, throw an exception and bail.
4238 */
4239 if (clazz->status == CLASS_ERROR) {
4240 throwEarlierClassFailure(clazz);
4241 goto bail_unlock;
4242 }
4243
4244 assert(clazz->status == CLASS_RESOLVED);
4245 assert(!IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4246
4247 if (gDvm.classVerifyMode == VERIFY_MODE_NONE ||
4248 (gDvm.classVerifyMode == VERIFY_MODE_REMOTE &&
4249 clazz->classLoader == NULL))
4250 {
Andy McFaddend22748a2010-04-22 17:08:11 -07004251 /* advance to "verified" state */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004252 LOGV("+++ not verifying class %s (cl=%p)\n",
4253 clazz->descriptor, clazz->classLoader);
Andy McFaddend22748a2010-04-22 17:08:11 -07004254 clazz->status = CLASS_VERIFIED;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004255 goto noverify;
4256 }
4257
4258 if (!gDvm.optimizing)
4259 LOGV("+++ late verify on %s\n", clazz->descriptor);
4260
4261 /*
4262 * We're not supposed to optimize an unverified class, but during
4263 * development this mode was useful. We can't verify an optimized
4264 * class because the optimization process discards information.
4265 */
4266 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) {
4267 LOGW("Class '%s' was optimized without verification; "
4268 "not verifying now\n",
4269 clazz->descriptor);
4270 LOGW(" ('rm /data/dalvik-cache/*' and restart to fix this)");
4271 goto verify_failed;
4272 }
4273
4274 clazz->status = CLASS_VERIFYING;
Andy McFadden228a6b02010-05-04 15:02:32 -07004275 if (!dvmVerifyClass(clazz)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004276verify_failed:
4277 dvmThrowExceptionWithClassMessage("Ljava/lang/VerifyError;",
4278 clazz->descriptor);
Andy McFaddenfb119e62010-06-28 16:21:20 -07004279 dvmSetFieldObject((Object*) clazz,
4280 offsetof(ClassObject, verifyErrorClass),
4281 (Object*) dvmGetException(self)->clazz);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004282 clazz->status = CLASS_ERROR;
4283 goto bail_unlock;
4284 }
4285
4286 clazz->status = CLASS_VERIFIED;
4287 }
4288noverify:
4289
Andy McFaddenfb119e62010-06-28 16:21:20 -07004290 /*
4291 * We need to ensure that certain instructions, notably accesses to
4292 * volatile fields, are replaced before any code is executed. This
4293 * must happen even if DEX optimizations are disabled.
4294 */
4295 if (!IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) {
4296 LOGV("+++ late optimize on %s (pv=%d)\n",
4297 clazz->descriptor, IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4298 dvmOptimizeClass(clazz, true);
4299 SET_CLASS_FLAG(clazz, CLASS_ISOPTIMIZED);
4300 }
4301
Andy McFaddenfb119e62010-06-28 16:21:20 -07004302 /* update instruction stream now that verification + optimization is done */
Andy McFaddend22748a2010-04-22 17:08:11 -07004303 dvmFlushBreakpoints(clazz);
Andy McFaddend22748a2010-04-22 17:08:11 -07004304
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004305 if (clazz->status == CLASS_INITIALIZED)
4306 goto bail_unlock;
4307
4308 while (clazz->status == CLASS_INITIALIZING) {
4309 /* we caught somebody else in the act; was it us? */
4310 if (clazz->initThreadId == self->threadId) {
4311 //LOGV("HEY: found a recursive <clinit>\n");
4312 goto bail_unlock;
4313 }
4314
4315 if (dvmCheckException(self)) {
4316 LOGW("GLITCH: exception pending at start of class init\n");
4317 dvmAbort();
4318 }
4319
4320 /*
4321 * Wait for the other thread to finish initialization. We pass
4322 * "false" for the "interruptShouldThrow" arg so it doesn't throw
4323 * an exception on interrupt.
4324 */
4325 dvmObjectWait(self, (Object*) clazz, 0, 0, false);
4326
4327 /*
4328 * When we wake up, repeat the test for init-in-progress. If there's
4329 * an exception pending (only possible if "interruptShouldThrow"
4330 * was set), bail out.
4331 */
4332 if (dvmCheckException(self)) {
4333 LOGI("Class init of '%s' failing with wait() exception\n",
4334 clazz->descriptor);
4335 /*
4336 * TODO: this is bogus, because it means the two threads have a
4337 * different idea of the class status. We need to flag the
4338 * class as bad and ensure that the initializer thread respects
4339 * our notice. If we get lucky and wake up after the class has
4340 * finished initialization but before being woken, we have to
4341 * swallow the exception, perhaps raising thread->interrupted
4342 * to preserve semantics.
4343 *
4344 * Since we're not currently allowing interrupts, this should
4345 * never happen and we don't need to fix this.
4346 */
4347 assert(false);
4348 throwClinitError();
4349 clazz->status = CLASS_ERROR;
4350 goto bail_unlock;
4351 }
4352 if (clazz->status == CLASS_INITIALIZING) {
4353 LOGI("Waiting again for class init\n");
4354 continue;
4355 }
4356 assert(clazz->status == CLASS_INITIALIZED ||
4357 clazz->status == CLASS_ERROR);
4358 if (clazz->status == CLASS_ERROR) {
4359 /*
4360 * The caller wants an exception, but it was thrown in a
4361 * different thread. Synthesize one here.
4362 */
4363 dvmThrowException("Ljava/lang/UnsatisfiedLinkError;",
4364 "(<clinit> failed, see exception in other thread)");
4365 }
4366 goto bail_unlock;
4367 }
4368
4369 /* see if we failed previously */
4370 if (clazz->status == CLASS_ERROR) {
4371 // might be wise to unlock before throwing; depends on which class
4372 // it is that we have locked
4373 dvmUnlockObject(self, (Object*) clazz);
4374 throwEarlierClassFailure(clazz);
4375 return false;
4376 }
4377
Andy McFaddene15a8eb2010-02-22 17:07:23 -08004378 u8 startWhen = 0;
4379 if (gDvm.allocProf.enabled) {
4380 startWhen = dvmGetRelativeTimeNsec();
4381 }
4382
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004383 /*
4384 * We're ready to go, and have exclusive access to the class.
4385 *
4386 * Before we start initialization, we need to do one extra bit of
4387 * validation: make sure that the methods declared here match up
4388 * with our superclass and interfaces. We know that the UTF-8
4389 * descriptors match, but classes from different class loaders can
4390 * have the same name.
4391 *
4392 * We do this now, rather than at load/link time, for the same reason
4393 * that we defer verification.
4394 *
4395 * It's unfortunate that we need to do this at all, but we risk
4396 * mixing reference types with identical names (see Dalvik test 068).
4397 */
4398 if (!validateSuperDescriptors(clazz)) {
4399 assert(dvmCheckException(self));
4400 clazz->status = CLASS_ERROR;
4401 goto bail_unlock;
4402 }
4403
4404 /*
4405 * Let's initialize this thing.
4406 *
4407 * We unlock the object so that other threads can politely sleep on
4408 * our mutex with Object.wait(), instead of hanging or spinning trying
4409 * to grab our mutex.
4410 */
4411 assert(clazz->status < CLASS_INITIALIZING);
4412
4413#if LOG_CLASS_LOADING
4414 // We started initializing.
4415 logClassLoad('+', clazz);
4416 initializedByUs = true;
4417#endif
4418
4419 clazz->status = CLASS_INITIALIZING;
4420 clazz->initThreadId = self->threadId;
4421 dvmUnlockObject(self, (Object*) clazz);
4422
4423 /* init our superclass */
4424 if (clazz->super != NULL && clazz->super->status != CLASS_INITIALIZED) {
4425 assert(!dvmIsInterfaceClass(clazz));
4426 if (!dvmInitClass(clazz->super)) {
4427 assert(dvmCheckException(self));
4428 clazz->status = CLASS_ERROR;
4429 /* wake up anybody who started waiting while we were unlocked */
4430 dvmLockObject(self, (Object*) clazz);
4431 goto bail_notify;
4432 }
4433 }
4434
4435 /* Initialize any static fields whose values are
4436 * stored in the Dex file. This should include all of the
4437 * simple "final static" fields, which are required to
4438 * be initialized first. (vmspec 2 sec 2.17.5 item 8)
4439 * More-complicated final static fields should be set
4440 * at the beginning of <clinit>; all we can do is trust
4441 * that the compiler did the right thing.
4442 */
4443 initSFields(clazz);
4444
4445 /* Execute any static initialization code.
4446 */
4447 method = dvmFindDirectMethodByDescriptor(clazz, "<clinit>", "()V");
4448 if (method == NULL) {
4449 LOGVV("No <clinit> found for %s\n", clazz->descriptor);
4450 } else {
4451 LOGVV("Invoking %s.<clinit>\n", clazz->descriptor);
4452 JValue unused;
4453 dvmCallMethod(self, method, NULL, &unused);
4454 }
4455
4456 if (dvmCheckException(self)) {
4457 /*
4458 * We've had an exception thrown during static initialization. We
4459 * need to throw an ExceptionInInitializerError, but we want to
4460 * tuck the original exception into the "cause" field.
4461 */
Elliott Hughes22680ee2010-07-20 17:23:06 -07004462 LOGW("Exception %s thrown while initializing %s\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004463 (dvmGetException(self)->clazz)->descriptor, clazz->descriptor);
4464 throwClinitError();
4465 //LOGW("+++ replaced\n");
4466
4467 dvmLockObject(self, (Object*) clazz);
4468 clazz->status = CLASS_ERROR;
4469 } else {
4470 /* success! */
4471 dvmLockObject(self, (Object*) clazz);
4472 clazz->status = CLASS_INITIALIZED;
4473 LOGVV("Initialized class: %s\n", clazz->descriptor);
Andy McFaddene15a8eb2010-02-22 17:07:23 -08004474
4475 /*
4476 * Update alloc counters. TODO: guard with mutex.
4477 */
4478 if (gDvm.allocProf.enabled && startWhen != 0) {
4479 u8 initDuration = dvmGetRelativeTimeNsec() - startWhen;
4480 gDvm.allocProf.classInitTime += initDuration;
4481 self->allocProf.classInitTime += initDuration;
4482 gDvm.allocProf.classInitCount++;
4483 self->allocProf.classInitCount++;
4484 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004485 }
4486
4487bail_notify:
4488 /*
4489 * Notify anybody waiting on the object.
4490 */
4491 dvmObjectNotifyAll(self, (Object*) clazz);
4492
4493bail_unlock:
4494
4495#if LOG_CLASS_LOADING
4496 if (initializedByUs) {
4497 // We finished initializing.
4498 logClassLoad('-', clazz);
4499 }
4500#endif
4501
4502 dvmUnlockObject(self, (Object*) clazz);
4503
4504 return (clazz->status != CLASS_ERROR);
4505}
4506
4507/*
4508 * Replace method->nativeFunc and method->insns with new values. This is
Andy McFadden1e83b4d2010-07-15 17:20:24 -07004509 * commonly performed after successful resolution of a native method.
4510 *
4511 * There are three basic states:
4512 * (1) (initial) nativeFunc = dvmResolveNativeMethod, insns = NULL
4513 * (2) (internal native) nativeFunc = <impl>, insns = NULL
4514 * (3) (JNI) nativeFunc = JNI call bridge, insns = <impl>
4515 *
4516 * nativeFunc must never be NULL for a native method.
4517 *
4518 * The most common transitions are (1)->(2) and (1)->(3). The former is
4519 * atomic, since only one field is updated; the latter is not, but since
4520 * dvmResolveNativeMethod ignores the "insns" field we just need to make
4521 * sure the update happens in the correct order.
4522 *
4523 * A transition from (2)->(1) would work fine, but (3)->(1) will not,
4524 * because both fields change. If we did this while a thread was executing
4525 * in the call bridge, we could null out the "insns" field right before
4526 * the bridge tried to call through it. So, once "insns" is set, we do
4527 * not allow it to be cleared. A NULL value for the "insns" argument is
4528 * treated as "do not change existing value".
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004529 */
Andy McFadden1e83b4d2010-07-15 17:20:24 -07004530void dvmSetNativeFunc(Method* method, DalvikBridgeFunc func,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004531 const u2* insns)
4532{
4533 ClassObject* clazz = method->clazz;
4534
Andy McFadden1e83b4d2010-07-15 17:20:24 -07004535 assert(func != NULL);
4536
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004537 /* just open up both; easier that way */
4538 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4539 dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4540
Andy McFadden1e83b4d2010-07-15 17:20:24 -07004541 if (insns != NULL) {
4542 /* update both, ensuring that "insns" is observed first */
4543 method->insns = insns;
4544 android_atomic_release_store((int32_t) func,
4545 (void*) &method->nativeFunc);
4546 } else {
4547 /* only update nativeFunc */
4548 method->nativeFunc = func;
4549 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004550
4551 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4552 dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4553}
4554
4555/*
4556 * Add a RegisterMap to a Method. This is done when we verify the class
The Android Open Source Project99409882009-03-18 22:20:24 -07004557 * and compute the register maps at class initialization time (i.e. when
4558 * we don't have a pre-generated map). This means "pMap" is on the heap
4559 * and should be freed when the Method is discarded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004560 */
4561void dvmSetRegisterMap(Method* method, const RegisterMap* pMap)
4562{
4563 ClassObject* clazz = method->clazz;
4564
4565 if (method->registerMap != NULL) {
Andy McFaddend45a8872009-03-24 20:41:52 -07004566 /* unexpected during class loading, okay on first use (uncompress) */
Andy McFadden9faa9e62009-04-08 00:35:55 -07004567 LOGV("NOTE: registerMap already set for %s.%s\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004568 method->clazz->descriptor, method->name);
4569 /* keep going */
4570 }
The Android Open Source Project99409882009-03-18 22:20:24 -07004571 assert(!dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004572
4573 /* might be virtual or direct */
4574 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4575 dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4576
4577 method->registerMap = pMap;
4578
4579 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4580 dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4581}
4582
4583/*
4584 * dvmHashForeach callback. A nonzero return value causes foreach to
4585 * bail out.
4586 */
4587static int findClassCallback(void* vclazz, void* arg)
4588{
4589 ClassObject* clazz = vclazz;
4590 const char* descriptor = (const char*) arg;
4591
4592 if (strcmp(clazz->descriptor, descriptor) == 0)
4593 return (int) clazz;
4594 return 0;
4595}
4596
4597/*
4598 * Find a loaded class by descriptor. Returns the first one found.
4599 * Because there can be more than one if class loaders are involved,
4600 * this is not an especially good API. (Currently only used by the
4601 * debugger and "checking" JNI.)
4602 *
4603 * "descriptor" should have the form "Ljava/lang/Class;" or
4604 * "[Ljava/lang/Class;", i.e. a descriptor and not an internal-form
4605 * class name.
4606 */
4607ClassObject* dvmFindLoadedClass(const char* descriptor)
4608{
4609 int result;
4610
4611 dvmHashTableLock(gDvm.loadedClasses);
4612 result = dvmHashForeach(gDvm.loadedClasses, findClassCallback,
4613 (void*) descriptor);
4614 dvmHashTableUnlock(gDvm.loadedClasses);
4615
4616 return (ClassObject*) result;
4617}
4618
4619/*
4620 * Retrieve the system (a/k/a application) class loader.
4621 */
4622Object* dvmGetSystemClassLoader(void)
4623{
4624 ClassObject* clazz;
4625 Method* getSysMeth;
4626 Object* loader;
4627
4628 clazz = dvmFindSystemClass("Ljava/lang/ClassLoader;");
4629 if (clazz == NULL)
4630 return NULL;
4631
4632 getSysMeth = dvmFindDirectMethodByDescriptor(clazz, "getSystemClassLoader",
4633 "()Ljava/lang/ClassLoader;");
4634 if (getSysMeth == NULL)
4635 return NULL;
4636
4637 JValue result;
4638 dvmCallMethod(dvmThreadSelf(), getSysMeth, NULL, &result);
4639 loader = (Object*)result.l;
4640 return loader;
4641}
4642
4643
4644/*
4645 * This is a dvmHashForeach callback.
4646 */
4647static int dumpClass(void* vclazz, void* varg)
4648{
4649 const ClassObject* clazz = (const ClassObject*) vclazz;
4650 const ClassObject* super;
4651 int flags = (int) varg;
4652 char* desc;
4653 int i;
4654
4655 if (clazz == NULL) {
4656 LOGI("dumpClass: ignoring request to dump null class\n");
4657 return 0;
4658 }
4659
4660 if ((flags & kDumpClassFullDetail) == 0) {
4661 bool showInit = (flags & kDumpClassInitialized) != 0;
4662 bool showLoader = (flags & kDumpClassClassLoader) != 0;
4663 const char* initStr;
4664
4665 initStr = dvmIsClassInitialized(clazz) ? "true" : "false";
4666
4667 if (showInit && showLoader)
4668 LOGI("%s %p %s\n", clazz->descriptor, clazz->classLoader, initStr);
4669 else if (showInit)
4670 LOGI("%s %s\n", clazz->descriptor, initStr);
4671 else if (showLoader)
4672 LOGI("%s %p\n", clazz->descriptor, clazz->classLoader);
4673 else
4674 LOGI("%s\n", clazz->descriptor);
4675
4676 return 0;
4677 }
4678
4679 /* clazz->super briefly holds the superclass index during class prep */
4680 if ((u4)clazz->super > 0x10000 && (u4) clazz->super != (u4)-1)
4681 super = clazz->super;
4682 else
4683 super = NULL;
4684
4685 LOGI("----- %s '%s' cl=%p ser=0x%08x -----\n",
4686 dvmIsInterfaceClass(clazz) ? "interface" : "class",
4687 clazz->descriptor, clazz->classLoader, clazz->serialNumber);
4688 LOGI(" objectSize=%d (%d from super)\n", (int) clazz->objectSize,
4689 super != NULL ? (int) super->objectSize : -1);
4690 LOGI(" access=0x%04x.%04x\n", clazz->accessFlags >> 16,
4691 clazz->accessFlags & JAVA_FLAGS_MASK);
4692 if (super != NULL)
4693 LOGI(" super='%s' (cl=%p)\n", super->descriptor, super->classLoader);
4694 if (dvmIsArrayClass(clazz)) {
4695 LOGI(" dimensions=%d elementClass=%s\n",
4696 clazz->arrayDim, clazz->elementClass->descriptor);
4697 }
4698 if (clazz->iftableCount > 0) {
4699 LOGI(" interfaces (%d):\n", clazz->iftableCount);
4700 for (i = 0; i < clazz->iftableCount; i++) {
4701 InterfaceEntry* ent = &clazz->iftable[i];
4702 int j;
4703
4704 LOGI(" %2d: %s (cl=%p)\n",
4705 i, ent->clazz->descriptor, ent->clazz->classLoader);
4706
4707 /* enable when needed */
4708 if (false && ent->methodIndexArray != NULL) {
4709 for (j = 0; j < ent->clazz->virtualMethodCount; j++)
4710 LOGI(" %2d: %d %s %s\n",
4711 j, ent->methodIndexArray[j],
4712 ent->clazz->virtualMethods[j].name,
4713 clazz->vtable[ent->methodIndexArray[j]]->name);
4714 }
4715 }
4716 }
4717 if (!dvmIsInterfaceClass(clazz)) {
4718 LOGI(" vtable (%d entries, %d in super):\n", clazz->vtableCount,
4719 super != NULL ? super->vtableCount : 0);
4720 for (i = 0; i < clazz->vtableCount; i++) {
4721 desc = dexProtoCopyMethodDescriptor(&clazz->vtable[i]->prototype);
4722 LOGI(" %s%2d: %p %20s %s\n",
4723 (i != clazz->vtable[i]->methodIndex) ? "*** " : "",
4724 (u4) clazz->vtable[i]->methodIndex, clazz->vtable[i],
4725 clazz->vtable[i]->name, desc);
4726 free(desc);
4727 }
4728 LOGI(" direct methods (%d entries):\n", clazz->directMethodCount);
4729 for (i = 0; i < clazz->directMethodCount; i++) {
4730 desc = dexProtoCopyMethodDescriptor(
4731 &clazz->directMethods[i].prototype);
4732 LOGI(" %2d: %20s %s\n", i, clazz->directMethods[i].name,
4733 desc);
4734 free(desc);
4735 }
4736 } else {
4737 LOGI(" interface methods (%d):\n", clazz->virtualMethodCount);
4738 for (i = 0; i < clazz->virtualMethodCount; i++) {
4739 desc = dexProtoCopyMethodDescriptor(
4740 &clazz->virtualMethods[i].prototype);
4741 LOGI(" %2d: %2d %20s %s\n", i,
4742 (u4) clazz->virtualMethods[i].methodIndex,
4743 clazz->virtualMethods[i].name,
4744 desc);
4745 free(desc);
4746 }
4747 }
4748 if (clazz->sfieldCount > 0) {
4749 LOGI(" static fields (%d entries):\n", clazz->sfieldCount);
4750 for (i = 0; i < clazz->sfieldCount; i++) {
4751 LOGI(" %2d: %20s %s\n", i, clazz->sfields[i].field.name,
4752 clazz->sfields[i].field.signature);
4753 }
4754 }
4755 if (clazz->ifieldCount > 0) {
4756 LOGI(" instance fields (%d entries):\n", clazz->ifieldCount);
4757 for (i = 0; i < clazz->ifieldCount; i++) {
4758 LOGI(" %2d: %20s %s\n", i, clazz->ifields[i].field.name,
4759 clazz->ifields[i].field.signature);
4760 }
4761 }
4762 return 0;
4763}
4764
4765/*
4766 * Dump the contents of a single class.
4767 *
4768 * Pass kDumpClassFullDetail into "flags" to get lots of detail.
4769 */
4770void dvmDumpClass(const ClassObject* clazz, int flags)
4771{
4772 dumpClass((void*) clazz, (void*) flags);
4773}
4774
4775/*
4776 * Dump the contents of all classes.
4777 */
4778void dvmDumpAllClasses(int flags)
4779{
4780 dvmHashTableLock(gDvm.loadedClasses);
4781 dvmHashForeach(gDvm.loadedClasses, dumpClass, (void*) flags);
4782 dvmHashTableUnlock(gDvm.loadedClasses);
4783}
4784
4785/*
4786 * Get the number of loaded classes
4787 */
4788int dvmGetNumLoadedClasses()
4789{
4790 int count;
4791 dvmHashTableLock(gDvm.loadedClasses);
4792 count = dvmHashTableNumEntries(gDvm.loadedClasses);
4793 dvmHashTableUnlock(gDvm.loadedClasses);
4794 return count;
4795}
4796
4797/*
4798 * Write some statistics to the log file.
4799 */
4800void dvmDumpLoaderStats(const char* msg)
4801{
4802 LOGV("VM stats (%s): cls=%d/%d meth=%d ifld=%d sfld=%d linear=%d\n",
4803 msg, gDvm.numLoadedClasses, dvmHashTableNumEntries(gDvm.loadedClasses),
4804 gDvm.numDeclaredMethods, gDvm.numDeclaredInstFields,
4805 gDvm.numDeclaredStaticFields, gDvm.pBootLoaderAlloc->curOffset);
4806#ifdef COUNT_PRECISE_METHODS
4807 LOGI("GC precise methods: %d\n",
4808 dvmPointerSetGetCount(gDvm.preciseMethods));
4809#endif
4810}
4811
4812#ifdef PROFILE_FIELD_ACCESS
4813/*
4814 * Dump the field access counts for all fields in this method.
4815 */
4816static int dumpAccessCounts(void* vclazz, void* varg)
4817{
4818 const ClassObject* clazz = (const ClassObject*) vclazz;
4819 int i;
4820
4821 for (i = 0; i < clazz->ifieldCount; i++) {
4822 Field* field = &clazz->ifields[i].field;
4823
4824 if (field->gets != 0)
4825 printf("GI %d %s.%s\n", field->gets,
4826 field->clazz->descriptor, field->name);
4827 if (field->puts != 0)
4828 printf("PI %d %s.%s\n", field->puts,
4829 field->clazz->descriptor, field->name);
4830 }
4831 for (i = 0; i < clazz->sfieldCount; i++) {
4832 Field* field = &clazz->sfields[i].field;
4833
4834 if (field->gets != 0)
4835 printf("GS %d %s.%s\n", field->gets,
4836 field->clazz->descriptor, field->name);
4837 if (field->puts != 0)
4838 printf("PS %d %s.%s\n", field->puts,
4839 field->clazz->descriptor, field->name);
4840 }
4841
4842 return 0;
4843}
4844
4845/*
4846 * Dump the field access counts for all loaded classes.
4847 */
4848void dvmDumpFieldAccessCounts(void)
4849{
4850 dvmHashTableLock(gDvm.loadedClasses);
4851 dvmHashForeach(gDvm.loadedClasses, dumpAccessCounts, NULL);
4852 dvmHashTableUnlock(gDvm.loadedClasses);
4853}
4854#endif
4855
4856
4857/*
4858 * Mark all classes associated with the built-in loader.
4859 */
4860static int markClassObject(void *clazz, void *arg)
4861{
4862 UNUSED_PARAMETER(arg);
4863
4864 dvmMarkObjectNonNull((Object *)clazz);
4865 return 0;
4866}
4867
4868/*
4869 * The garbage collector calls this to mark the class objects for all
4870 * loaded classes.
4871 */
4872void dvmGcScanRootClassLoader()
4873{
4874 /* dvmClassStartup() may not have been called before the first GC.
4875 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004876 if (gDvm.loadedClasses != NULL) {
4877 dvmHashTableLock(gDvm.loadedClasses);
4878 dvmHashForeach(gDvm.loadedClasses, markClassObject, NULL);
4879 dvmHashTableUnlock(gDvm.loadedClasses);
4880 }
4881}
4882
4883
4884/*
4885 * ===========================================================================
4886 * Method Prototypes and Descriptors
4887 * ===========================================================================
4888 */
4889
4890/*
4891 * Compare the two method names and prototypes, a la strcmp(). The
4892 * name is considered the "major" order and the prototype the "minor"
4893 * order. The prototypes are compared as if by dvmCompareMethodProtos().
4894 */
4895int dvmCompareMethodNamesAndProtos(const Method* method1,
4896 const Method* method2)
4897{
4898 int result = strcmp(method1->name, method2->name);
4899
4900 if (result != 0) {
4901 return result;
4902 }
4903
4904 return dvmCompareMethodProtos(method1, method2);
4905}
4906
4907/*
4908 * Compare the two method names and prototypes, a la strcmp(), ignoring
4909 * the return value. The name is considered the "major" order and the
4910 * prototype the "minor" order. The prototypes are compared as if by
4911 * dvmCompareMethodArgProtos().
4912 */
4913int dvmCompareMethodNamesAndParameterProtos(const Method* method1,
4914 const Method* method2)
4915{
4916 int result = strcmp(method1->name, method2->name);
4917
4918 if (result != 0) {
4919 return result;
4920 }
4921
4922 return dvmCompareMethodParameterProtos(method1, method2);
4923}
4924
4925/*
4926 * Compare a (name, prototype) pair with the (name, prototype) of
4927 * a method, a la strcmp(). The name is considered the "major" order and
4928 * the prototype the "minor" order. The descriptor and prototype are
4929 * compared as if by dvmCompareDescriptorAndMethodProto().
4930 */
4931int dvmCompareNameProtoAndMethod(const char* name,
4932 const DexProto* proto, const Method* method)
4933{
4934 int result = strcmp(name, method->name);
4935
4936 if (result != 0) {
4937 return result;
4938 }
4939
4940 return dexProtoCompare(proto, &method->prototype);
4941}
4942
4943/*
4944 * Compare a (name, method descriptor) pair with the (name, prototype) of
4945 * a method, a la strcmp(). The name is considered the "major" order and
4946 * the prototype the "minor" order. The descriptor and prototype are
4947 * compared as if by dvmCompareDescriptorAndMethodProto().
4948 */
4949int dvmCompareNameDescriptorAndMethod(const char* name,
4950 const char* descriptor, const Method* method)
4951{
4952 int result = strcmp(name, method->name);
4953
4954 if (result != 0) {
4955 return result;
4956 }
4957
4958 return dvmCompareDescriptorAndMethodProto(descriptor, method);
4959}