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