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