blob: b7fbb59e8c91a2d30404008c9dbe63778391327c [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 {
Dan Bornstein32bc0782010-09-13 17:30:10 -0700587 if (isBootstrap &&
588 dvmPathToAbsolutePortion(cp) == NULL) {
589 LOGE("Non-absolute bootclasspath entry '%s'\n", cp);
590 free(cpe);
591 cpe = NULL;
592 goto bail;
593 }
594
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800595 ClassPathEntry tmp;
596 tmp.kind = kCpeUnknown;
597 tmp.fileName = strdup(cp);
598 tmp.ptr = NULL;
599
Dan Bornstein32bc0782010-09-13 17:30:10 -0700600 /*
601 * Drop an end marker here so DEX loader can walk unfinished
602 * list.
603 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800604 cpe[idx].kind = kCpeLastEntry;
605 cpe[idx].fileName = NULL;
606 cpe[idx].ptr = NULL;
607
608 if (!prepareCpe(&tmp, isBootstrap)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800609 /* drop from list and continue on */
610 free(tmp.fileName);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800611 } else {
612 /* copy over, pointers and all */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800613 cpe[idx] = tmp;
614 idx++;
615 }
616 }
617
618 cp += strlen(cp) +1;
619 }
620 assert(idx <= count);
621 if (idx == 0 && !gDvm.optimizing) {
Dan Bornstein32bc0782010-09-13 17:30:10 -0700622 LOGE("No valid entries found in bootclasspath '%s'\n", pathStr);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800623 free(cpe);
624 cpe = NULL;
625 goto bail;
626 }
627
628 LOGVV(" (filled %d of %d slots)\n", idx, count);
629
630 /* put end marker in over-alloc slot */
631 cpe[idx].kind = kCpeLastEntry;
632 cpe[idx].fileName = NULL;
633 cpe[idx].ptr = NULL;
634
635 //dumpClassPath(cpe);
636
637bail:
638 free(mangle);
639 gDvm.bootClassPath = cpe;
640 return cpe;
641}
642
643/*
644 * Search the DEX files we loaded from the bootstrap class path for a DEX
645 * file that has the class with the matching descriptor.
646 *
647 * Returns the matching DEX file and DexClassDef entry if found, otherwise
648 * returns NULL.
649 */
650static DvmDex* searchBootPathForClass(const char* descriptor,
651 const DexClassDef** ppClassDef)
652{
653 const ClassPathEntry* cpe = gDvm.bootClassPath;
654 const DexClassDef* pFoundDef = NULL;
655 DvmDex* pFoundFile = NULL;
656
657 LOGVV("+++ class '%s' not yet loaded, scanning bootclasspath...\n",
658 descriptor);
659
660 while (cpe->kind != kCpeLastEntry) {
661 //LOGV("+++ checking '%s' (%d)\n", cpe->fileName, cpe->kind);
662
663 switch (cpe->kind) {
664 case kCpeDir:
665 LOGW("Directory entries ('%s') not supported in bootclasspath\n",
666 cpe->fileName);
667 break;
668 case kCpeJar:
669 {
670 JarFile* pJarFile = (JarFile*) cpe->ptr;
671 const DexClassDef* pClassDef;
672 DvmDex* pDvmDex;
673
674 pDvmDex = dvmGetJarFileDex(pJarFile);
675 pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
676 if (pClassDef != NULL) {
677 /* found */
678 pFoundDef = pClassDef;
679 pFoundFile = pDvmDex;
680 goto found;
681 }
682 }
683 break;
684 case kCpeDex:
685 {
686 RawDexFile* pRawDexFile = (RawDexFile*) cpe->ptr;
687 const DexClassDef* pClassDef;
688 DvmDex* pDvmDex;
689
690 pDvmDex = dvmGetRawDexFileDex(pRawDexFile);
691 pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
692 if (pClassDef != NULL) {
693 /* found */
694 pFoundDef = pClassDef;
695 pFoundFile = pDvmDex;
696 goto found;
697 }
698 }
699 break;
700 default:
701 LOGE("Unknown kind %d\n", cpe->kind);
702 assert(false);
703 break;
704 }
705
706 cpe++;
707 }
708
709 /*
710 * Special handling during verification + optimization.
711 *
712 * The DEX optimizer needs to load classes from the DEX file it's working
713 * on. Rather than trying to insert it into the bootstrap class path
714 * or synthesizing a class loader to manage it, we just make it available
715 * here. It logically comes after all existing entries in the bootstrap
716 * class path.
717 */
718 if (gDvm.bootClassPathOptExtra != NULL) {
719 const DexClassDef* pClassDef;
720
721 pClassDef =
722 dexFindClass(gDvm.bootClassPathOptExtra->pDexFile, descriptor);
723 if (pClassDef != NULL) {
724 /* found */
725 pFoundDef = pClassDef;
726 pFoundFile = gDvm.bootClassPathOptExtra;
727 }
728 }
729
730found:
731 *ppClassDef = pFoundDef;
732 return pFoundFile;
733}
734
735/*
736 * Set the "extra" DEX, which becomes a de facto member of the bootstrap
737 * class set.
738 */
739void dvmSetBootPathExtraDex(DvmDex* pDvmDex)
740{
741 gDvm.bootClassPathOptExtra = pDvmDex;
742}
743
744
745/*
746 * Return the #of entries in the bootstrap class path.
747 *
748 * (Used for ClassLoader.getResources().)
749 */
750int dvmGetBootPathSize(void)
751{
752 const ClassPathEntry* cpe = gDvm.bootClassPath;
753
754 while (cpe->kind != kCpeLastEntry)
755 cpe++;
756
757 return cpe - gDvm.bootClassPath;
758}
759
760/*
761 * Find a resource with the specified name in entry N of the boot class path.
762 *
763 * We return a newly-allocated String of one of these forms:
764 * file://path/name
765 * jar:file://path!/name
766 * Where "path" is the bootstrap class path entry and "name" is the string
767 * passed into this method. "path" needs to be an absolute path (starting
768 * with '/'); if it's not we'd need to "absolutify" it as part of forming
769 * the URL string.
770 */
771StringObject* dvmGetBootPathResource(const char* name, int idx)
772{
773 const int kUrlOverhead = 13; // worst case for Jar URL
774 const ClassPathEntry* cpe = gDvm.bootClassPath;
775 StringObject* urlObj = NULL;
776
777 LOGV("+++ searching for resource '%s' in %d(%s)\n",
778 name, idx, cpe[idx].fileName);
779
780 /* we could use direct array index, but I don't entirely trust "idx" */
781 while (idx-- && cpe->kind != kCpeLastEntry)
782 cpe++;
783 if (cpe->kind == kCpeLastEntry) {
784 assert(false);
785 return NULL;
786 }
787
788 char urlBuf[strlen(name) + strlen(cpe->fileName) + kUrlOverhead +1];
789
790 switch (cpe->kind) {
791 case kCpeDir:
792 sprintf(urlBuf, "file://%s/%s", cpe->fileName, name);
793 if (access(urlBuf+7, F_OK) != 0)
794 goto bail;
795 break;
796 case kCpeJar:
797 {
798 JarFile* pJarFile = (JarFile*) cpe->ptr;
799 if (dexZipFindEntry(&pJarFile->archive, name) == NULL)
800 goto bail;
801 sprintf(urlBuf, "jar:file://%s!/%s", cpe->fileName, name);
802 }
803 break;
804 case kCpeDex:
805 LOGV("No resources in DEX files\n");
806 goto bail;
807 default:
808 assert(false);
809 goto bail;
810 }
811
812 LOGV("+++ using URL='%s'\n", urlBuf);
Barry Hayes81f3ebe2010-06-15 16:17:37 -0700813 urlObj = dvmCreateStringFromCstr(urlBuf);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800814
815bail:
816 return urlObj;
817}
818
819
820/*
821 * ===========================================================================
822 * Class list management
823 * ===========================================================================
824 */
825
826/* search for these criteria in the Class hash table */
827typedef struct ClassMatchCriteria {
828 const char* descriptor;
829 Object* loader;
830} ClassMatchCriteria;
831
832#define kInitLoaderInc 4 /* must be power of 2 */
833
Barry Hayes2c987472009-04-06 10:03:48 -0700834static InitiatingLoaderList *dvmGetInitiatingLoaderList(ClassObject* clazz)
835{
Barry Hayesc49db852010-05-14 13:43:34 -0700836 assert(clazz->serialNumber >= INITIAL_CLASS_SERIAL_NUMBER);
Barry Hayes2c987472009-04-06 10:03:48 -0700837 int classIndex = clazz->serialNumber-INITIAL_CLASS_SERIAL_NUMBER;
838 if (gDvm.initiatingLoaderList != NULL &&
839 classIndex < ZYGOTE_CLASS_CUTOFF) {
840 return &(gDvm.initiatingLoaderList[classIndex]);
841 } else {
842 return &(clazz->initiatingLoaderList);
843 }
844}
845
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800846/*
847 * Determine if "loader" appears in clazz' initiating loader list.
848 *
849 * The class hash table lock must be held when calling here, since
850 * it's also used when updating a class' initiating loader list.
851 *
852 * TODO: switch to some sort of lock-free data structure so we don't have
853 * to grab the lock to do a lookup. Among other things, this would improve
854 * the speed of compareDescriptorClasses().
855 */
856bool dvmLoaderInInitiatingList(const ClassObject* clazz, const Object* loader)
857{
858 /*
859 * The bootstrap class loader can't be just an initiating loader for
860 * anything (it's always the defining loader if the class is visible
861 * to it). We don't put defining loaders in the initiating list.
862 */
863 if (loader == NULL)
864 return false;
865
866 /*
867 * Scan the list for a match. The list is expected to be short.
868 */
Barry Hayes2c987472009-04-06 10:03:48 -0700869 /* Cast to remove the const from clazz, but use const loaderList */
870 ClassObject* nonConstClazz = (ClassObject*) clazz;
871 const InitiatingLoaderList *loaderList =
872 dvmGetInitiatingLoaderList(nonConstClazz);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800873 int i;
Barry Hayes2c987472009-04-06 10:03:48 -0700874 for (i = loaderList->initiatingLoaderCount-1; i >= 0; --i) {
875 if (loaderList->initiatingLoaders[i] == loader) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800876 //LOGI("+++ found initiating match %p in %s\n",
877 // loader, clazz->descriptor);
878 return true;
879 }
880 }
881 return false;
882}
883
884/*
885 * Add "loader" to clazz's initiating loader set, unless it's the defining
886 * class loader.
887 *
888 * In the common case this will be a short list, so we don't need to do
889 * anything too fancy here.
890 *
891 * This locks gDvm.loadedClasses for synchronization, so don't hold it
892 * when calling here.
893 */
894void dvmAddInitiatingLoader(ClassObject* clazz, Object* loader)
895{
896 if (loader != clazz->classLoader) {
897 assert(loader != NULL);
898
899 LOGVV("Adding %p to '%s' init list\n", loader, clazz->descriptor);
900 dvmHashTableLock(gDvm.loadedClasses);
901
902 /*
903 * Make sure nobody snuck in. The penalty for adding twice is
904 * pretty minor, and probably outweighs the O(n^2) hit for
905 * checking before every add, so we may not want to do this.
906 */
Barry Hayes2c987472009-04-06 10:03:48 -0700907 //if (dvmLoaderInInitiatingList(clazz, loader)) {
908 // LOGW("WOW: simultaneous add of initiating class loader\n");
909 // goto bail_unlock;
910 //}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800911
912 /*
913 * The list never shrinks, so we just keep a count of the
914 * number of elements in it, and reallocate the buffer when
915 * we run off the end.
916 *
917 * The pointer is initially NULL, so we *do* want to call realloc
918 * when count==0.
919 */
Barry Hayes2c987472009-04-06 10:03:48 -0700920 InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz);
921 if ((loaderList->initiatingLoaderCount & (kInitLoaderInc-1)) == 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800922 Object** newList;
923
Barry Hayes2c987472009-04-06 10:03:48 -0700924 newList = (Object**) realloc(loaderList->initiatingLoaders,
925 (loaderList->initiatingLoaderCount + kInitLoaderInc)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800926 * sizeof(Object*));
927 if (newList == NULL) {
928 /* this is mainly a cache, so it's not the EotW */
929 assert(false);
930 goto bail_unlock;
931 }
Barry Hayes2c987472009-04-06 10:03:48 -0700932 loaderList->initiatingLoaders = newList;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800933
934 //LOGI("Expanded init list to %d (%s)\n",
Barry Hayes2c987472009-04-06 10:03:48 -0700935 // loaderList->initiatingLoaderCount+kInitLoaderInc,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800936 // clazz->descriptor);
937 }
Barry Hayes2c987472009-04-06 10:03:48 -0700938 loaderList->initiatingLoaders[loaderList->initiatingLoaderCount++] =
939 loader;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800940
941bail_unlock:
942 dvmHashTableUnlock(gDvm.loadedClasses);
943 }
944}
945
946/*
947 * (This is a dvmHashTableLookup callback.)
948 *
949 * Entries in the class hash table are stored as { descriptor, d-loader }
950 * tuples. If the hashed class descriptor matches the requested descriptor,
951 * and the hashed defining class loader matches the requested class
952 * loader, we're good. If only the descriptor matches, we check to see if the
953 * loader is in the hashed class' initiating loader list. If so, we
954 * can return "true" immediately and skip some of the loadClass melodrama.
955 *
956 * The caller must lock the hash table before calling here.
957 *
958 * Returns 0 if a matching entry is found, nonzero otherwise.
959 */
960static int hashcmpClassByCrit(const void* vclazz, const void* vcrit)
961{
962 const ClassObject* clazz = (const ClassObject*) vclazz;
963 const ClassMatchCriteria* pCrit = (const ClassMatchCriteria*) vcrit;
964 bool match;
965
966 match = (strcmp(clazz->descriptor, pCrit->descriptor) == 0 &&
967 (clazz->classLoader == pCrit->loader ||
968 (pCrit->loader != NULL &&
969 dvmLoaderInInitiatingList(clazz, pCrit->loader)) ));
970 //if (match)
971 // LOGI("+++ %s %p matches existing %s %p\n",
972 // pCrit->descriptor, pCrit->loader,
973 // clazz->descriptor, clazz->classLoader);
974 return !match;
975}
976
977/*
978 * Like hashcmpClassByCrit, but passing in a fully-formed ClassObject
979 * instead of a ClassMatchCriteria.
980 */
981static int hashcmpClassByClass(const void* vclazz, const void* vaddclazz)
982{
983 const ClassObject* clazz = (const ClassObject*) vclazz;
984 const ClassObject* addClazz = (const ClassObject*) vaddclazz;
985 bool match;
986
987 match = (strcmp(clazz->descriptor, addClazz->descriptor) == 0 &&
988 (clazz->classLoader == addClazz->classLoader ||
989 (addClazz->classLoader != NULL &&
990 dvmLoaderInInitiatingList(clazz, addClazz->classLoader)) ));
991 return !match;
992}
993
994/*
995 * Search through the hash table to find an entry with a matching descriptor
996 * and an initiating class loader that matches "loader".
997 *
998 * The table entries are hashed on descriptor only, because they're unique
999 * on *defining* class loader, not *initiating* class loader. This isn't
1000 * great, because it guarantees we will have to probe when multiple
1001 * class loaders are used.
1002 *
1003 * Note this does NOT try to load a class; it just finds a class that
1004 * has already been loaded.
1005 *
1006 * If "unprepOkay" is set, this will return classes that have been added
1007 * to the hash table but are not yet fully loaded and linked. Otherwise,
1008 * such classes are ignored. (The only place that should set "unprepOkay"
1009 * is findClassNoInit(), which will wait for the prep to finish.)
1010 *
1011 * Returns NULL if not found.
1012 */
1013ClassObject* dvmLookupClass(const char* descriptor, Object* loader,
1014 bool unprepOkay)
1015{
1016 ClassMatchCriteria crit;
1017 void* found;
1018 u4 hash;
1019
1020 crit.descriptor = descriptor;
1021 crit.loader = loader;
1022 hash = dvmComputeUtf8Hash(descriptor);
1023
1024 LOGVV("threadid=%d: dvmLookupClass searching for '%s' %p\n",
1025 dvmThreadSelf()->threadId, descriptor, loader);
1026
1027 dvmHashTableLock(gDvm.loadedClasses);
1028 found = dvmHashTableLookup(gDvm.loadedClasses, hash, &crit,
1029 hashcmpClassByCrit, false);
1030 dvmHashTableUnlock(gDvm.loadedClasses);
1031
1032 /*
1033 * The class has been added to the hash table but isn't ready for use.
1034 * We're going to act like we didn't see it, so that the caller will
1035 * go through the full "find class" path, which includes locking the
1036 * object and waiting until it's ready. We could do that lock/wait
1037 * here, but this is an extremely rare case, and it's simpler to have
1038 * the wait-for-class code centralized.
1039 */
1040 if (found != NULL && !unprepOkay && !dvmIsClassLinked(found)) {
1041 LOGV("Ignoring not-yet-ready %s, using slow path\n",
1042 ((ClassObject*)found)->descriptor);
1043 found = NULL;
1044 }
1045
1046 return (ClassObject*) found;
1047}
1048
1049/*
1050 * Add a new class to the hash table.
1051 *
1052 * The class is considered "new" if it doesn't match on both the class
1053 * descriptor and the defining class loader.
1054 *
1055 * TODO: we should probably have separate hash tables for each
1056 * ClassLoader. This could speed up dvmLookupClass and
1057 * other common operations. It does imply a VM-visible data structure
1058 * for each ClassLoader object with loaded classes, which we don't
1059 * have yet.
1060 */
1061bool dvmAddClassToHash(ClassObject* clazz)
1062{
1063 void* found;
1064 u4 hash;
1065
1066 hash = dvmComputeUtf8Hash(clazz->descriptor);
1067
1068 dvmHashTableLock(gDvm.loadedClasses);
1069 found = dvmHashTableLookup(gDvm.loadedClasses, hash, clazz,
1070 hashcmpClassByClass, true);
1071 dvmHashTableUnlock(gDvm.loadedClasses);
1072
1073 LOGV("+++ dvmAddClassToHash '%s' %p (isnew=%d) --> %p\n",
1074 clazz->descriptor, clazz->classLoader,
1075 (found == (void*) clazz), clazz);
1076
1077 //dvmCheckClassTablePerf();
1078
1079 /* can happen if two threads load the same class simultaneously */
1080 return (found == (void*) clazz);
1081}
1082
1083#if 0
1084/*
1085 * Compute hash value for a class.
1086 */
1087u4 hashcalcClass(const void* item)
1088{
1089 return dvmComputeUtf8Hash(((const ClassObject*) item)->descriptor);
1090}
1091
1092/*
1093 * Check the performance of the "loadedClasses" hash table.
1094 */
1095void dvmCheckClassTablePerf(void)
1096{
1097 dvmHashTableLock(gDvm.loadedClasses);
1098 dvmHashTableProbeCount(gDvm.loadedClasses, hashcalcClass,
1099 hashcmpClassByClass);
1100 dvmHashTableUnlock(gDvm.loadedClasses);
1101}
1102#endif
1103
1104/*
1105 * Remove a class object from the hash table.
1106 */
1107static void removeClassFromHash(ClassObject* clazz)
1108{
1109 LOGV("+++ removeClassFromHash '%s'\n", clazz->descriptor);
1110
1111 u4 hash = dvmComputeUtf8Hash(clazz->descriptor);
1112
1113 dvmHashTableLock(gDvm.loadedClasses);
1114 if (!dvmHashTableRemove(gDvm.loadedClasses, hash, clazz))
1115 LOGW("Hash table remove failed on class '%s'\n", clazz->descriptor);
1116 dvmHashTableUnlock(gDvm.loadedClasses);
1117}
1118
1119
1120/*
1121 * ===========================================================================
1122 * Class creation
1123 * ===========================================================================
1124 */
1125
1126/*
1127 * Set clazz->serialNumber to the next available value.
1128 *
1129 * This usually happens *very* early in class creation, so don't expect
1130 * anything else in the class to be ready.
1131 */
1132void dvmSetClassSerialNumber(ClassObject* clazz)
1133{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001134 assert(clazz->serialNumber == 0);
Andy McFaddenfc3d3162010-08-05 14:34:26 -07001135 clazz->serialNumber = android_atomic_inc(&gDvm.classSerialNumber);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001136}
1137
1138
1139/*
1140 * Find the named class (by descriptor), using the specified
1141 * initiating ClassLoader.
1142 *
1143 * The class will be loaded and initialized if it has not already been.
1144 * If necessary, the superclass will be loaded.
1145 *
1146 * If the class can't be found, returns NULL with an appropriate exception
1147 * raised.
1148 */
1149ClassObject* dvmFindClass(const char* descriptor, Object* loader)
1150{
1151 ClassObject* clazz;
1152
1153 clazz = dvmFindClassNoInit(descriptor, loader);
1154 if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1155 /* initialize class */
1156 if (!dvmInitClass(clazz)) {
1157 /* init failed; leave it in the list, marked as bad */
1158 assert(dvmCheckException(dvmThreadSelf()));
1159 assert(clazz->status == CLASS_ERROR);
1160 return NULL;
1161 }
1162 }
1163
1164 return clazz;
1165}
1166
1167/*
1168 * Find the named class (by descriptor), using the specified
1169 * initiating ClassLoader.
1170 *
1171 * The class will be loaded if it has not already been, as will its
1172 * superclass. It will not be initialized.
1173 *
1174 * If the class can't be found, returns NULL with an appropriate exception
1175 * raised.
1176 */
1177ClassObject* dvmFindClassNoInit(const char* descriptor,
1178 Object* loader)
1179{
1180 assert(descriptor != NULL);
1181 //assert(loader != NULL);
1182
1183 LOGVV("FindClassNoInit '%s' %p\n", descriptor, loader);
1184
1185 if (*descriptor == '[') {
1186 /*
1187 * Array class. Find in table, generate if not found.
1188 */
1189 return dvmFindArrayClass(descriptor, loader);
1190 } else {
1191 /*
1192 * Regular class. Find in table, load if not found.
1193 */
1194 if (loader != NULL) {
1195 return findClassFromLoaderNoInit(descriptor, loader);
1196 } else {
1197 return dvmFindSystemClassNoInit(descriptor);
1198 }
1199 }
1200}
1201
1202/*
1203 * Load the named class (by descriptor) from the specified class
1204 * loader. This calls out to let the ClassLoader object do its thing.
1205 *
1206 * Returns with NULL and an exception raised on error.
1207 */
1208static ClassObject* findClassFromLoaderNoInit(const char* descriptor,
1209 Object* loader)
1210{
1211 //LOGI("##### findClassFromLoaderNoInit (%s,%p)\n",
1212 // descriptor, loader);
1213
1214 Thread* self = dvmThreadSelf();
1215 ClassObject* clazz;
1216
1217 assert(loader != NULL);
1218
1219 /*
1220 * Do we already have it?
1221 *
1222 * The class loader code does the "is it already loaded" check as
1223 * well. However, this call is much faster than calling through
1224 * interpreted code. Doing this does mean that in the common case
1225 * (365 out of 420 calls booting the sim) we're doing the
1226 * lookup-by-descriptor twice. It appears this is still a win, so
1227 * I'm keeping it in.
1228 */
1229 clazz = dvmLookupClass(descriptor, loader, false);
1230 if (clazz != NULL) {
1231 LOGVV("Already loaded: %s %p\n", descriptor, loader);
1232 return clazz;
1233 } else {
1234 LOGVV("Not already loaded: %s %p\n", descriptor, loader);
1235 }
1236
1237 char* dotName = NULL;
1238 StringObject* nameObj = NULL;
1239 Object* excep;
1240 Method* loadClass;
1241
1242 /* convert "Landroid/debug/Stuff;" to "android.debug.Stuff" */
1243 dotName = dvmDescriptorToDot(descriptor);
1244 if (dotName == NULL) {
1245 dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL);
1246 goto bail;
1247 }
Barry Hayes81f3ebe2010-06-15 16:17:37 -07001248 nameObj = dvmCreateStringFromCstr(dotName);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001249 if (nameObj == NULL) {
1250 assert(dvmCheckException(self));
1251 goto bail;
1252 }
1253
1254 // TODO: cache the vtable offset
1255 loadClass = dvmFindVirtualMethodHierByDescriptor(loader->clazz, "loadClass",
1256 "(Ljava/lang/String;)Ljava/lang/Class;");
1257 if (loadClass == NULL) {
1258 LOGW("Couldn't find loadClass in ClassLoader\n");
1259 goto bail;
1260 }
1261
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001262 dvmMethodTraceClassPrepBegin();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001263
1264 /*
1265 * Invoke loadClass(). This will probably result in a couple of
1266 * exceptions being thrown, because the ClassLoader.loadClass()
1267 * implementation eventually calls VMClassLoader.loadClass to see if
1268 * the bootstrap class loader can find it before doing its own load.
1269 */
1270 LOGVV("--- Invoking loadClass(%s, %p)\n", dotName, loader);
1271 JValue result;
1272 dvmCallMethod(self, loadClass, loader, &result, nameObj);
1273 clazz = (ClassObject*) result.l;
1274
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001275 dvmMethodTraceClassPrepEnd();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001276
1277 excep = dvmGetException(self);
1278 if (excep != NULL) {
1279#if DVM_SHOW_EXCEPTION >= 2
1280 LOGD("NOTE: loadClass '%s' %p threw exception %s\n",
1281 dotName, loader, excep->clazz->descriptor);
1282#endif
1283 dvmAddTrackedAlloc(excep, self);
1284 dvmClearException(self);
1285 dvmThrowChainedExceptionWithClassMessage(
1286 "Ljava/lang/NoClassDefFoundError;", descriptor, excep);
1287 dvmReleaseTrackedAlloc(excep, self);
1288 clazz = NULL;
1289 goto bail;
Andy McFaddend0f0ee62010-07-09 10:52:19 -07001290 } else if (clazz == NULL) {
1291 LOGW("ClassLoader returned NULL w/o exception pending\n");
1292 dvmThrowException("Ljava/lang/NullPointerException;",
1293 "ClassLoader returned null");
1294 goto bail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001295 }
1296
1297 dvmAddInitiatingLoader(clazz, loader);
1298
1299 LOGVV("--- Successfully loaded %s %p (thisldr=%p clazz=%p)\n",
1300 descriptor, clazz->classLoader, loader, clazz);
1301
1302bail:
1303 dvmReleaseTrackedAlloc((Object*)nameObj, NULL);
1304 free(dotName);
1305 return clazz;
1306}
1307
1308/*
1309 * Load the named class (by descriptor) from the specified DEX file.
1310 * Used by class loaders to instantiate a class object from a
1311 * VM-managed DEX.
1312 */
1313ClassObject* dvmDefineClass(DvmDex* pDvmDex, const char* descriptor,
1314 Object* classLoader)
1315{
1316 assert(pDvmDex != NULL);
1317
1318 return findClassNoInit(descriptor, classLoader, pDvmDex);
1319}
1320
1321
1322/*
1323 * Find the named class (by descriptor), scanning through the
1324 * bootclasspath if it hasn't already been loaded.
1325 *
1326 * "descriptor" looks like "Landroid/debug/Stuff;".
1327 *
1328 * Uses NULL as the defining class loader.
1329 */
1330ClassObject* dvmFindSystemClass(const char* descriptor)
1331{
1332 ClassObject* clazz;
1333
1334 clazz = dvmFindSystemClassNoInit(descriptor);
1335 if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1336 /* initialize class */
1337 if (!dvmInitClass(clazz)) {
1338 /* init failed; leave it in the list, marked as bad */
1339 assert(dvmCheckException(dvmThreadSelf()));
1340 assert(clazz->status == CLASS_ERROR);
1341 return NULL;
1342 }
1343 }
1344
1345 return clazz;
1346}
1347
1348/*
1349 * Find the named class (by descriptor), searching for it in the
1350 * bootclasspath.
1351 *
1352 * On failure, this returns NULL with an exception raised.
1353 */
1354ClassObject* dvmFindSystemClassNoInit(const char* descriptor)
1355{
1356 return findClassNoInit(descriptor, NULL, NULL);
1357}
1358
1359/*
1360 * Find the named class (by descriptor). If it's not already loaded,
1361 * we load it and link it, but don't execute <clinit>. (The VM has
1362 * specific limitations on which events can cause initialization.)
1363 *
1364 * If "pDexFile" is NULL, we will search the bootclasspath for an entry.
1365 *
1366 * On failure, this returns NULL with an exception raised.
1367 *
1368 * TODO: we need to return an indication of whether we loaded the class or
1369 * used an existing definition. If somebody deliberately tries to load a
1370 * class twice in the same class loader, they should get a LinkageError,
1371 * but inadvertent simultaneous class references should "just work".
1372 */
1373static ClassObject* findClassNoInit(const char* descriptor, Object* loader,
1374 DvmDex* pDvmDex)
1375{
1376 Thread* self = dvmThreadSelf();
1377 ClassObject* clazz;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001378 bool profilerNotified = false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001379
1380 if (loader != NULL) {
1381 LOGVV("#### findClassNoInit(%s,%p,%p)\n", descriptor, loader,
1382 pDvmDex->pDexFile);
1383 }
1384
1385 /*
1386 * We don't expect an exception to be raised at this point. The
1387 * exception handling code is good about managing this. This *can*
1388 * happen if a JNI lookup fails and the JNI code doesn't do any
1389 * error checking before doing another class lookup, so we may just
1390 * want to clear this and restore it on exit. If we don't, some kinds
1391 * of failures can't be detected without rearranging other stuff.
1392 *
1393 * Most often when we hit this situation it means that something is
1394 * broken in the VM or in JNI code, so I'm keeping it in place (and
1395 * making it an informative abort rather than an assert).
1396 */
1397 if (dvmCheckException(self)) {
Andy McFadden504e9f42009-09-15 20:01:40 -07001398 LOGE("Class lookup %s attempted while exception %s pending\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001399 descriptor, dvmGetException(self)->clazz->descriptor);
1400 dvmDumpAllThreads(false);
1401 dvmAbort();
1402 }
1403
1404 clazz = dvmLookupClass(descriptor, loader, true);
1405 if (clazz == NULL) {
1406 const DexClassDef* pClassDef;
1407
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001408 dvmMethodTraceClassPrepBegin();
1409 profilerNotified = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001410
1411#if LOG_CLASS_LOADING
1412 u8 startTime = dvmGetThreadCpuTimeNsec();
1413#endif
1414
1415 if (pDvmDex == NULL) {
1416 assert(loader == NULL); /* shouldn't be here otherwise */
1417 pDvmDex = searchBootPathForClass(descriptor, &pClassDef);
1418 } else {
1419 pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
1420 }
1421
1422 if (pDvmDex == NULL || pClassDef == NULL) {
Andy McFadden7fc3ce82009-07-14 15:57:23 -07001423 if (gDvm.noClassDefFoundErrorObj != NULL) {
1424 /* usual case -- use prefabricated object */
1425 dvmSetException(self, gDvm.noClassDefFoundErrorObj);
1426 } else {
1427 /* dexopt case -- can't guarantee prefab (core.jar) */
1428 dvmThrowExceptionWithClassMessage(
1429 "Ljava/lang/NoClassDefFoundError;", descriptor);
1430 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001431 goto bail;
1432 }
1433
1434 /* found a match, try to load it */
1435 clazz = loadClassFromDex(pDvmDex, pClassDef, loader);
1436 if (dvmCheckException(self)) {
1437 /* class was found but had issues */
Andy McFaddena0b525d2010-08-04 12:47:21 -07001438 if (clazz != NULL) {
1439 dvmFreeClassInnards(clazz);
1440 dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1441 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001442 goto bail;
1443 }
1444
1445 /*
1446 * Lock the class while we link it so other threads must wait for us
1447 * to finish. Set the "initThreadId" so we can identify recursive
1448 * invocation.
1449 */
1450 dvmLockObject(self, (Object*) clazz);
1451 clazz->initThreadId = self->threadId;
1452
1453 /*
1454 * Add to hash table so lookups succeed.
1455 *
1456 * [Are circular references possible when linking a class?]
1457 */
1458 assert(clazz->classLoader == loader);
1459 if (!dvmAddClassToHash(clazz)) {
1460 /*
1461 * Another thread must have loaded the class after we
1462 * started but before we finished. Discard what we've
1463 * done and leave some hints for the GC.
1464 *
1465 * (Yes, this happens.)
1466 */
1467 //LOGW("WOW: somebody loaded %s simultaneously\n", descriptor);
1468 clazz->initThreadId = 0;
1469 dvmUnlockObject(self, (Object*) clazz);
1470
1471 /* Let the GC free the class.
1472 */
Andy McFaddena0b525d2010-08-04 12:47:21 -07001473 dvmFreeClassInnards(clazz);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001474 dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1475
1476 /* Grab the winning class.
1477 */
1478 clazz = dvmLookupClass(descriptor, loader, true);
1479 assert(clazz != NULL);
1480 goto got_class;
1481 }
1482 dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1483
1484#if LOG_CLASS_LOADING
1485 logClassLoadWithTime('>', clazz, startTime);
1486#endif
1487 /*
1488 * Prepare and resolve.
1489 */
Barry Hayesc49db852010-05-14 13:43:34 -07001490 if (!dvmLinkClass(clazz)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001491 assert(dvmCheckException(self));
1492
1493 /* Make note of the error and clean up the class.
1494 */
1495 removeClassFromHash(clazz);
1496 clazz->status = CLASS_ERROR;
1497 dvmFreeClassInnards(clazz);
1498
1499 /* Let any waiters know.
1500 */
1501 clazz->initThreadId = 0;
1502 dvmObjectNotifyAll(self, (Object*) clazz);
1503 dvmUnlockObject(self, (Object*) clazz);
1504
1505#if LOG_CLASS_LOADING
1506 LOG(LOG_INFO, "DVMLINK FAILED FOR CLASS ", "%s in %s\n",
1507 clazz->descriptor, get_process_name());
1508
1509 /*
1510 * TODO: It would probably be better to use a new type code here (instead of '<') to
1511 * indicate the failure. This change would require a matching change in the parser
1512 * and analysis code in frameworks/base/tools/preload.
1513 */
1514 logClassLoad('<', clazz);
1515#endif
1516 clazz = NULL;
1517 if (gDvm.optimizing) {
1518 /* happens with "external" libs */
1519 LOGV("Link of class '%s' failed\n", descriptor);
1520 } else {
1521 LOGW("Link of class '%s' failed\n", descriptor);
1522 }
1523 goto bail;
1524 }
1525 dvmObjectNotifyAll(self, (Object*) clazz);
1526 dvmUnlockObject(self, (Object*) clazz);
1527
1528 /*
1529 * Add class stats to global counters.
1530 *
1531 * TODO: these should probably be atomic ops.
1532 */
1533 gDvm.numLoadedClasses++;
1534 gDvm.numDeclaredMethods +=
1535 clazz->virtualMethodCount + clazz->directMethodCount;
1536 gDvm.numDeclaredInstFields += clazz->ifieldCount;
1537 gDvm.numDeclaredStaticFields += clazz->sfieldCount;
1538
1539 /*
1540 * Cache pointers to basic classes. We want to use these in
1541 * various places, and it's easiest to initialize them on first
1542 * use rather than trying to force them to initialize (startup
1543 * ordering makes it weird).
1544 */
1545 if (gDvm.classJavaLangObject == NULL &&
1546 strcmp(descriptor, "Ljava/lang/Object;") == 0)
1547 {
1548 /* It should be impossible to get here with anything
1549 * but the bootclasspath loader.
1550 */
1551 assert(loader == NULL);
1552 gDvm.classJavaLangObject = clazz;
1553 }
1554
1555#if LOG_CLASS_LOADING
1556 logClassLoad('<', clazz);
1557#endif
1558
1559 } else {
1560got_class:
1561 if (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1562 /*
1563 * We can race with other threads for class linking. We should
1564 * never get here recursively; doing so indicates that two
1565 * classes have circular dependencies.
1566 *
1567 * One exception: we force discovery of java.lang.Class in
1568 * dvmLinkClass(), and Class has Object as its superclass. So
1569 * if the first thing we ever load is Object, we will init
1570 * Object->Class->Object. The easiest way to avoid this is to
1571 * ensure that Object is never the first thing we look up, so
1572 * we get Foo->Class->Object instead.
1573 */
1574 dvmLockObject(self, (Object*) clazz);
1575 if (!dvmIsClassLinked(clazz) &&
1576 clazz->initThreadId == self->threadId)
1577 {
1578 LOGW("Recursive link on class %s\n", clazz->descriptor);
1579 dvmUnlockObject(self, (Object*) clazz);
1580 dvmThrowExceptionWithClassMessage(
1581 "Ljava/lang/ClassCircularityError;", clazz->descriptor);
1582 clazz = NULL;
1583 goto bail;
1584 }
1585 //LOGI("WAITING for '%s' (owner=%d)\n",
1586 // clazz->descriptor, clazz->initThreadId);
1587 while (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1588 dvmObjectWait(self, (Object*) clazz, 0, 0, false);
1589 }
1590 dvmUnlockObject(self, (Object*) clazz);
1591 }
1592 if (clazz->status == CLASS_ERROR) {
1593 /*
1594 * Somebody else tried to load this and failed. We need to raise
1595 * an exception and report failure.
1596 */
1597 throwEarlierClassFailure(clazz);
1598 clazz = NULL;
1599 goto bail;
1600 }
1601 }
1602
1603 /* check some invariants */
1604 assert(dvmIsClassLinked(clazz));
1605 assert(gDvm.classJavaLangClass != NULL);
1606 assert(clazz->obj.clazz == gDvm.classJavaLangClass);
Andy McFadden9ef5ca62010-10-05 17:02:54 -07001607 assert(clazz == gDvm.classJavaLangObject || clazz->super != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001608 if (!dvmIsInterfaceClass(clazz)) {
1609 //LOGI("class=%s vtableCount=%d, virtualMeth=%d\n",
1610 // clazz->descriptor, clazz->vtableCount,
1611 // clazz->virtualMethodCount);
1612 assert(clazz->vtableCount >= clazz->virtualMethodCount);
1613 }
1614
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001615bail:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001616 if (profilerNotified)
1617 dvmMethodTraceClassPrepEnd();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001618 assert(clazz != NULL || dvmCheckException(self));
1619 return clazz;
1620}
1621
1622/*
1623 * Helper for loadClassFromDex, which takes a DexClassDataHeader and
1624 * encoded data pointer in addition to the other arguments.
1625 */
1626static ClassObject* loadClassFromDex0(DvmDex* pDvmDex,
1627 const DexClassDef* pClassDef, const DexClassDataHeader* pHeader,
1628 const u1* pEncodedData, Object* classLoader)
1629{
1630 ClassObject* newClass = NULL;
1631 const DexFile* pDexFile;
1632 const char* descriptor;
1633 int i;
1634
1635 pDexFile = pDvmDex->pDexFile;
1636 descriptor = dexGetClassDescriptor(pDexFile, pClassDef);
1637
1638 /*
1639 * Make sure the aren't any "bonus" flags set, since we use them for
1640 * runtime state.
1641 */
1642 if ((pClassDef->accessFlags & ~EXPECTED_FILE_FLAGS) != 0) {
1643 LOGW("Invalid file flags in class %s: %04x\n",
1644 descriptor, pClassDef->accessFlags);
1645 return NULL;
1646 }
1647
1648 /*
1649 * Allocate storage for the class object on the GC heap, so that other
1650 * objects can have references to it. We bypass the usual mechanism
1651 * (allocObject), because we don't have all the bits and pieces yet.
1652 *
1653 * Note that we assume that java.lang.Class does not override
1654 * finalize().
1655 */
Barry Hayesc49db852010-05-14 13:43:34 -07001656 /* TODO: Can there be fewer special checks in the usual path? */
1657 assert(descriptor != NULL);
1658 if (classLoader == NULL &&
1659 strcmp(descriptor, "Ljava/lang/Class;") == 0) {
1660 assert(gDvm.classJavaLangClass != NULL);
1661 newClass = gDvm.classJavaLangClass;
1662 } else {
1663 size_t size = classObjectSize(pHeader->staticFieldsSize);
1664 newClass = (ClassObject*) dvmMalloc(size, ALLOC_DEFAULT);
1665 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001666 if (newClass == NULL)
1667 return NULL;
1668
Barry Hayesc49db852010-05-14 13:43:34 -07001669 DVM_OBJECT_INIT(&newClass->obj, gDvm.classJavaLangClass);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001670 dvmSetClassSerialNumber(newClass);
1671 newClass->descriptor = descriptor;
1672 assert(newClass->descriptorAlloc == NULL);
1673 newClass->accessFlags = pClassDef->accessFlags;
Barry Hayes364f9d92010-06-11 16:12:47 -07001674 dvmSetFieldObject((Object *)newClass,
1675 offsetof(ClassObject, classLoader),
1676 (Object *)classLoader);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001677 newClass->pDvmDex = pDvmDex;
1678 newClass->primitiveType = PRIM_NOT;
Barry Hayesc49db852010-05-14 13:43:34 -07001679 newClass->status = CLASS_IDX;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001680
1681 /*
1682 * Stuff the superclass index into the object pointer field. The linker
1683 * pulls it out and replaces it with a resolved ClassObject pointer.
1684 * I'm doing it this way (rather than having a dedicated superclassIdx
1685 * field) to save a few bytes of overhead per class.
1686 *
1687 * newClass->super is not traversed or freed by dvmFreeClassInnards, so
1688 * this is safe.
1689 */
Barry Hayesc49db852010-05-14 13:43:34 -07001690 assert(sizeof(u4) == sizeof(ClassObject*)); /* 32-bit check */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001691 newClass->super = (ClassObject*) pClassDef->superclassIdx;
1692
1693 /*
1694 * Stuff class reference indices into the pointer fields.
1695 *
1696 * The elements of newClass->interfaces are not traversed or freed by
1697 * dvmFreeClassInnards, so this is GC-safe.
1698 */
1699 const DexTypeList* pInterfacesList;
1700 pInterfacesList = dexGetInterfacesList(pDexFile, pClassDef);
1701 if (pInterfacesList != NULL) {
1702 newClass->interfaceCount = pInterfacesList->size;
1703 newClass->interfaces = (ClassObject**) dvmLinearAlloc(classLoader,
1704 newClass->interfaceCount * sizeof(ClassObject*));
1705
1706 for (i = 0; i < newClass->interfaceCount; i++) {
1707 const DexTypeItem* pType = dexGetTypeItem(pInterfacesList, i);
1708 newClass->interfaces[i] = (ClassObject*)(u4) pType->typeIdx;
1709 }
1710 dvmLinearReadOnly(classLoader, newClass->interfaces);
1711 }
1712
1713 /* load field definitions */
1714
1715 /*
Barry Hayes03aa70a2010-03-01 15:49:41 -08001716 * Over-allocate the class object and append static field info
1717 * onto the end. It's fixed-size and known at alloc time. This
1718 * seems to increase zygote sharing. Heap compaction will have to
1719 * be careful if it ever tries to move ClassObject instances,
1720 * because we pass Field pointers around internally. But at least
1721 * now these Field pointers are in the object heap.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001722 */
1723
1724 if (pHeader->staticFieldsSize != 0) {
1725 /* static fields stay on system heap; field data isn't "write once" */
1726 int count = (int) pHeader->staticFieldsSize;
1727 u4 lastIndex = 0;
1728 DexField field;
1729
1730 newClass->sfieldCount = count;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001731 for (i = 0; i < count; i++) {
1732 dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1733 loadSFieldFromDex(newClass, &field, &newClass->sfields[i]);
1734 }
1735 }
1736
1737 if (pHeader->instanceFieldsSize != 0) {
1738 int count = (int) pHeader->instanceFieldsSize;
1739 u4 lastIndex = 0;
1740 DexField field;
1741
1742 newClass->ifieldCount = count;
1743 newClass->ifields = (InstField*) dvmLinearAlloc(classLoader,
1744 count * sizeof(InstField));
1745 for (i = 0; i < count; i++) {
1746 dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1747 loadIFieldFromDex(newClass, &field, &newClass->ifields[i]);
1748 }
1749 dvmLinearReadOnly(classLoader, newClass->ifields);
1750 }
1751
The Android Open Source Project99409882009-03-18 22:20:24 -07001752 /*
1753 * Load method definitions. We do this in two batches, direct then
1754 * virtual.
1755 *
1756 * If register maps have already been generated for this class, and
1757 * precise GC is enabled, we pull out pointers to them. We know that
1758 * they were streamed to the DEX file in the same order in which the
1759 * methods appear.
1760 *
1761 * If the class wasn't pre-verified, the maps will be generated when
1762 * the class is verified during class initialization.
1763 */
1764 u4 classDefIdx = dexGetIndexForClassDef(pDexFile, pClassDef);
1765 const void* classMapData;
1766 u4 numMethods;
1767
1768 if (gDvm.preciseGc) {
1769 classMapData =
Andy McFaddend45a8872009-03-24 20:41:52 -07001770 dvmRegisterMapGetClassData(pDexFile, classDefIdx, &numMethods);
The Android Open Source Project99409882009-03-18 22:20:24 -07001771
1772 /* sanity check */
1773 if (classMapData != NULL &&
1774 pHeader->directMethodsSize + pHeader->virtualMethodsSize != numMethods)
1775 {
1776 LOGE("ERROR: in %s, direct=%d virtual=%d, maps have %d\n",
1777 newClass->descriptor, pHeader->directMethodsSize,
1778 pHeader->virtualMethodsSize, numMethods);
1779 assert(false);
1780 classMapData = NULL; /* abandon */
1781 }
1782 } else {
1783 classMapData = NULL;
1784 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001785
1786 if (pHeader->directMethodsSize != 0) {
1787 int count = (int) pHeader->directMethodsSize;
1788 u4 lastIndex = 0;
1789 DexMethod method;
1790
1791 newClass->directMethodCount = count;
1792 newClass->directMethods = (Method*) dvmLinearAlloc(classLoader,
1793 count * sizeof(Method));
1794 for (i = 0; i < count; i++) {
1795 dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1796 loadMethodFromDex(newClass, &method, &newClass->directMethods[i]);
The Android Open Source Project99409882009-03-18 22:20:24 -07001797 if (classMapData != NULL) {
Andy McFaddend45a8872009-03-24 20:41:52 -07001798 const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
1799 if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
The Android Open Source Project99409882009-03-18 22:20:24 -07001800 newClass->directMethods[i].registerMap = pMap;
1801 /* TODO: add rigorous checks */
1802 assert((newClass->directMethods[i].registersSize+7) / 8 ==
1803 newClass->directMethods[i].registerMap->regWidth);
1804 }
1805 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001806 }
1807 dvmLinearReadOnly(classLoader, newClass->directMethods);
1808 }
1809
1810 if (pHeader->virtualMethodsSize != 0) {
1811 int count = (int) pHeader->virtualMethodsSize;
1812 u4 lastIndex = 0;
1813 DexMethod method;
1814
1815 newClass->virtualMethodCount = count;
1816 newClass->virtualMethods = (Method*) dvmLinearAlloc(classLoader,
1817 count * sizeof(Method));
1818 for (i = 0; i < count; i++) {
1819 dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1820 loadMethodFromDex(newClass, &method, &newClass->virtualMethods[i]);
The Android Open Source Project99409882009-03-18 22:20:24 -07001821 if (classMapData != NULL) {
Andy McFaddend45a8872009-03-24 20:41:52 -07001822 const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
1823 if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
The Android Open Source Project99409882009-03-18 22:20:24 -07001824 newClass->virtualMethods[i].registerMap = pMap;
1825 /* TODO: add rigorous checks */
1826 assert((newClass->virtualMethods[i].registersSize+7) / 8 ==
1827 newClass->virtualMethods[i].registerMap->regWidth);
1828 }
1829 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001830 }
1831 dvmLinearReadOnly(classLoader, newClass->virtualMethods);
1832 }
1833
1834 newClass->sourceFile = dexGetSourceFile(pDexFile, pClassDef);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001835
1836 /* caller must call dvmReleaseTrackedAlloc */
1837 return newClass;
1838}
1839
1840/*
1841 * Try to load the indicated class from the specified DEX file.
1842 *
1843 * This is effectively loadClass()+defineClass() for a DexClassDef. The
1844 * loading was largely done when we crunched through the DEX.
1845 *
1846 * Returns NULL on failure. If we locate the class but encounter an error
1847 * while processing it, an appropriate exception is thrown.
1848 */
1849static ClassObject* loadClassFromDex(DvmDex* pDvmDex,
1850 const DexClassDef* pClassDef, Object* classLoader)
1851{
1852 ClassObject* result;
1853 DexClassDataHeader header;
1854 const u1* pEncodedData;
1855 const DexFile* pDexFile;
1856
1857 assert((pDvmDex != NULL) && (pClassDef != NULL));
1858 pDexFile = pDvmDex->pDexFile;
1859
1860 if (gDvm.verboseClass) {
1861 LOGV("CLASS: loading '%s'...\n",
1862 dexGetClassDescriptor(pDexFile, pClassDef));
1863 }
1864
1865 pEncodedData = dexGetClassData(pDexFile, pClassDef);
1866
1867 if (pEncodedData != NULL) {
1868 dexReadClassDataHeader(&pEncodedData, &header);
1869 } else {
1870 // Provide an all-zeroes header for the rest of the loading.
1871 memset(&header, 0, sizeof(header));
1872 }
1873
1874 result = loadClassFromDex0(pDvmDex, pClassDef, &header, pEncodedData,
1875 classLoader);
1876
1877 if (gDvm.verboseClass && (result != NULL)) {
1878 LOGI("[Loaded %s from DEX %p (cl=%p)]\n",
1879 result->descriptor, pDvmDex, classLoader);
1880 }
1881
1882 return result;
1883}
1884
1885/*
1886 * Free anything in a ClassObject that was allocated on the system heap.
1887 *
1888 * The ClassObject itself is allocated on the GC heap, so we leave it for
1889 * the garbage collector.
1890 *
1891 * NOTE: this may be called with a partially-constructed object.
1892 * NOTE: there is no particular ordering imposed, so don't go poking at
1893 * superclasses.
1894 */
1895void dvmFreeClassInnards(ClassObject* clazz)
1896{
1897 void *tp;
1898 int i;
1899
1900 if (clazz == NULL)
1901 return;
1902
Barry Hayesc49db852010-05-14 13:43:34 -07001903 assert(clazz->obj.clazz == gDvm.classJavaLangClass);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001904
1905 /* Guarantee that dvmFreeClassInnards can be called on a given
1906 * class multiple times by clearing things out as we free them.
1907 * We don't make any attempt at real atomicity here; higher
1908 * levels need to make sure that no two threads can free the
1909 * same ClassObject at the same time.
1910 *
1911 * TODO: maybe just make it so the GC will never free the
1912 * innards of an already-freed class.
1913 *
1914 * TODO: this #define isn't MT-safe -- the compiler could rearrange it.
1915 */
1916#define NULL_AND_FREE(p) \
1917 do { \
1918 if ((p) != NULL) { \
1919 tp = (p); \
1920 (p) = NULL; \
1921 free(tp); \
1922 } \
1923 } while (0)
1924#define NULL_AND_LINEAR_FREE(p) \
1925 do { \
1926 if ((p) != NULL) { \
1927 tp = (p); \
1928 (p) = NULL; \
1929 dvmLinearFree(clazz->classLoader, tp); \
1930 } \
1931 } while (0)
1932
1933 /* arrays just point at Object's vtable; don't free vtable in this case.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001934 */
1935 clazz->vtableCount = -1;
Barry Hayes33a192e2010-06-29 11:14:20 -07001936 if (clazz->vtable == gDvm.classJavaLangObject->vtable) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001937 clazz->vtable = NULL;
1938 } else {
1939 NULL_AND_LINEAR_FREE(clazz->vtable);
1940 }
1941
1942 clazz->descriptor = NULL;
1943 NULL_AND_FREE(clazz->descriptorAlloc);
1944
1945 if (clazz->directMethods != NULL) {
1946 Method *directMethods = clazz->directMethods;
1947 int directMethodCount = clazz->directMethodCount;
1948 clazz->directMethods = NULL;
1949 clazz->directMethodCount = -1;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001950 dvmLinearReadWrite(clazz->classLoader, directMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001951 for (i = 0; i < directMethodCount; i++) {
1952 freeMethodInnards(&directMethods[i]);
1953 }
Andy McFaddenb51ea112009-05-08 16:50:17 -07001954 dvmLinearReadOnly(clazz->classLoader, directMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001955 dvmLinearFree(clazz->classLoader, directMethods);
1956 }
1957 if (clazz->virtualMethods != NULL) {
1958 Method *virtualMethods = clazz->virtualMethods;
1959 int virtualMethodCount = clazz->virtualMethodCount;
1960 clazz->virtualMethodCount = -1;
1961 clazz->virtualMethods = NULL;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001962 dvmLinearReadWrite(clazz->classLoader, virtualMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001963 for (i = 0; i < virtualMethodCount; i++) {
1964 freeMethodInnards(&virtualMethods[i]);
1965 }
Andy McFaddenb51ea112009-05-08 16:50:17 -07001966 dvmLinearReadOnly(clazz->classLoader, virtualMethods);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001967 dvmLinearFree(clazz->classLoader, virtualMethods);
1968 }
1969
Barry Hayes2c987472009-04-06 10:03:48 -07001970 InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz);
1971 loaderList->initiatingLoaderCount = -1;
1972 NULL_AND_FREE(loaderList->initiatingLoaders);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001973
1974 clazz->interfaceCount = -1;
1975 NULL_AND_LINEAR_FREE(clazz->interfaces);
1976
1977 clazz->iftableCount = -1;
1978 NULL_AND_LINEAR_FREE(clazz->iftable);
1979
1980 clazz->ifviPoolCount = -1;
1981 NULL_AND_LINEAR_FREE(clazz->ifviPool);
1982
1983 clazz->sfieldCount = -1;
Barry Hayes03aa70a2010-03-01 15:49:41 -08001984 /* The sfields are attached to the ClassObject, and will be freed
1985 * with it. */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001986
1987 clazz->ifieldCount = -1;
1988 NULL_AND_LINEAR_FREE(clazz->ifields);
1989
1990#undef NULL_AND_FREE
1991#undef NULL_AND_LINEAR_FREE
1992}
1993
1994/*
1995 * Free anything in a Method that was allocated on the system heap.
The Android Open Source Project99409882009-03-18 22:20:24 -07001996 *
1997 * The containing class is largely torn down by this point.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001998 */
1999static void freeMethodInnards(Method* meth)
2000{
2001#if 0
2002 free(meth->exceptions);
2003 free(meth->lines);
2004 free(meth->locals);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002005#endif
The Android Open Source Project99409882009-03-18 22:20:24 -07002006
2007 /*
2008 * Some register maps are allocated on the heap, either because of late
2009 * verification or because we're caching an uncompressed form.
2010 */
2011 const RegisterMap* pMap = meth->registerMap;
Andy McFaddend45a8872009-03-24 20:41:52 -07002012 if (pMap != NULL && dvmRegisterMapGetOnHeap(pMap)) {
The Android Open Source Project99409882009-03-18 22:20:24 -07002013 dvmFreeRegisterMap((RegisterMap*) pMap);
2014 meth->registerMap = NULL;
2015 }
Andy McFaddenb51ea112009-05-08 16:50:17 -07002016
2017 /*
2018 * We may have copied the instructions.
2019 */
2020 if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
2021 DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2022 dvmLinearFree(meth->clazz->classLoader, methodDexCode);
2023 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002024}
2025
2026/*
2027 * Clone a Method, making new copies of anything that will be freed up
The Android Open Source Project99409882009-03-18 22:20:24 -07002028 * by freeMethodInnards(). This is used for "miranda" methods.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002029 */
2030static void cloneMethod(Method* dst, const Method* src)
2031{
The Android Open Source Project99409882009-03-18 22:20:24 -07002032 if (src->registerMap != NULL) {
2033 LOGE("GLITCH: only expected abstract methods here\n");
2034 LOGE(" cloning %s.%s\n", src->clazz->descriptor, src->name);
2035 dvmAbort();
2036 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002037 memcpy(dst, src, sizeof(Method));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002038}
2039
2040/*
2041 * Pull the interesting pieces out of a DexMethod.
2042 *
2043 * The DEX file isn't going anywhere, so we don't need to make copies of
2044 * the code area.
2045 */
2046static void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,
2047 Method* meth)
2048{
2049 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2050 const DexMethodId* pMethodId;
2051 const DexCode* pDexCode;
2052
2053 pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
2054
2055 meth->name = dexStringById(pDexFile, pMethodId->nameIdx);
2056 dexProtoSetFromMethodId(&meth->prototype, pDexFile, pMethodId);
2057 meth->shorty = dexProtoGetShorty(&meth->prototype);
2058 meth->accessFlags = pDexMethod->accessFlags;
2059 meth->clazz = clazz;
2060 meth->jniArgInfo = 0;
2061
2062 if (dvmCompareNameDescriptorAndMethod("finalize", "()V", meth) == 0) {
2063 SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2064 }
2065
2066 pDexCode = dexGetCode(pDexFile, pDexMethod);
2067 if (pDexCode != NULL) {
2068 /* integer constants, copy over for faster access */
2069 meth->registersSize = pDexCode->registersSize;
2070 meth->insSize = pDexCode->insSize;
2071 meth->outsSize = pDexCode->outsSize;
2072
2073 /* pointer to code area */
2074 meth->insns = pDexCode->insns;
2075 } else {
2076 /*
2077 * We don't have a DexCode block, but we still want to know how
2078 * much space is needed for the arguments (so we don't have to
2079 * compute it later). We also take this opportunity to compute
2080 * JNI argument info.
2081 *
2082 * We do this for abstract methods as well, because we want to
2083 * be able to substitute our exception-throwing "stub" in.
2084 */
2085 int argsSize = dvmComputeMethodArgsSize(meth);
2086 if (!dvmIsStaticMethod(meth))
2087 argsSize++;
2088 meth->registersSize = meth->insSize = argsSize;
2089 assert(meth->outsSize == 0);
2090 assert(meth->insns == NULL);
2091
2092 if (dvmIsNativeMethod(meth)) {
2093 meth->nativeFunc = dvmResolveNativeMethod;
2094 meth->jniArgInfo = computeJniArgInfo(&meth->prototype);
2095 }
2096 }
2097}
2098
Andy McFadden96516932009-10-28 17:39:02 -07002099#if 0 /* replaced with private/read-write mapping */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002100/*
Andy McFaddenb51ea112009-05-08 16:50:17 -07002101 * We usually map bytecode directly out of the DEX file, which is mapped
2102 * shared read-only. If we want to be able to modify it, we have to make
2103 * a new copy.
2104 *
2105 * Once copied, the code will be in the LinearAlloc region, which may be
2106 * marked read-only.
2107 *
2108 * The bytecode instructions are embedded inside a DexCode structure, so we
2109 * need to copy all of that. (The dvmGetMethodCode function backs up the
2110 * instruction pointer to find the start of the DexCode.)
2111 */
2112void dvmMakeCodeReadWrite(Method* meth)
2113{
2114 DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2115
2116 if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
2117 dvmLinearReadWrite(meth->clazz->classLoader, methodDexCode);
2118 return;
2119 }
2120
2121 assert(!dvmIsNativeMethod(meth) && !dvmIsAbstractMethod(meth));
2122
2123 size_t dexCodeSize = dexGetDexCodeSize(methodDexCode);
2124 LOGD("Making a copy of %s.%s code (%d bytes)\n",
2125 meth->clazz->descriptor, meth->name, dexCodeSize);
2126
2127 DexCode* newCode =
2128 (DexCode*) dvmLinearAlloc(meth->clazz->classLoader, dexCodeSize);
2129 memcpy(newCode, methodDexCode, dexCodeSize);
2130
2131 meth->insns = newCode->insns;
2132 SET_METHOD_FLAG(meth, METHOD_ISWRITABLE);
2133}
2134
2135/*
2136 * Mark the bytecode read-only.
2137 *
2138 * If the contents of the DexCode haven't actually changed, we could revert
2139 * to the original shared page.
2140 */
2141void dvmMakeCodeReadOnly(Method* meth)
2142{
2143 DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2144 LOGV("+++ marking %p read-only\n", methodDexCode);
2145 dvmLinearReadOnly(meth->clazz->classLoader, methodDexCode);
2146}
Andy McFadden96516932009-10-28 17:39:02 -07002147#endif
Andy McFaddenb51ea112009-05-08 16:50:17 -07002148
2149
2150/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002151 * jniArgInfo (32-bit int) layout:
2152 * SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
2153 *
2154 * S - if set, do things the hard way (scan the signature)
2155 * R - return-type enumeration
2156 * H - target-specific hints
2157 *
2158 * This info is used at invocation time by dvmPlatformInvoke. In most
2159 * cases, the target-specific hints allow dvmPlatformInvoke to avoid
2160 * having to fully parse the signature.
2161 *
2162 * The return-type bits are always set, even if target-specific hint bits
2163 * are unavailable.
2164 */
2165static int computeJniArgInfo(const DexProto* proto)
2166{
2167 const char* sig = dexProtoGetShorty(proto);
Carl Shapiroe3c01da2010-05-20 22:54:18 -07002168 int returnType, jniArgInfo;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002169 u4 hints;
2170
2171 /* The first shorty character is the return type. */
2172 switch (*(sig++)) {
2173 case 'V':
2174 returnType = DALVIK_JNI_RETURN_VOID;
2175 break;
2176 case 'F':
2177 returnType = DALVIK_JNI_RETURN_FLOAT;
2178 break;
2179 case 'D':
2180 returnType = DALVIK_JNI_RETURN_DOUBLE;
2181 break;
2182 case 'J':
2183 returnType = DALVIK_JNI_RETURN_S8;
2184 break;
Bill Buzbeee2557512009-07-27 15:51:54 -07002185 case 'Z':
2186 case 'B':
2187 returnType = DALVIK_JNI_RETURN_S1;
2188 break;
2189 case 'C':
2190 returnType = DALVIK_JNI_RETURN_U2;
2191 break;
2192 case 'S':
2193 returnType = DALVIK_JNI_RETURN_S2;
2194 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002195 default:
2196 returnType = DALVIK_JNI_RETURN_S4;
2197 break;
2198 }
2199
2200 jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT;
2201
2202 hints = dvmPlatformInvokeHints(proto);
2203
2204 if (hints & DALVIK_JNI_NO_ARG_INFO) {
2205 jniArgInfo |= DALVIK_JNI_NO_ARG_INFO;
2206 } else {
2207 assert((hints & DALVIK_JNI_RETURN_MASK) == 0);
2208 jniArgInfo |= hints;
2209 }
2210
2211 return jniArgInfo;
2212}
2213
2214/*
2215 * Load information about a static field.
2216 *
2217 * This also "prepares" static fields by initializing them
2218 * to their "standard default values".
2219 */
2220static void loadSFieldFromDex(ClassObject* clazz,
2221 const DexField* pDexSField, StaticField* sfield)
2222{
2223 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2224 const DexFieldId* pFieldId;
2225
2226 pFieldId = dexGetFieldId(pDexFile, pDexSField->fieldIdx);
2227
2228 sfield->field.clazz = clazz;
2229 sfield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2230 sfield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2231 sfield->field.accessFlags = pDexSField->accessFlags;
2232
2233 /* Static object field values are set to "standard default values"
2234 * (null or 0) until the class is initialized. We delay loading
2235 * constant values from the class until that time.
2236 */
2237 //sfield->value.j = 0;
2238 assert(sfield->value.j == 0LL); // cleared earlier with calloc
2239
2240#ifdef PROFILE_FIELD_ACCESS
2241 sfield->field.gets = sfield->field.puts = 0;
2242#endif
2243}
2244
2245/*
2246 * Load information about an instance field.
2247 */
2248static void loadIFieldFromDex(ClassObject* clazz,
2249 const DexField* pDexIField, InstField* ifield)
2250{
2251 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2252 const DexFieldId* pFieldId;
2253
2254 pFieldId = dexGetFieldId(pDexFile, pDexIField->fieldIdx);
2255
2256 ifield->field.clazz = clazz;
2257 ifield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2258 ifield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2259 ifield->field.accessFlags = pDexIField->accessFlags;
2260#ifndef NDEBUG
2261 assert(ifield->byteOffset == 0); // cleared earlier with calloc
2262 ifield->byteOffset = -1; // make it obvious if we fail to set later
2263#endif
2264
2265#ifdef PROFILE_FIELD_ACCESS
2266 ifield->field.gets = ifield->field.puts = 0;
2267#endif
2268}
2269
2270/*
2271 * Cache java.lang.ref.Reference fields and methods.
2272 */
Barry Hayes6daaac12009-07-08 10:01:56 -07002273static bool precacheReferenceOffsets(ClassObject* clazz)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002274{
2275 Method *meth;
2276 int i;
2277
2278 /* We trick the GC object scanner by not counting
2279 * java.lang.ref.Reference.referent as an object
2280 * field. It will get explicitly scanned as part
2281 * of the reference-walking process.
2282 *
2283 * Find the object field named "referent" and put it
2284 * just after the list of object reference fields.
2285 */
2286 dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
2287 for (i = 0; i < clazz->ifieldRefCount; i++) {
2288 InstField *pField = &clazz->ifields[i];
2289 if (strcmp(pField->field.name, "referent") == 0) {
2290 int targetIndex;
2291
2292 /* Swap this field with the last object field.
2293 */
2294 targetIndex = clazz->ifieldRefCount - 1;
2295 if (i != targetIndex) {
2296 InstField *swapField = &clazz->ifields[targetIndex];
2297 InstField tmpField;
2298 int tmpByteOffset;
2299
2300 /* It's not currently strictly necessary
2301 * for the fields to be in byteOffset order,
2302 * but it's more predictable that way.
2303 */
2304 tmpByteOffset = swapField->byteOffset;
2305 swapField->byteOffset = pField->byteOffset;
2306 pField->byteOffset = tmpByteOffset;
2307
2308 tmpField = *swapField;
2309 *swapField = *pField;
2310 *pField = tmpField;
2311 }
2312
2313 /* One fewer object field (wink wink).
2314 */
2315 clazz->ifieldRefCount--;
2316 i--; /* don't trip "didn't find it" test if field was last */
2317 break;
2318 }
2319 }
2320 dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
2321 if (i == clazz->ifieldRefCount) {
2322 LOGE("Unable to reorder 'referent' in %s\n", clazz->descriptor);
2323 return false;
2324 }
2325
2326 /* Cache pretty much everything about Reference so that
2327 * we don't need to call interpreted code when clearing/enqueueing
2328 * references. This is fragile, so we'll be paranoid.
2329 */
2330 gDvm.classJavaLangRefReference = clazz;
2331
2332 gDvm.offJavaLangRefReference_referent =
2333 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2334 "referent", "Ljava/lang/Object;");
2335 assert(gDvm.offJavaLangRefReference_referent >= 0);
2336
2337 gDvm.offJavaLangRefReference_queue =
2338 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2339 "queue", "Ljava/lang/ref/ReferenceQueue;");
2340 assert(gDvm.offJavaLangRefReference_queue >= 0);
2341
2342 gDvm.offJavaLangRefReference_queueNext =
2343 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2344 "queueNext", "Ljava/lang/ref/Reference;");
2345 assert(gDvm.offJavaLangRefReference_queueNext >= 0);
2346
Carl Shapiro2a6f4842010-07-09 16:50:54 -07002347 gDvm.offJavaLangRefReference_pendingNext =
2348 dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2349 "pendingNext", "Ljava/lang/ref/Reference;");
2350 assert(gDvm.offJavaLangRefReference_pendingNext >= 0);
2351
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002352 /* enqueueInternal() is private and thus a direct method. */
2353 meth = dvmFindDirectMethodByDescriptor(clazz, "enqueueInternal", "()Z");
2354 assert(meth != NULL);
2355 gDvm.methJavaLangRefReference_enqueueInternal = meth;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002356
2357 return true;
2358}
2359
2360
2361/*
Barry Hayes6daaac12009-07-08 10:01:56 -07002362 * Set the bitmap of reference offsets, refOffsets, from the ifields
2363 * list.
2364 */
2365static void computeRefOffsets(ClassObject* clazz)
2366{
2367 if (clazz->super != NULL) {
2368 clazz->refOffsets = clazz->super->refOffsets;
2369 } else {
2370 clazz->refOffsets = 0;
2371 }
2372 /*
2373 * If our superclass overflowed, we don't stand a chance.
2374 */
2375 if (clazz->refOffsets != CLASS_WALK_SUPER) {
2376 InstField *f;
2377 int i;
2378
2379 /* All of the fields that contain object references
2380 * are guaranteed to be at the beginning of the ifields list.
2381 */
2382 f = clazz->ifields;
2383 const int ifieldRefCount = clazz->ifieldRefCount;
2384 for (i = 0; i < ifieldRefCount; i++) {
2385 /*
2386 * Note that, per the comment on struct InstField,
2387 * f->byteOffset is the offset from the beginning of
2388 * obj, not the offset into obj->instanceData.
2389 */
Andy McFadden2fbe6d12009-09-04 15:38:13 -07002390 assert(f->byteOffset >= (int) CLASS_SMALLEST_OFFSET);
Barry Hayes6daaac12009-07-08 10:01:56 -07002391 assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
2392 if (CLASS_CAN_ENCODE_OFFSET(f->byteOffset)) {
2393 u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
2394 assert(newBit != 0);
2395 clazz->refOffsets |= newBit;
2396 } else {
2397 clazz->refOffsets = CLASS_WALK_SUPER;
2398 break;
2399 }
2400 f++;
2401 }
2402 }
2403}
2404
2405
2406/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002407 * Link (prepare and resolve). Verification is deferred until later.
2408 *
2409 * This converts symbolic references into pointers. It's independent of
2410 * the source file format.
2411 *
Barry Hayesc49db852010-05-14 13:43:34 -07002412 * If clazz->status is CLASS_IDX, then clazz->super and interfaces[] are
2413 * holding class reference indices rather than pointers. The class
2414 * references will be resolved during link. (This is done when
2415 * loading from DEX to avoid having to create additional storage to
2416 * pass the indices around.)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002417 *
2418 * Returns "false" with an exception pending on failure.
2419 */
Barry Hayesc49db852010-05-14 13:43:34 -07002420bool dvmLinkClass(ClassObject* clazz)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002421{
2422 u4 superclassIdx = 0;
Barry Hayesc49db852010-05-14 13:43:34 -07002423 u4 *interfaceIdxArray = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002424 bool okay = false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002425 int i;
2426
Barry Hayesc49db852010-05-14 13:43:34 -07002427 assert(clazz != NULL);
2428 assert(clazz->descriptor != NULL);
2429 assert(clazz->status == CLASS_IDX || clazz->status == CLASS_LOADED);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002430 if (gDvm.verboseClass)
2431 LOGV("CLASS: linking '%s'...\n", clazz->descriptor);
2432
Barry Hayesc49db852010-05-14 13:43:34 -07002433 assert(gDvm.classJavaLangClass != NULL);
2434 assert(clazz->obj.clazz == gDvm.classJavaLangClass);
2435 if (clazz->classLoader == NULL &&
2436 (strcmp(clazz->descriptor, "Ljava/lang/Class;") == 0))
2437 {
2438 if (gDvm.classJavaLangClass->ifieldCount > CLASS_FIELD_SLOTS) {
2439 LOGE("java.lang.Class has %d instance fields (expected at most %d)",
2440 gDvm.classJavaLangClass->ifieldCount, CLASS_FIELD_SLOTS);
2441 dvmAbort();
2442 }
2443 if (gDvm.classJavaLangClass->sfieldCount != CLASS_SFIELD_SLOTS) {
2444 LOGE("java.lang.Class has %d static fields (expected %d)",
2445 gDvm.classJavaLangClass->sfieldCount, CLASS_SFIELD_SLOTS);
2446 dvmAbort();
2447 }
2448 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002449 /* "Resolve" the class.
2450 *
Barry Hayesc49db852010-05-14 13:43:34 -07002451 * At this point, clazz's reference fields may contain Dex file
2452 * indices instead of direct object references. Proxy objects are
2453 * an exception, and may be the only exception. We need to
2454 * translate those indices into real references, and let the GC
2455 * look inside this ClassObject.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002456 */
Barry Hayesc49db852010-05-14 13:43:34 -07002457 if (clazz->status == CLASS_IDX) {
2458 if (clazz->interfaceCount > 0) {
2459 /* Copy u4 DEX idx values out of the ClassObject* array
2460 * where we stashed them.
2461 */
2462 assert(sizeof(*interfaceIdxArray) == sizeof(*clazz->interfaces));
2463 size_t len = clazz->interfaceCount * sizeof(*interfaceIdxArray);
2464 interfaceIdxArray = malloc(len);
2465 if (interfaceIdxArray == NULL) {
2466 LOGW("Unable to allocate memory to link %s", clazz->descriptor);
2467 goto bail;
Barry Hayes3595a092010-05-24 12:13:30 -07002468 }
Barry Hayesc49db852010-05-14 13:43:34 -07002469 memcpy(interfaceIdxArray, clazz->interfaces, len);
Andy McFadden1145f222010-06-21 12:58:20 -07002470
2471 dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
Barry Hayesc49db852010-05-14 13:43:34 -07002472 memset(clazz->interfaces, 0, len);
Andy McFadden1145f222010-06-21 12:58:20 -07002473 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
Barry Hayesc49db852010-05-14 13:43:34 -07002474 }
2475
2476 assert(sizeof(superclassIdx) == sizeof(clazz->super));
2477 superclassIdx = (u4) clazz->super;
2478 clazz->super = NULL;
2479 /* After this line, clazz will be fair game for the GC. The
2480 * superclass and interfaces are all NULL.
2481 */
2482 clazz->status = CLASS_LOADED;
2483
2484 if (superclassIdx != kDexNoIndex) {
Barry Hayes364f9d92010-06-11 16:12:47 -07002485 ClassObject* super = dvmResolveClass(clazz, superclassIdx, false);
2486 if (super == NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002487 assert(dvmCheckException(dvmThreadSelf()));
Barry Hayesc49db852010-05-14 13:43:34 -07002488 if (gDvm.optimizing) {
2489 /* happens with "external" libs */
2490 LOGV("Unable to resolve superclass of %s (%d)\n",
2491 clazz->descriptor, superclassIdx);
2492 } else {
2493 LOGW("Unable to resolve superclass of %s (%d)\n",
2494 clazz->descriptor, superclassIdx);
2495 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002496 goto bail;
2497 }
Barry Hayes364f9d92010-06-11 16:12:47 -07002498 dvmSetFieldObject((Object *)clazz,
2499 offsetof(ClassObject, super),
2500 (Object *)super);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002501 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002502
Barry Hayesc49db852010-05-14 13:43:34 -07002503 if (clazz->interfaceCount > 0) {
2504 /* Resolve the interfaces implemented directly by this class. */
2505 assert(interfaceIdxArray != NULL);
2506 dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
2507 for (i = 0; i < clazz->interfaceCount; i++) {
2508 assert(interfaceIdxArray[i] != kDexNoIndex);
2509 clazz->interfaces[i] =
2510 dvmResolveClass(clazz, interfaceIdxArray[i], false);
2511 if (clazz->interfaces[i] == NULL) {
2512 const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2513
2514 assert(dvmCheckException(dvmThreadSelf()));
2515 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2516
2517 const char* classDescriptor;
2518 classDescriptor =
2519 dexStringByTypeIdx(pDexFile, interfaceIdxArray[i]);
2520 if (gDvm.optimizing) {
2521 /* happens with "external" libs */
2522 LOGV("Failed resolving %s interface %d '%s'\n",
2523 clazz->descriptor, interfaceIdxArray[i],
2524 classDescriptor);
2525 } else {
2526 LOGI("Failed resolving %s interface %d '%s'\n",
2527 clazz->descriptor, interfaceIdxArray[i],
2528 classDescriptor);
2529 }
2530 goto bail;
2531 }
2532
2533 /* are we allowed to implement this interface? */
2534 if (!dvmCheckClassAccess(clazz, clazz->interfaces[i])) {
2535 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2536 LOGW("Interface '%s' is not accessible to '%s'\n",
2537 clazz->interfaces[i]->descriptor, clazz->descriptor);
2538 dvmThrowException("Ljava/lang/IllegalAccessError;",
2539 "interface not accessible");
2540 goto bail;
2541 }
2542 LOGVV("+++ found interface '%s'\n",
2543 clazz->interfaces[i]->descriptor);
2544 }
2545 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2546 }
2547 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002548 /*
Barry Hayesc49db852010-05-14 13:43:34 -07002549 * There are now Class references visible to the GC in super and
2550 * interfaces.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002551 */
2552
2553 /*
Barry Hayesc49db852010-05-14 13:43:34 -07002554 * All classes have a direct superclass, except for
2555 * java/lang/Object and primitive classes. Primitive classes are
2556 * are created CLASS_INITIALIZED, so won't get here.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002557 */
Barry Hayesc49db852010-05-14 13:43:34 -07002558 assert(clazz->primitiveType == PRIM_NOT);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002559 if (strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0) {
Barry Hayesc49db852010-05-14 13:43:34 -07002560 if (clazz->super != NULL) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002561 /* TODO: is this invariant true for all java/lang/Objects,
2562 * regardless of the class loader? For now, assume it is.
2563 */
2564 dvmThrowException("Ljava/lang/ClassFormatError;",
2565 "java.lang.Object has a superclass");
2566 goto bail;
2567 }
2568
2569 /* Don't finalize objects whose classes use the
2570 * default (empty) Object.finalize().
2571 */
2572 CLEAR_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2573 } else {
Barry Hayesc49db852010-05-14 13:43:34 -07002574 if (clazz->super == NULL) {
2575 dvmThrowException("Ljava/lang/LinkageError;",
2576 "no superclass defined");
2577 goto bail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002578 }
2579 /* verify */
2580 if (dvmIsFinalClass(clazz->super)) {
2581 LOGW("Superclass of '%s' is final '%s'\n",
2582 clazz->descriptor, clazz->super->descriptor);
2583 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2584 "superclass is final");
2585 goto bail;
2586 } else if (dvmIsInterfaceClass(clazz->super)) {
2587 LOGW("Superclass of '%s' is interface '%s'\n",
2588 clazz->descriptor, clazz->super->descriptor);
2589 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2590 "superclass is an interface");
2591 goto bail;
2592 } else if (!dvmCheckClassAccess(clazz, clazz->super)) {
2593 LOGW("Superclass of '%s' (%s) is not accessible\n",
2594 clazz->descriptor, clazz->super->descriptor);
2595 dvmThrowException("Ljava/lang/IllegalAccessError;",
2596 "superclass not accessible");
2597 goto bail;
2598 }
2599
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002600 /* Inherit finalizability from the superclass. If this
2601 * class also overrides finalize(), its CLASS_ISFINALIZABLE
2602 * bit will already be set.
2603 */
2604 if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISFINALIZABLE)) {
2605 SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2606 }
2607
2608 /* See if this class descends from java.lang.Reference
2609 * and set the class flags appropriately.
2610 */
2611 if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISREFERENCE)) {
2612 u4 superRefFlags;
2613
2614 /* We've already determined the reference type of this
2615 * inheritance chain. Inherit reference-ness from the superclass.
2616 */
2617 superRefFlags = GET_CLASS_FLAG_GROUP(clazz->super,
2618 CLASS_ISREFERENCE |
2619 CLASS_ISWEAKREFERENCE |
2620 CLASS_ISPHANTOMREFERENCE);
2621 SET_CLASS_FLAG(clazz, superRefFlags);
2622 } else if (clazz->classLoader == NULL &&
2623 clazz->super->classLoader == NULL &&
2624 strcmp(clazz->super->descriptor,
2625 "Ljava/lang/ref/Reference;") == 0)
2626 {
2627 u4 refFlags;
2628
2629 /* This class extends Reference, which means it should
2630 * be one of the magic Soft/Weak/PhantomReference classes.
2631 */
2632 refFlags = CLASS_ISREFERENCE;
2633 if (strcmp(clazz->descriptor,
2634 "Ljava/lang/ref/SoftReference;") == 0)
2635 {
2636 /* Only CLASS_ISREFERENCE is set for soft references.
2637 */
2638 } else if (strcmp(clazz->descriptor,
2639 "Ljava/lang/ref/WeakReference;") == 0)
2640 {
2641 refFlags |= CLASS_ISWEAKREFERENCE;
2642 } else if (strcmp(clazz->descriptor,
2643 "Ljava/lang/ref/PhantomReference;") == 0)
2644 {
2645 refFlags |= CLASS_ISPHANTOMREFERENCE;
2646 } else {
2647 /* No-one else is allowed to inherit directly
2648 * from Reference.
2649 */
2650//xxx is this the right exception? better than an assertion.
2651 dvmThrowException("Ljava/lang/LinkageError;",
2652 "illegal inheritance from Reference");
2653 goto bail;
2654 }
2655
2656 /* The class should not have any reference bits set yet.
2657 */
2658 assert(GET_CLASS_FLAG_GROUP(clazz,
2659 CLASS_ISREFERENCE |
2660 CLASS_ISWEAKREFERENCE |
2661 CLASS_ISPHANTOMREFERENCE) == 0);
2662
2663 SET_CLASS_FLAG(clazz, refFlags);
2664 }
2665 }
2666
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002667 /*
2668 * Populate vtable.
2669 */
2670 if (dvmIsInterfaceClass(clazz)) {
2671 /* no vtable; just set the method indices */
2672 int count = clazz->virtualMethodCount;
2673
2674 if (count != (u2) count) {
2675 LOGE("Too many methods (%d) in interface '%s'\n", count,
2676 clazz->descriptor);
2677 goto bail;
2678 }
2679
2680 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2681
2682 for (i = 0; i < count; i++)
2683 clazz->virtualMethods[i].methodIndex = (u2) i;
2684
2685 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2686 } else {
2687 if (!createVtable(clazz)) {
2688 LOGW("failed creating vtable\n");
2689 goto bail;
2690 }
2691 }
2692
2693 /*
2694 * Populate interface method tables. Can alter the vtable.
2695 */
2696 if (!createIftable(clazz))
2697 goto bail;
2698
2699 /*
2700 * Insert special-purpose "stub" method implementations.
2701 */
2702 if (!insertMethodStubs(clazz))
2703 goto bail;
2704
2705 /*
2706 * Compute instance field offsets and, hence, the size of the object.
2707 */
2708 if (!computeFieldOffsets(clazz))
2709 goto bail;
2710
2711 /*
2712 * Cache fields and methods from java/lang/ref/Reference and
2713 * java/lang/Class. This has to happen after computeFieldOffsets().
2714 */
2715 if (clazz->classLoader == NULL) {
2716 if (strcmp(clazz->descriptor, "Ljava/lang/ref/Reference;") == 0) {
2717 if (!precacheReferenceOffsets(clazz)) {
2718 LOGE("failed pre-caching Reference offsets\n");
2719 dvmThrowException("Ljava/lang/InternalError;", NULL);
2720 goto bail;
2721 }
2722 } else if (clazz == gDvm.classJavaLangClass) {
2723 gDvm.offJavaLangClass_pd = dvmFindFieldOffset(clazz, "pd",
2724 "Ljava/security/ProtectionDomain;");
2725 if (gDvm.offJavaLangClass_pd <= 0) {
2726 LOGE("ERROR: unable to find 'pd' field in Class\n");
2727 dvmAbort(); /* we're not going to get much farther */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002728 }
2729 }
2730 }
2731
2732 /*
Barry Hayes6daaac12009-07-08 10:01:56 -07002733 * Compact the offsets the GC has to examine into a bitmap, if
2734 * possible. (This has to happen after Reference.referent is
2735 * massaged in precacheReferenceOffsets.)
2736 */
2737 computeRefOffsets(clazz);
2738
2739 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002740 * Done!
2741 */
2742 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED))
2743 clazz->status = CLASS_VERIFIED;
2744 else
2745 clazz->status = CLASS_RESOLVED;
2746 okay = true;
2747 if (gDvm.verboseClass)
2748 LOGV("CLASS: linked '%s'\n", clazz->descriptor);
2749
2750 /*
2751 * We send CLASS_PREPARE events to the debugger from here. The
2752 * definition of "preparation" is creating the static fields for a
2753 * class and initializing them to the standard default values, but not
2754 * executing any code (that comes later, during "initialization").
2755 *
2756 * We did the static prep in loadSFieldFromDex() while loading the class.
2757 *
2758 * The class has been prepared and resolved but possibly not yet verified
2759 * at this point.
2760 */
2761 if (gDvm.debuggerActive) {
2762 dvmDbgPostClassPrepare(clazz);
2763 }
2764
2765bail:
2766 if (!okay) {
2767 clazz->status = CLASS_ERROR;
2768 if (!dvmCheckException(dvmThreadSelf())) {
2769 dvmThrowException("Ljava/lang/VirtualMachineError;", NULL);
2770 }
2771 }
Barry Hayesc49db852010-05-14 13:43:34 -07002772 if (interfaceIdxArray != NULL) {
2773 free(interfaceIdxArray);
2774 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002775 return okay;
2776}
2777
2778/*
2779 * Create the virtual method table.
2780 *
2781 * The top part of the table is a copy of the table from our superclass,
2782 * with our local methods overriding theirs. The bottom part of the table
2783 * has any new methods we defined.
2784 */
2785static bool createVtable(ClassObject* clazz)
2786{
2787 bool result = false;
2788 int maxCount;
2789 int i;
2790
2791 if (clazz->super != NULL) {
2792 //LOGI("SUPER METHODS %d %s->%s\n", clazz->super->vtableCount,
2793 // clazz->descriptor, clazz->super->descriptor);
2794 }
2795
2796 /* the virtual methods we define, plus the superclass vtable size */
2797 maxCount = clazz->virtualMethodCount;
2798 if (clazz->super != NULL) {
2799 maxCount += clazz->super->vtableCount;
2800 } else {
2801 /* TODO: is this invariant true for all java/lang/Objects,
2802 * regardless of the class loader? For now, assume it is.
2803 */
2804 assert(strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0);
2805 }
2806 //LOGD("+++ max vmethods for '%s' is %d\n", clazz->descriptor, maxCount);
2807
2808 /*
2809 * Over-allocate the table, then realloc it down if necessary. So
2810 * long as we don't allocate anything in between we won't cause
2811 * fragmentation, and reducing the size should be unlikely to cause
2812 * a buffer copy.
2813 */
2814 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2815 clazz->vtable = (Method**) dvmLinearAlloc(clazz->classLoader,
2816 sizeof(Method*) * maxCount);
2817 if (clazz->vtable == NULL)
2818 goto bail;
2819
2820 if (clazz->super != NULL) {
2821 int actualCount;
2822
2823 memcpy(clazz->vtable, clazz->super->vtable,
2824 sizeof(*(clazz->vtable)) * clazz->super->vtableCount);
2825 actualCount = clazz->super->vtableCount;
2826
2827 /*
2828 * See if any of our virtual methods override the superclass.
2829 */
2830 for (i = 0; i < clazz->virtualMethodCount; i++) {
2831 Method* localMeth = &clazz->virtualMethods[i];
2832 int si;
2833
2834 for (si = 0; si < clazz->super->vtableCount; si++) {
2835 Method* superMeth = clazz->vtable[si];
2836
2837 if (dvmCompareMethodNamesAndProtos(localMeth, superMeth) == 0)
2838 {
2839 /* verify */
2840 if (dvmIsFinalMethod(superMeth)) {
2841 LOGW("Method %s.%s overrides final %s.%s\n",
2842 localMeth->clazz->descriptor, localMeth->name,
2843 superMeth->clazz->descriptor, superMeth->name);
2844 goto bail;
2845 }
2846 clazz->vtable[si] = localMeth;
2847 localMeth->methodIndex = (u2) si;
2848 //LOGV("+++ override %s.%s (slot %d)\n",
2849 // clazz->descriptor, localMeth->name, si);
2850 break;
2851 }
2852 }
2853
2854 if (si == clazz->super->vtableCount) {
2855 /* not an override, add to end */
2856 clazz->vtable[actualCount] = localMeth;
2857 localMeth->methodIndex = (u2) actualCount;
2858 actualCount++;
2859
2860 //LOGV("+++ add method %s.%s\n",
2861 // clazz->descriptor, localMeth->name);
2862 }
2863 }
2864
2865 if (actualCount != (u2) actualCount) {
2866 LOGE("Too many methods (%d) in class '%s'\n", actualCount,
2867 clazz->descriptor);
2868 goto bail;
2869 }
2870
2871 assert(actualCount <= maxCount);
2872
2873 if (actualCount < maxCount) {
2874 assert(clazz->vtable != NULL);
2875 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2876 clazz->vtable = dvmLinearRealloc(clazz->classLoader, clazz->vtable,
2877 sizeof(*(clazz->vtable)) * actualCount);
2878 if (clazz->vtable == NULL) {
2879 LOGE("vtable realloc failed\n");
2880 goto bail;
2881 } else {
2882 LOGVV("+++ reduced vtable from %d to %d\n",
2883 maxCount, actualCount);
2884 }
2885 }
2886
2887 clazz->vtableCount = actualCount;
2888 } else {
2889 /* java/lang/Object case */
2890 int count = clazz->virtualMethodCount;
2891 if (count != (u2) count) {
2892 LOGE("Too many methods (%d) in base class '%s'\n", count,
2893 clazz->descriptor);
2894 goto bail;
2895 }
2896
2897 for (i = 0; i < count; i++) {
2898 clazz->vtable[i] = &clazz->virtualMethods[i];
2899 clazz->virtualMethods[i].methodIndex = (u2) i;
2900 }
2901 clazz->vtableCount = clazz->virtualMethodCount;
2902 }
2903
2904 result = true;
2905
2906bail:
2907 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2908 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2909 return result;
2910}
2911
2912/*
2913 * Create and populate "iftable".
2914 *
2915 * The set of interfaces we support is the combination of the interfaces
2916 * we implement directly and those implemented by our superclass. Each
2917 * interface can have one or more "superinterfaces", which we must also
2918 * support. For speed we flatten the tree out.
2919 *
2920 * We might be able to speed this up when there are lots of interfaces
2921 * by merge-sorting the class pointers and binary-searching when removing
2922 * duplicates. We could also drop the duplicate removal -- it's only
2923 * there to reduce the memory footprint.
2924 *
2925 * Because of "Miranda methods", this may reallocate clazz->virtualMethods.
2926 *
2927 * Returns "true" on success.
2928 */
2929static bool createIftable(ClassObject* clazz)
2930{
2931 bool result = false;
2932 bool zapIftable = false;
2933 bool zapVtable = false;
2934 bool zapIfvipool = false;
2935 int ifCount, superIfCount, idx;
2936 int i;
2937
2938 if (clazz->super != NULL)
2939 superIfCount = clazz->super->iftableCount;
2940 else
2941 superIfCount = 0;
2942
2943 ifCount = superIfCount;
2944 ifCount += clazz->interfaceCount;
2945 for (i = 0; i < clazz->interfaceCount; i++)
2946 ifCount += clazz->interfaces[i]->iftableCount;
2947
2948 LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d\n",
2949 clazz->descriptor, ifCount - superIfCount, superIfCount, ifCount);
2950
2951 if (ifCount == 0) {
2952 assert(clazz->iftableCount == 0);
2953 assert(clazz->iftable == NULL);
2954 result = true;
2955 goto bail;
2956 }
2957
2958 /*
2959 * Create a table with enough space for all interfaces, and copy the
2960 * superclass' table in.
2961 */
2962 clazz->iftable = (InterfaceEntry*) dvmLinearAlloc(clazz->classLoader,
2963 sizeof(InterfaceEntry) * ifCount);
2964 zapIftable = true;
2965 memset(clazz->iftable, 0x00, sizeof(InterfaceEntry) * ifCount);
2966 if (superIfCount != 0) {
2967 memcpy(clazz->iftable, clazz->super->iftable,
2968 sizeof(InterfaceEntry) * superIfCount);
2969 }
2970
2971 /*
2972 * Create a flattened interface hierarchy of our immediate interfaces.
2973 */
2974 idx = superIfCount;
2975
2976 for (i = 0; i < clazz->interfaceCount; i++) {
2977 ClassObject* interf;
2978 int j;
2979
2980 interf = clazz->interfaces[i];
2981 assert(interf != NULL);
2982
2983 /* make sure this is still an interface class */
2984 if (!dvmIsInterfaceClass(interf)) {
2985 LOGW("Class '%s' implements non-interface '%s'\n",
2986 clazz->descriptor, interf->descriptor);
2987 dvmThrowExceptionWithClassMessage(
2988 "Ljava/lang/IncompatibleClassChangeError;",
2989 clazz->descriptor);
2990 goto bail;
2991 }
2992
2993 /* add entry for this interface */
2994 clazz->iftable[idx++].clazz = interf;
2995
2996 /* add entries for the interface's superinterfaces */
2997 for (j = 0; j < interf->iftableCount; j++) {
2998 clazz->iftable[idx++].clazz = interf->iftable[j].clazz;
2999 }
3000 }
3001
3002 assert(idx == ifCount);
3003
3004 if (false) {
3005 /*
3006 * Remove anything redundant from our recent additions. Note we have
3007 * to traverse the recent adds when looking for duplicates, because
3008 * it's possible the recent additions are self-redundant. This
3009 * reduces the memory footprint of classes with lots of inherited
3010 * interfaces.
3011 *
3012 * (I don't know if this will cause problems later on when we're trying
3013 * to find a static field. It looks like the proper search order is
3014 * (1) current class, (2) interfaces implemented by current class,
3015 * (3) repeat with superclass. A field implemented by an interface
3016 * and by a superclass might come out wrong if the superclass also
3017 * implements the interface. The javac compiler will reject the
3018 * situation as ambiguous, so the concern is somewhat artificial.)
3019 *
3020 * UPDATE: this makes ReferenceType.Interfaces difficult to implement,
3021 * because it wants to return just the interfaces declared to be
3022 * implemented directly by the class. I'm excluding this code for now.
3023 */
3024 for (i = superIfCount; i < ifCount; i++) {
3025 int j;
3026
3027 for (j = 0; j < ifCount; j++) {
3028 if (i == j)
3029 continue;
3030 if (clazz->iftable[i].clazz == clazz->iftable[j].clazz) {
3031 LOGVV("INTF: redundant interface %s in %s\n",
3032 clazz->iftable[i].clazz->descriptor,
3033 clazz->descriptor);
3034
3035 if (i != ifCount-1)
3036 memmove(&clazz->iftable[i], &clazz->iftable[i+1],
3037 (ifCount - i -1) * sizeof(InterfaceEntry));
3038 ifCount--;
3039 i--; // adjust for i++ above
3040 break;
3041 }
3042 }
3043 }
3044 LOGVV("INTF: class '%s' nodupes=%d\n", clazz->descriptor, ifCount);
3045 } // if (false)
3046
3047 clazz->iftableCount = ifCount;
3048
3049 /*
3050 * If we're an interface, we don't need the vtable pointers, so
3051 * we're done. If this class doesn't implement an interface that our
3052 * superclass doesn't have, then we again have nothing to do.
3053 */
3054 if (dvmIsInterfaceClass(clazz) || superIfCount == ifCount) {
3055 //dvmDumpClass(clazz, kDumpClassFullDetail);
3056 result = true;
3057 goto bail;
3058 }
3059
3060 /*
3061 * When we're handling invokeinterface, we probably have an object
3062 * whose type is an interface class rather than a concrete class. We
3063 * need to convert the method reference into a vtable index. So, for
3064 * every entry in "iftable", we create a list of vtable indices.
3065 *
3066 * Because our vtable encompasses the superclass vtable, we can use
3067 * the vtable indices from our superclass for all of the interfaces
3068 * that weren't directly implemented by us.
3069 *
3070 * Each entry in "iftable" has a pointer to the start of its set of
3071 * vtable offsets. The iftable entries in the superclass point to
3072 * storage allocated in the superclass, and the iftable entries added
3073 * for this class point to storage allocated in this class. "iftable"
3074 * is flat for fast access in a class and all of its subclasses, but
3075 * "ifviPool" is only created for the topmost implementor.
3076 */
3077 int poolSize = 0;
3078 for (i = superIfCount; i < ifCount; i++) {
3079 /*
3080 * Note it's valid for an interface to have no methods (e.g.
3081 * java/io/Serializable).
3082 */
3083 LOGVV("INTF: pool: %d from %s\n",
3084 clazz->iftable[i].clazz->virtualMethodCount,
3085 clazz->iftable[i].clazz->descriptor);
3086 poolSize += clazz->iftable[i].clazz->virtualMethodCount;
3087 }
3088
3089 if (poolSize == 0) {
3090 LOGVV("INTF: didn't find any new interfaces with methods\n");
3091 result = true;
3092 goto bail;
3093 }
3094
3095 clazz->ifviPoolCount = poolSize;
3096 clazz->ifviPool = (int*) dvmLinearAlloc(clazz->classLoader,
3097 poolSize * sizeof(int*));
3098 zapIfvipool = true;
3099
3100 /*
3101 * Fill in the vtable offsets for the interfaces that weren't part of
3102 * our superclass.
3103 */
3104 int poolOffset = 0;
3105 Method** mirandaList = NULL;
3106 int mirandaCount = 0, mirandaAlloc = 0;
3107
3108 for (i = superIfCount; i < ifCount; i++) {
3109 ClassObject* interface;
3110 int methIdx;
3111
3112 clazz->iftable[i].methodIndexArray = clazz->ifviPool + poolOffset;
3113 interface = clazz->iftable[i].clazz;
3114 poolOffset += interface->virtualMethodCount; // end here
3115
3116 /*
3117 * For each method listed in the interface's method list, find the
3118 * matching method in our class's method list. We want to favor the
3119 * subclass over the superclass, which just requires walking
3120 * back from the end of the vtable. (This only matters if the
3121 * superclass defines a private method and this class redefines
3122 * it -- otherwise it would use the same vtable slot. In Dalvik
3123 * those don't end up in the virtual method table, so it shouldn't
3124 * matter which direction we go. We walk it backward anyway.)
3125 *
3126 *
3127 * Suppose we have the following arrangement:
3128 * public interface MyInterface
3129 * public boolean inInterface();
3130 * public abstract class MirandaAbstract implements MirandaInterface
3131 * //public abstract boolean inInterface(); // not declared!
3132 * public boolean inAbstract() { stuff } // in vtable
3133 * public class MirandClass extends MirandaAbstract
3134 * public boolean inInterface() { stuff }
3135 * public boolean inAbstract() { stuff } // in vtable
3136 *
3137 * The javac compiler happily compiles MirandaAbstract even though
3138 * it doesn't declare all methods from its interface. When we try
3139 * to set up a vtable for MirandaAbstract, we find that we don't
3140 * have an slot for inInterface. To prevent this, we synthesize
3141 * abstract method declarations in MirandaAbstract.
3142 *
3143 * We have to expand vtable and update some things that point at it,
3144 * so we accumulate the method list and do it all at once below.
3145 */
3146 for (methIdx = 0; methIdx < interface->virtualMethodCount; methIdx++) {
3147 Method* imeth = &interface->virtualMethods[methIdx];
3148 int j;
3149
3150 IF_LOGVV() {
3151 char* desc = dexProtoCopyMethodDescriptor(&imeth->prototype);
3152 LOGVV("INTF: matching '%s' '%s'\n", imeth->name, desc);
3153 free(desc);
3154 }
3155
3156 for (j = clazz->vtableCount-1; j >= 0; j--) {
3157 if (dvmCompareMethodNamesAndProtos(imeth, clazz->vtable[j])
3158 == 0)
3159 {
3160 LOGVV("INTF: matched at %d\n", j);
3161 if (!dvmIsPublicMethod(clazz->vtable[j])) {
3162 LOGW("Implementation of %s.%s is not public\n",
3163 clazz->descriptor, clazz->vtable[j]->name);
3164 dvmThrowException("Ljava/lang/IllegalAccessError;",
3165 "interface implementation not public");
3166 goto bail;
3167 }
3168 clazz->iftable[i].methodIndexArray[methIdx] = j;
3169 break;
3170 }
3171 }
3172 if (j < 0) {
3173 IF_LOGV() {
3174 char* desc =
3175 dexProtoCopyMethodDescriptor(&imeth->prototype);
3176 LOGV("No match for '%s' '%s' in '%s' (creating miranda)\n",
3177 imeth->name, desc, clazz->descriptor);
3178 free(desc);
3179 }
3180 //dvmThrowException("Ljava/lang/RuntimeException;", "Miranda!");
3181 //return false;
3182
3183 if (mirandaCount == mirandaAlloc) {
3184 mirandaAlloc += 8;
3185 if (mirandaList == NULL) {
3186 mirandaList = dvmLinearAlloc(clazz->classLoader,
3187 mirandaAlloc * sizeof(Method*));
3188 } else {
3189 dvmLinearReadOnly(clazz->classLoader, mirandaList);
3190 mirandaList = dvmLinearRealloc(clazz->classLoader,
3191 mirandaList, mirandaAlloc * sizeof(Method*));
3192 }
3193 assert(mirandaList != NULL); // mem failed + we leaked
3194 }
3195
3196 /*
3197 * These may be redundant (e.g. method with same name and
3198 * signature declared in two interfaces implemented by the
3199 * same abstract class). We can squeeze the duplicates
3200 * out here.
3201 */
3202 int mir;
3203 for (mir = 0; mir < mirandaCount; mir++) {
3204 if (dvmCompareMethodNamesAndProtos(
3205 mirandaList[mir], imeth) == 0)
3206 {
3207 IF_LOGVV() {
3208 char* desc = dexProtoCopyMethodDescriptor(
3209 &imeth->prototype);
3210 LOGVV("MIRANDA dupe: %s and %s %s%s\n",
3211 mirandaList[mir]->clazz->descriptor,
3212 imeth->clazz->descriptor,
3213 imeth->name, desc);
3214 free(desc);
3215 }
3216 break;
3217 }
3218 }
3219
3220 /* point the iftable at a phantom slot index */
3221 clazz->iftable[i].methodIndexArray[methIdx] =
3222 clazz->vtableCount + mir;
3223 LOGVV("MIRANDA: %s points at slot %d\n",
3224 imeth->name, clazz->vtableCount + mir);
3225
3226 /* if non-duplicate among Mirandas, add to Miranda list */
3227 if (mir == mirandaCount) {
3228 //LOGV("MIRANDA: holding '%s' in slot %d\n",
3229 // imeth->name, mir);
3230 mirandaList[mirandaCount++] = imeth;
3231 }
3232 }
3233 }
3234 }
3235
3236 if (mirandaCount != 0) {
Andy McFadden68825972009-05-08 11:25:35 -07003237 static const int kManyMirandas = 150; /* arbitrary */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003238 Method* newVirtualMethods;
3239 Method* meth;
3240 int oldMethodCount, oldVtableCount;
3241
3242 for (i = 0; i < mirandaCount; i++) {
3243 LOGVV("MIRANDA %d: %s.%s\n", i,
3244 mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
3245 }
Andy McFadden68825972009-05-08 11:25:35 -07003246 if (mirandaCount > kManyMirandas) {
3247 /*
3248 * Some obfuscators like to create an interface with a huge
3249 * pile of methods, declare classes as implementing it, and then
3250 * only define a couple of methods. This leads to a rather
3251 * massive collection of Miranda methods and a lot of wasted
3252 * space, sometimes enough to blow out the LinearAlloc cap.
3253 */
3254 LOGD("Note: class %s has %d unimplemented (abstract) methods\n",
3255 clazz->descriptor, mirandaCount);
3256 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003257
3258 /*
3259 * We found methods in one or more interfaces for which we do not
3260 * have vtable entries. We have to expand our virtualMethods
3261 * table (which might be empty) to hold some new entries.
3262 */
3263 if (clazz->virtualMethods == NULL) {
3264 newVirtualMethods = (Method*) dvmLinearAlloc(clazz->classLoader,
3265 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3266 } else {
3267 //dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3268 newVirtualMethods = (Method*) dvmLinearRealloc(clazz->classLoader,
3269 clazz->virtualMethods,
3270 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3271 }
3272 if (newVirtualMethods != clazz->virtualMethods) {
3273 /*
3274 * Table was moved in memory. We have to run through the
3275 * vtable and fix the pointers. The vtable entries might be
3276 * pointing at superclasses, so we flip it around: run through
3277 * all locally-defined virtual methods, and fix their entries
3278 * in the vtable. (This would get really messy if sub-classes
3279 * had already been loaded.)
3280 *
3281 * Reminder: clazz->virtualMethods and clazz->virtualMethodCount
3282 * hold the virtual methods declared by this class. The
3283 * method's methodIndex is the vtable index, and is the same
3284 * for all sub-classes (and all super classes in which it is
3285 * defined). We're messing with these because the Miranda
3286 * stuff makes it look like the class actually has an abstract
3287 * method declaration in it.
3288 */
3289 LOGVV("MIRANDA fixing vtable pointers\n");
3290 dvmLinearReadWrite(clazz->classLoader, clazz->vtable);
3291 Method* meth = newVirtualMethods;
3292 for (i = 0; i < clazz->virtualMethodCount; i++, meth++)
3293 clazz->vtable[meth->methodIndex] = meth;
3294 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3295 }
3296
3297 oldMethodCount = clazz->virtualMethodCount;
3298 clazz->virtualMethods = newVirtualMethods;
3299 clazz->virtualMethodCount += mirandaCount;
3300
3301 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3302
3303 /*
3304 * We also have to expand the vtable.
3305 */
3306 assert(clazz->vtable != NULL);
3307 clazz->vtable = (Method**) dvmLinearRealloc(clazz->classLoader,
3308 clazz->vtable,
3309 sizeof(Method*) * (clazz->vtableCount + mirandaCount));
3310 if (clazz->vtable == NULL) {
3311 assert(false);
3312 goto bail;
3313 }
3314 zapVtable = true;
3315
3316 oldVtableCount = clazz->vtableCount;
3317 clazz->vtableCount += mirandaCount;
3318
3319 /*
3320 * Now we need to create the fake methods. We clone the abstract
3321 * method definition from the interface and then replace a few
3322 * things.
Andy McFadden68825972009-05-08 11:25:35 -07003323 *
3324 * The Method will be an "abstract native", with nativeFunc set to
3325 * dvmAbstractMethodStub().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003326 */
3327 meth = clazz->virtualMethods + oldMethodCount;
3328 for (i = 0; i < mirandaCount; i++, meth++) {
3329 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3330 cloneMethod(meth, mirandaList[i]);
3331 meth->clazz = clazz;
3332 meth->accessFlags |= ACC_MIRANDA;
3333 meth->methodIndex = (u2) (oldVtableCount + i);
3334 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3335
3336 /* point the new vtable entry at the new method */
3337 clazz->vtable[oldVtableCount + i] = meth;
3338 }
3339
3340 dvmLinearReadOnly(clazz->classLoader, mirandaList);
3341 dvmLinearFree(clazz->classLoader, mirandaList);
3342
3343 }
3344
3345 /*
3346 * TODO?
3347 * Sort the interfaces by number of declared methods. All we really
3348 * want is to get the interfaces with zero methods at the end of the
3349 * list, so that when we walk through the list during invoke-interface
3350 * we don't examine interfaces that can't possibly be useful.
3351 *
3352 * The set will usually be small, so a simple insertion sort works.
3353 *
3354 * We have to be careful not to change the order of two interfaces
3355 * that define the same method. (Not a problem if we only move the
3356 * zero-method interfaces to the end.)
3357 *
3358 * PROBLEM:
3359 * If we do this, we will no longer be able to identify super vs.
3360 * current class interfaces by comparing clazz->super->iftableCount. This
3361 * breaks anything that only wants to find interfaces declared directly
3362 * by the class (dvmFindStaticFieldHier, ReferenceType.Interfaces,
3363 * dvmDbgOutputAllInterfaces, etc). Need to provide a workaround.
3364 *
3365 * We can sort just the interfaces implemented directly by this class,
3366 * but that doesn't seem like it would provide much of an advantage. I'm
3367 * not sure this is worthwhile.
3368 *
3369 * (This has been made largely obsolete by the interface cache mechanism.)
3370 */
3371
3372 //dvmDumpClass(clazz);
3373
3374 result = true;
3375
3376bail:
3377 if (zapIftable)
3378 dvmLinearReadOnly(clazz->classLoader, clazz->iftable);
3379 if (zapVtable)
3380 dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3381 if (zapIfvipool)
3382 dvmLinearReadOnly(clazz->classLoader, clazz->ifviPool);
3383 return result;
3384}
3385
3386
3387/*
3388 * Provide "stub" implementations for methods without them.
3389 *
3390 * Currently we provide an implementation for all abstract methods that
3391 * throws an AbstractMethodError exception. This allows us to avoid an
3392 * explicit check for abstract methods in every virtual call.
3393 *
3394 * NOTE: for Miranda methods, the method declaration is a clone of what
3395 * was found in the interface class. That copy may already have had the
3396 * function pointer filled in, so don't be surprised if it's not NULL.
3397 *
3398 * NOTE: this sets the "native" flag, giving us an "abstract native" method,
3399 * which is nonsensical. Need to make sure that this doesn't escape the
3400 * VM. We can either mask it out in reflection calls, or copy "native"
3401 * into the high 16 bits of accessFlags and check that internally.
3402 */
3403static bool insertMethodStubs(ClassObject* clazz)
3404{
3405 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3406
3407 Method* meth;
3408 int i;
3409
3410 meth = clazz->virtualMethods;
3411 for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
3412 if (dvmIsAbstractMethod(meth)) {
3413 assert(meth->insns == NULL);
3414 assert(meth->nativeFunc == NULL ||
3415 meth->nativeFunc == (DalvikBridgeFunc)dvmAbstractMethodStub);
3416
3417 meth->accessFlags |= ACC_NATIVE;
3418 meth->nativeFunc = (DalvikBridgeFunc) dvmAbstractMethodStub;
3419 }
3420 }
3421
3422 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3423 return true;
3424}
3425
3426
3427/*
3428 * Swap two instance fields.
3429 */
3430static inline void swapField(InstField* pOne, InstField* pTwo)
3431{
3432 InstField swap;
3433
3434 LOGVV(" --- swap '%s' and '%s'\n", pOne->field.name, pTwo->field.name);
3435 swap = *pOne;
3436 *pOne = *pTwo;
3437 *pTwo = swap;
3438}
3439
3440/*
3441 * Assign instance fields to u4 slots.
3442 *
3443 * The top portion of the instance field area is occupied by the superclass
3444 * fields, the bottom by the fields for this class.
3445 *
3446 * "long" and "double" fields occupy two adjacent slots. On some
3447 * architectures, 64-bit quantities must be 64-bit aligned, so we need to
3448 * arrange fields (or introduce padding) to ensure this. We assume the
3449 * fields of the topmost superclass (i.e. Object) are 64-bit aligned, so
3450 * we can just ensure that the offset is "even". To avoid wasting space,
3451 * we want to move non-reference 32-bit fields into gaps rather than
3452 * creating pad words.
3453 *
3454 * In the worst case we will waste 4 bytes, but because objects are
3455 * allocated on >= 64-bit boundaries, those bytes may well be wasted anyway
3456 * (assuming this is the most-derived class).
3457 *
3458 * Pad words are not represented in the field table, so the field table
3459 * itself does not change size.
3460 *
3461 * The number of field slots determines the size of the object, so we
3462 * set that here too.
3463 *
3464 * This function feels a little more complicated than I'd like, but it
3465 * has the property of moving the smallest possible set of fields, which
3466 * should reduce the time required to load a class.
3467 *
3468 * NOTE: reference fields *must* come first, or precacheReferenceOffsets()
3469 * will break.
3470 */
3471static bool computeFieldOffsets(ClassObject* clazz)
3472{
3473 int fieldOffset;
3474 int i, j;
3475
3476 dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
3477
3478 if (clazz->super != NULL)
3479 fieldOffset = clazz->super->objectSize;
3480 else
3481 fieldOffset = offsetof(DataObject, instanceData);
3482
3483 LOGVV("--- computeFieldOffsets '%s'\n", clazz->descriptor);
3484
3485 //LOGI("OFFSETS fieldCount=%d\n", clazz->ifieldCount);
3486 //LOGI("dataobj, instance: %d\n", offsetof(DataObject, instanceData));
3487 //LOGI("classobj, access: %d\n", offsetof(ClassObject, accessFlags));
3488 //LOGI("super=%p, fieldOffset=%d\n", clazz->super, fieldOffset);
3489
3490 /*
3491 * Start by moving all reference fields to the front.
3492 */
3493 clazz->ifieldRefCount = 0;
3494 j = clazz->ifieldCount - 1;
3495 for (i = 0; i < clazz->ifieldCount; i++) {
3496 InstField* pField = &clazz->ifields[i];
3497 char c = pField->field.signature[0];
3498
3499 if (c != '[' && c != 'L') {
3500 /* This isn't a reference field; see if any reference fields
3501 * follow this one. If so, we'll move it to this position.
3502 * (quicksort-style partitioning)
3503 */
3504 while (j > i) {
3505 InstField* refField = &clazz->ifields[j--];
3506 char rc = refField->field.signature[0];
3507
3508 if (rc == '[' || rc == 'L') {
3509 /* Here's a reference field that follows at least one
3510 * non-reference field. Swap it with the current field.
3511 * (When this returns, "pField" points to the reference
3512 * field, and "refField" points to the non-ref field.)
3513 */
3514 swapField(pField, refField);
3515
3516 /* Fix the signature.
3517 */
3518 c = rc;
3519
3520 clazz->ifieldRefCount++;
3521 break;
3522 }
3523 }
3524 /* We may or may not have swapped a field.
3525 */
3526 } else {
3527 /* This is a reference field.
3528 */
3529 clazz->ifieldRefCount++;
3530 }
3531
3532 /*
3533 * If we've hit the end of the reference fields, break.
3534 */
3535 if (c != '[' && c != 'L')
3536 break;
3537
3538 pField->byteOffset = fieldOffset;
3539 fieldOffset += sizeof(u4);
3540 LOGVV(" --- offset1 '%s'=%d\n", pField->field.name,pField->byteOffset);
3541 }
3542
3543 /*
3544 * Now we want to pack all of the double-wide fields together. If we're
3545 * not aligned, though, we want to shuffle one 32-bit field into place.
3546 * If we can't find one, we'll have to pad it.
3547 */
3548 if (i != clazz->ifieldCount && (fieldOffset & 0x04) != 0) {
3549 LOGVV(" +++ not aligned\n");
3550
3551 InstField* pField = &clazz->ifields[i];
3552 char c = pField->field.signature[0];
3553
3554 if (c != 'J' && c != 'D') {
3555 /*
3556 * The field that comes next is 32-bit, so just advance past it.
3557 */
3558 assert(c != '[' && c != 'L');
3559 pField->byteOffset = fieldOffset;
3560 fieldOffset += sizeof(u4);
3561 i++;
3562 LOGVV(" --- offset2 '%s'=%d\n",
3563 pField->field.name, pField->byteOffset);
3564 } else {
3565 /*
3566 * Next field is 64-bit, so search for a 32-bit field we can
3567 * swap into it.
3568 */
3569 bool found = false;
3570 j = clazz->ifieldCount - 1;
3571 while (j > i) {
3572 InstField* singleField = &clazz->ifields[j--];
3573 char rc = singleField->field.signature[0];
3574
3575 if (rc != 'J' && rc != 'D') {
3576 swapField(pField, singleField);
3577 //c = rc;
3578 LOGVV(" +++ swapped '%s' for alignment\n",
3579 pField->field.name);
3580 pField->byteOffset = fieldOffset;
3581 fieldOffset += sizeof(u4);
3582 LOGVV(" --- offset3 '%s'=%d\n",
3583 pField->field.name, pField->byteOffset);
3584 found = true;
3585 i++;
3586 break;
3587 }
3588 }
3589 if (!found) {
3590 LOGV(" +++ inserting pad field in '%s'\n", clazz->descriptor);
3591 fieldOffset += sizeof(u4);
3592 }
3593 }
3594 }
3595
3596 /*
3597 * Alignment is good, shuffle any double-wide fields forward, and
3598 * finish assigning field offsets to all fields.
3599 */
3600 assert(i == clazz->ifieldCount || (fieldOffset & 0x04) == 0);
3601 j = clazz->ifieldCount - 1;
3602 for ( ; i < clazz->ifieldCount; i++) {
3603 InstField* pField = &clazz->ifields[i];
3604 char c = pField->field.signature[0];
3605
3606 if (c != 'D' && c != 'J') {
3607 /* This isn't a double-wide field; see if any double fields
3608 * follow this one. If so, we'll move it to this position.
3609 * (quicksort-style partitioning)
3610 */
3611 while (j > i) {
3612 InstField* doubleField = &clazz->ifields[j--];
3613 char rc = doubleField->field.signature[0];
3614
3615 if (rc == 'D' || rc == 'J') {
3616 /* Here's a double-wide field that follows at least one
3617 * non-double field. Swap it with the current field.
3618 * (When this returns, "pField" points to the reference
3619 * field, and "doubleField" points to the non-double field.)
3620 */
3621 swapField(pField, doubleField);
3622 c = rc;
3623
3624 break;
3625 }
3626 }
3627 /* We may or may not have swapped a field.
3628 */
3629 } else {
3630 /* This is a double-wide field, leave it be.
3631 */
3632 }
3633
3634 pField->byteOffset = fieldOffset;
3635 LOGVV(" --- offset4 '%s'=%d\n", pField->field.name,pField->byteOffset);
3636 fieldOffset += sizeof(u4);
3637 if (c == 'J' || c == 'D')
3638 fieldOffset += sizeof(u4);
3639 }
3640
3641#ifndef NDEBUG
3642 /* Make sure that all reference fields appear before
3643 * non-reference fields, and all double-wide fields are aligned.
3644 */
3645 j = 0; // seen non-ref
3646 for (i = 0; i < clazz->ifieldCount; i++) {
3647 InstField *pField = &clazz->ifields[i];
3648 char c = pField->field.signature[0];
3649
3650 if (c == 'D' || c == 'J') {
3651 assert((pField->byteOffset & 0x07) == 0);
3652 }
3653
3654 if (c != '[' && c != 'L') {
3655 if (!j) {
3656 assert(i == clazz->ifieldRefCount);
3657 j = 1;
3658 }
3659 } else if (j) {
3660 assert(false);
3661 }
3662 }
3663 if (!j) {
3664 assert(clazz->ifieldRefCount == clazz->ifieldCount);
3665 }
3666#endif
3667
3668 /*
3669 * We map a C struct directly on top of java/lang/Class objects. Make
3670 * sure we left enough room for the instance fields.
3671 */
3672 assert(clazz != gDvm.classJavaLangClass || (size_t)fieldOffset <
3673 offsetof(ClassObject, instanceData) + sizeof(clazz->instanceData));
3674
3675 clazz->objectSize = fieldOffset;
3676
3677 dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
3678 return true;
3679}
3680
3681/*
3682 * Throw the VM-spec-mandated error when an exception is thrown during
3683 * class initialization.
3684 *
3685 * The safest way to do this is to call the ExceptionInInitializerError
3686 * constructor that takes a Throwable.
3687 *
3688 * [Do we want to wrap it if the original is an Error rather than
3689 * an Exception?]
3690 */
3691static void throwClinitError(void)
3692{
3693 Thread* self = dvmThreadSelf();
3694 Object* exception;
3695 Object* eiie;
3696
3697 exception = dvmGetException(self);
3698 dvmAddTrackedAlloc(exception, self);
3699 dvmClearException(self);
3700
3701 if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3702 /*
3703 * Always resolves to same thing -- no race condition.
3704 */
3705 gDvm.classJavaLangExceptionInInitializerError =
3706 dvmFindSystemClass(
3707 "Ljava/lang/ExceptionInInitializerError;");
3708 if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3709 LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3710 goto fail;
3711 }
3712
3713 gDvm.methJavaLangExceptionInInitializerError_init =
3714 dvmFindDirectMethodByDescriptor(gDvm.classJavaLangExceptionInInitializerError,
3715 "<init>", "(Ljava/lang/Throwable;)V");
3716 if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) {
3717 LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3718 goto fail;
3719 }
3720 }
3721
3722 eiie = dvmAllocObject(gDvm.classJavaLangExceptionInInitializerError,
3723 ALLOC_DEFAULT);
3724 if (eiie == NULL)
3725 goto fail;
3726
3727 /*
3728 * Construct the new object, and replace the exception with it.
3729 */
3730 JValue unused;
3731 dvmCallMethod(self, gDvm.methJavaLangExceptionInInitializerError_init,
3732 eiie, &unused, exception);
3733 dvmSetException(self, eiie);
3734 dvmReleaseTrackedAlloc(eiie, NULL);
3735 dvmReleaseTrackedAlloc(exception, self);
3736 return;
3737
3738fail: /* restore original exception */
3739 dvmSetException(self, exception);
3740 dvmReleaseTrackedAlloc(exception, self);
3741 return;
3742}
3743
3744/*
3745 * The class failed to initialize on a previous attempt, so we want to throw
3746 * a NoClassDefFoundError (v2 2.17.5). The exception to this rule is if we
3747 * failed in verification, in which case v2 5.4.1 says we need to re-throw
3748 * the previous error.
3749 */
3750static void throwEarlierClassFailure(ClassObject* clazz)
3751{
3752 LOGI("Rejecting re-init on previously-failed class %s v=%p\n",
3753 clazz->descriptor, clazz->verifyErrorClass);
3754
3755 if (clazz->verifyErrorClass == NULL) {
3756 dvmThrowExceptionWithClassMessage("Ljava/lang/NoClassDefFoundError;",
3757 clazz->descriptor);
3758 } else {
3759 dvmThrowExceptionByClassWithClassMessage(clazz->verifyErrorClass,
3760 clazz->descriptor);
3761 }
3762}
3763
3764/*
3765 * Initialize any static fields whose values are stored in
3766 * the DEX file. This must be done during class initialization.
3767 */
3768static void initSFields(ClassObject* clazz)
3769{
3770 Thread* self = dvmThreadSelf(); /* for dvmReleaseTrackedAlloc() */
3771 DexFile* pDexFile;
3772 const DexClassDef* pClassDef;
3773 const DexEncodedArray* pValueList;
3774 EncodedArrayIterator iterator;
3775 int i;
3776
3777 if (clazz->sfieldCount == 0) {
3778 return;
3779 }
3780 if (clazz->pDvmDex == NULL) {
3781 /* generated class; any static fields should already be set up */
3782 LOGV("Not initializing static fields in %s\n", clazz->descriptor);
3783 return;
3784 }
3785 pDexFile = clazz->pDvmDex->pDexFile;
3786
3787 pClassDef = dexFindClass(pDexFile, clazz->descriptor);
3788 assert(pClassDef != NULL);
3789
3790 pValueList = dexGetStaticValuesList(pDexFile, pClassDef);
3791 if (pValueList == NULL) {
3792 return;
3793 }
3794
3795 dvmEncodedArrayIteratorInitialize(&iterator, pValueList, clazz);
3796
3797 /*
3798 * Iterate over the initial values array, setting the corresponding
3799 * static field for each array element.
3800 */
3801
3802 for (i = 0; dvmEncodedArrayIteratorHasNext(&iterator); i++) {
3803 AnnotationValue value;
3804 bool parsed = dvmEncodedArrayIteratorGetNext(&iterator, &value);
3805 StaticField* sfield = &clazz->sfields[i];
3806 const char* descriptor = sfield->field.signature;
Barry Hayes364f9d92010-06-11 16:12:47 -07003807 bool isObj = false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003808
3809 if (! parsed) {
3810 /*
3811 * TODO: Eventually verification should attempt to ensure
3812 * that this can't happen at least due to a data integrity
3813 * problem.
3814 */
3815 LOGE("Static initializer parse failed for %s at index %d",
3816 clazz->descriptor, i);
3817 dvmAbort();
3818 }
3819
3820 /* Verify that the value we got was of a valid type. */
3821
3822 switch (descriptor[0]) {
3823 case 'Z': parsed = (value.type == kDexAnnotationBoolean); break;
3824 case 'B': parsed = (value.type == kDexAnnotationByte); break;
3825 case 'C': parsed = (value.type == kDexAnnotationChar); break;
3826 case 'S': parsed = (value.type == kDexAnnotationShort); break;
3827 case 'I': parsed = (value.type == kDexAnnotationInt); break;
3828 case 'J': parsed = (value.type == kDexAnnotationLong); break;
3829 case 'F': parsed = (value.type == kDexAnnotationFloat); break;
3830 case 'D': parsed = (value.type == kDexAnnotationDouble); break;
3831 case '[': parsed = (value.type == kDexAnnotationNull); break;
3832 case 'L': {
3833 switch (value.type) {
3834 case kDexAnnotationNull: {
3835 /* No need for further tests. */
3836 break;
3837 }
3838 case kDexAnnotationString: {
3839 parsed =
3840 (strcmp(descriptor, "Ljava/lang/String;") == 0);
Barry Hayes364f9d92010-06-11 16:12:47 -07003841 isObj = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003842 break;
3843 }
3844 case kDexAnnotationType: {
3845 parsed =
3846 (strcmp(descriptor, "Ljava/lang/Class;") == 0);
Barry Hayes364f9d92010-06-11 16:12:47 -07003847 isObj = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003848 break;
3849 }
3850 default: {
3851 parsed = false;
3852 break;
3853 }
3854 }
3855 break;
3856 }
3857 default: {
3858 parsed = false;
3859 break;
3860 }
3861 }
3862
3863 if (parsed) {
3864 /*
Barry Hayes364f9d92010-06-11 16:12:47 -07003865 * All's well, so store the value.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003866 */
Barry Hayes364f9d92010-06-11 16:12:47 -07003867 if (isObj) {
3868 dvmSetStaticFieldObject(sfield, value.value.l);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003869 dvmReleaseTrackedAlloc(value.value.l, self);
Barry Hayes364f9d92010-06-11 16:12:47 -07003870 } else {
3871 /*
3872 * Note: This always stores the full width of a
3873 * JValue, even though most of the time only the first
3874 * word is needed.
3875 */
3876 sfield->value = value.value;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003877 }
3878 } else {
3879 /*
3880 * Something up above had a problem. TODO: See comment
3881 * above the switch about verfication.
3882 */
3883 LOGE("Bogus static initialization: value type %d in field type "
3884 "%s for %s at index %d",
3885 value.type, descriptor, clazz->descriptor, i);
3886 dvmAbort();
3887 }
3888 }
3889}
3890
3891
3892/*
3893 * Determine whether "descriptor" yields the same class object in the
3894 * context of clazz1 and clazz2.
3895 *
3896 * The caller must hold gDvm.loadedClasses.
3897 *
3898 * Returns "true" if they match.
3899 */
3900static bool compareDescriptorClasses(const char* descriptor,
3901 const ClassObject* clazz1, const ClassObject* clazz2)
3902{
3903 ClassObject* result1;
3904 ClassObject* result2;
3905
3906 /*
3907 * Do the first lookup by name.
3908 */
3909 result1 = dvmFindClassNoInit(descriptor, clazz1->classLoader);
3910
3911 /*
3912 * We can skip a second lookup by name if the second class loader is
3913 * in the initiating loader list of the class object we retrieved.
3914 * (This means that somebody already did a lookup of this class through
3915 * the second loader, and it resolved to the same class.) If it's not
3916 * there, we may simply not have had an opportunity to add it yet, so
3917 * we do the full lookup.
3918 *
3919 * The initiating loader test should catch the majority of cases
3920 * (in particular, the zillions of references to String/Object).
3921 *
3922 * Unfortunately we're still stuck grabbing a mutex to do the lookup.
3923 *
3924 * For this to work, the superclass/interface should be the first
3925 * argument, so that way if it's from the bootstrap loader this test
3926 * will work. (The bootstrap loader, by definition, never shows up
3927 * as the initiating loader of a class defined by some other loader.)
3928 */
3929 dvmHashTableLock(gDvm.loadedClasses);
3930 bool isInit = dvmLoaderInInitiatingList(result1, clazz2->classLoader);
3931 dvmHashTableUnlock(gDvm.loadedClasses);
3932
3933 if (isInit) {
3934 //printf("%s(obj=%p) / %s(cl=%p): initiating\n",
3935 // result1->descriptor, result1,
3936 // clazz2->descriptor, clazz2->classLoader);
3937 return true;
3938 } else {
3939 //printf("%s(obj=%p) / %s(cl=%p): RAW\n",
3940 // result1->descriptor, result1,
3941 // clazz2->descriptor, clazz2->classLoader);
3942 result2 = dvmFindClassNoInit(descriptor, clazz2->classLoader);
3943 }
3944
3945 if (result1 == NULL || result2 == NULL) {
3946 dvmClearException(dvmThreadSelf());
3947 if (result1 == result2) {
3948 /*
3949 * Neither class loader could find this class. Apparently it
3950 * doesn't exist.
3951 *
3952 * We can either throw some sort of exception now, or just
3953 * assume that it'll fail later when something actually tries
3954 * to use the class. For strict handling we should throw now,
3955 * because a "tricky" class loader could start returning
3956 * something later, and a pair of "tricky" loaders could set
3957 * us up for confusion.
3958 *
3959 * I'm not sure if we're allowed to complain about nonexistent
3960 * classes in method signatures during class init, so for now
3961 * this will just return "true" and let nature take its course.
3962 */
3963 return true;
3964 } else {
3965 /* only one was found, so clearly they're not the same */
3966 return false;
3967 }
3968 }
3969
3970 return result1 == result2;
3971}
3972
3973/*
3974 * For every component in the method descriptor, resolve the class in the
3975 * context of the two classes and compare the results.
3976 *
3977 * For best results, the "superclass" class should be first.
3978 *
3979 * Returns "true" if the classes match, "false" otherwise.
3980 */
3981static bool checkMethodDescriptorClasses(const Method* meth,
3982 const ClassObject* clazz1, const ClassObject* clazz2)
3983{
3984 DexParameterIterator iterator;
3985 const char* descriptor;
3986
3987 /* walk through the list of parameters */
3988 dexParameterIteratorInit(&iterator, &meth->prototype);
3989 while (true) {
3990 descriptor = dexParameterIteratorNextDescriptor(&iterator);
3991
3992 if (descriptor == NULL)
3993 break;
3994
3995 if (descriptor[0] == 'L' || descriptor[0] == '[') {
3996 /* non-primitive type */
3997 if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
3998 return false;
3999 }
4000 }
4001
4002 /* check the return type */
4003 descriptor = dexProtoGetReturnType(&meth->prototype);
4004 if (descriptor[0] == 'L' || descriptor[0] == '[') {
4005 if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4006 return false;
4007 }
4008 return true;
4009}
4010
4011/*
4012 * Validate the descriptors in the superclass and interfaces.
4013 *
4014 * What we need to do is ensure that the classes named in the method
4015 * descriptors in our ancestors and ourselves resolve to the same class
Andy McFaddencab8be02009-05-26 13:39:57 -07004016 * objects. We can get conflicts when the classes come from different
4017 * class loaders, and the resolver comes up with different results for
4018 * the same class name in different contexts.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004019 *
Andy McFaddencab8be02009-05-26 13:39:57 -07004020 * An easy way to cause the problem is to declare a base class that uses
4021 * class Foo in a method signature (e.g. as the return type). Then,
4022 * define a subclass and a different version of Foo, and load them from a
4023 * different class loader. If the subclass overrides the method, it will
4024 * have a different concept of what Foo is than its parent does, so even
4025 * though the method signature strings are identical, they actually mean
4026 * different things.
4027 *
4028 * A call to the method through a base-class reference would be treated
4029 * differently than a call to the method through a subclass reference, which
4030 * isn't the way polymorphism works, so we have to reject the subclass.
4031 * If the subclass doesn't override the base method, then there's no
4032 * problem, because calls through base-class references and subclass
4033 * references end up in the same place.
4034 *
4035 * We don't need to check to see if an interface's methods match with its
4036 * superinterface's methods, because you can't instantiate an interface
4037 * and do something inappropriate with it. If interface I1 extends I2
4038 * and is implemented by C, and I1 and I2 are in separate class loaders
4039 * and have conflicting views of other classes, we will catch the conflict
4040 * when we process C. Anything that implements I1 is doomed to failure,
4041 * but we don't need to catch that while processing I1.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004042 *
4043 * On failure, throws an exception and returns "false".
4044 */
4045static bool validateSuperDescriptors(const ClassObject* clazz)
4046{
4047 int i;
4048
4049 if (dvmIsInterfaceClass(clazz))
4050 return true;
4051
4052 /*
4053 * Start with the superclass-declared methods.
4054 */
4055 if (clazz->super != NULL &&
4056 clazz->classLoader != clazz->super->classLoader)
4057 {
4058 /*
Andy McFaddencab8be02009-05-26 13:39:57 -07004059 * Walk through every overridden method and compare resolved
4060 * descriptor components. We pull the Method structs out of
4061 * the vtable. It doesn't matter whether we get the struct from
4062 * the parent or child, since we just need the UTF-8 descriptor,
4063 * which must match.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004064 *
4065 * We need to do this even for the stuff inherited from Object,
4066 * because it's possible that the new class loader has redefined
4067 * a basic class like String.
Andy McFaddene7b30942009-05-27 12:42:38 -07004068 *
4069 * We don't need to check stuff defined in a superclass because
4070 * it was checked when the superclass was loaded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004071 */
4072 const Method* meth;
4073
4074 //printf("Checking %s %p vs %s %p\n",
4075 // clazz->descriptor, clazz->classLoader,
4076 // clazz->super->descriptor, clazz->super->classLoader);
4077 for (i = clazz->super->vtableCount - 1; i >= 0; i--) {
4078 meth = clazz->vtable[i];
Andy McFaddencab8be02009-05-26 13:39:57 -07004079 if (meth != clazz->super->vtable[i] &&
4080 !checkMethodDescriptorClasses(meth, clazz->super, clazz))
4081 {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004082 LOGW("Method mismatch: %s in %s (cl=%p) and super %s (cl=%p)\n",
4083 meth->name, clazz->descriptor, clazz->classLoader,
4084 clazz->super->descriptor, clazz->super->classLoader);
4085 dvmThrowException("Ljava/lang/LinkageError;",
4086 "Classes resolve differently in superclass");
4087 return false;
4088 }
4089 }
4090 }
4091
4092 /*
Andy McFaddene7b30942009-05-27 12:42:38 -07004093 * Check the methods defined by this class against the interfaces it
4094 * implements. If we inherited the implementation from a superclass,
4095 * we have to check it against the superclass (which might be in a
4096 * different class loader). If the superclass also implements the
4097 * interface, we could skip the check since by definition it was
4098 * performed when the class was loaded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004099 */
4100 for (i = 0; i < clazz->iftableCount; i++) {
4101 const InterfaceEntry* iftable = &clazz->iftable[i];
4102
4103 if (clazz->classLoader != iftable->clazz->classLoader) {
4104 const ClassObject* iface = iftable->clazz;
4105 int j;
4106
4107 for (j = 0; j < iface->virtualMethodCount; j++) {
4108 const Method* meth;
4109 int vtableIndex;
4110
4111 vtableIndex = iftable->methodIndexArray[j];
4112 meth = clazz->vtable[vtableIndex];
4113
Andy McFaddene7b30942009-05-27 12:42:38 -07004114 if (!checkMethodDescriptorClasses(meth, iface, meth->clazz)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004115 LOGW("Method mismatch: %s in %s (cl=%p) and "
4116 "iface %s (cl=%p)\n",
4117 meth->name, clazz->descriptor, clazz->classLoader,
4118 iface->descriptor, iface->classLoader);
4119 dvmThrowException("Ljava/lang/LinkageError;",
4120 "Classes resolve differently in interface");
4121 return false;
4122 }
4123 }
4124 }
4125 }
4126
4127 return true;
4128}
4129
4130/*
4131 * Returns true if the class is being initialized by us (which means that
4132 * calling dvmInitClass will return immediately after fiddling with locks).
4133 *
4134 * There isn't a race here, because either clazz->initThreadId won't match
4135 * us, or it will and it was set in the same thread.
4136 */
4137bool dvmIsClassInitializing(const ClassObject* clazz)
4138{
4139 return (clazz->status == CLASS_INITIALIZING &&
4140 clazz->initThreadId == dvmThreadSelf()->threadId);
4141}
4142
4143/*
4144 * If a class has not been initialized, do so by executing the code in
4145 * <clinit>. The sequence is described in the VM spec v2 2.17.5.
4146 *
4147 * It is possible for multiple threads to arrive here simultaneously, so
4148 * we need to lock the class while we check stuff. We know that no
4149 * interpreted code has access to the class yet, so we can use the class's
4150 * monitor lock.
4151 *
4152 * We will often be called recursively, e.g. when the <clinit> code resolves
4153 * one of its fields, the field resolution will try to initialize the class.
Andy McFadden77514ab2010-05-06 13:39:07 -07004154 * In that case we will return "true" even though the class isn't actually
4155 * ready to go. The ambiguity can be resolved with dvmIsClassInitializing().
4156 * (TODO: consider having this return an enum to avoid the extra call --
4157 * return -1 on failure, 0 on success, 1 on still-initializing. Looks like
4158 * dvmIsClassInitializing() is always paired with *Initialized())
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004159 *
4160 * This can get very interesting if a class has a static field initialized
4161 * to a new instance of itself. <clinit> will end up calling <init> on
4162 * the members it is initializing, which is fine unless it uses the contents
4163 * of static fields to initialize instance fields. This will leave the
4164 * static-referenced objects in a partially initialized state. This is
4165 * reasonably rare and can sometimes be cured with proper field ordering.
4166 *
4167 * On failure, returns "false" with an exception raised.
4168 *
4169 * -----
4170 *
4171 * It is possible to cause a deadlock by having a situation like this:
4172 * class A { static { sleep(10000); new B(); } }
4173 * class B { static { sleep(10000); new A(); } }
4174 * new Thread() { public void run() { new A(); } }.start();
4175 * new Thread() { public void run() { new B(); } }.start();
4176 * This appears to be expected under the spec.
4177 *
4178 * The interesting question is what to do if somebody calls Thread.interrupt()
4179 * on one of the deadlocked threads. According to the VM spec, they're both
4180 * sitting in "wait". Should the interrupt code quietly raise the
4181 * "interrupted" flag, or should the "wait" return immediately with an
4182 * exception raised?
4183 *
4184 * This gets a little murky. The VM spec says we call "wait", and the
4185 * spec for Thread.interrupt says Object.wait is interruptible. So it
4186 * seems that, if we get unlucky and interrupt class initialization, we
4187 * are expected to throw (which gets converted to ExceptionInInitializerError
4188 * since InterruptedException is checked).
4189 *
4190 * There are a couple of problems here. First, all threads are expected to
4191 * present a consistent view of class initialization, so we can't have it
4192 * fail in one thread and succeed in another. Second, once a class fails
4193 * to initialize, it must *always* fail. This means that a stray interrupt()
4194 * call could render a class unusable for the lifetime of the VM.
4195 *
4196 * In most cases -- the deadlock example above being a counter-example --
4197 * the interrupting thread can't tell whether the target thread handled
4198 * the initialization itself or had to wait while another thread did the
4199 * work. Refusing to interrupt class initialization is, in most cases,
4200 * not something that a program can reliably detect.
4201 *
4202 * On the assumption that interrupting class initialization is highly
4203 * undesirable in most circumstances, and that failing to do so does not
4204 * deviate from the spec in a meaningful way, we don't allow class init
4205 * to be interrupted by Thread.interrupt().
4206 */
4207bool dvmInitClass(ClassObject* clazz)
4208{
4209#if LOG_CLASS_LOADING
4210 bool initializedByUs = false;
4211#endif
4212
4213 Thread* self = dvmThreadSelf();
4214 const Method* method;
4215
4216 dvmLockObject(self, (Object*) clazz);
4217 assert(dvmIsClassLinked(clazz) || clazz->status == CLASS_ERROR);
4218
4219 /*
4220 * If the class hasn't been verified yet, do so now.
4221 */
4222 if (clazz->status < CLASS_VERIFIED) {
4223 /*
4224 * If we're in an "erroneous" state, throw an exception and bail.
4225 */
4226 if (clazz->status == CLASS_ERROR) {
4227 throwEarlierClassFailure(clazz);
4228 goto bail_unlock;
4229 }
4230
4231 assert(clazz->status == CLASS_RESOLVED);
4232 assert(!IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4233
4234 if (gDvm.classVerifyMode == VERIFY_MODE_NONE ||
4235 (gDvm.classVerifyMode == VERIFY_MODE_REMOTE &&
4236 clazz->classLoader == NULL))
4237 {
Andy McFaddend22748a2010-04-22 17:08:11 -07004238 /* advance to "verified" state */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004239 LOGV("+++ not verifying class %s (cl=%p)\n",
4240 clazz->descriptor, clazz->classLoader);
Andy McFaddend22748a2010-04-22 17:08:11 -07004241 clazz->status = CLASS_VERIFIED;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004242 goto noverify;
4243 }
4244
4245 if (!gDvm.optimizing)
4246 LOGV("+++ late verify on %s\n", clazz->descriptor);
4247
4248 /*
4249 * We're not supposed to optimize an unverified class, but during
4250 * development this mode was useful. We can't verify an optimized
4251 * class because the optimization process discards information.
4252 */
4253 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) {
4254 LOGW("Class '%s' was optimized without verification; "
4255 "not verifying now\n",
4256 clazz->descriptor);
4257 LOGW(" ('rm /data/dalvik-cache/*' and restart to fix this)");
4258 goto verify_failed;
4259 }
4260
4261 clazz->status = CLASS_VERIFYING;
Andy McFadden228a6b02010-05-04 15:02:32 -07004262 if (!dvmVerifyClass(clazz)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004263verify_failed:
4264 dvmThrowExceptionWithClassMessage("Ljava/lang/VerifyError;",
4265 clazz->descriptor);
Andy McFaddenfb119e62010-06-28 16:21:20 -07004266 dvmSetFieldObject((Object*) clazz,
4267 offsetof(ClassObject, verifyErrorClass),
4268 (Object*) dvmGetException(self)->clazz);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004269 clazz->status = CLASS_ERROR;
4270 goto bail_unlock;
4271 }
4272
4273 clazz->status = CLASS_VERIFIED;
4274 }
4275noverify:
4276
Andy McFaddenfb119e62010-06-28 16:21:20 -07004277 /*
4278 * We need to ensure that certain instructions, notably accesses to
4279 * volatile fields, are replaced before any code is executed. This
4280 * must happen even if DEX optimizations are disabled.
4281 */
4282 if (!IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) {
4283 LOGV("+++ late optimize on %s (pv=%d)\n",
4284 clazz->descriptor, IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4285 dvmOptimizeClass(clazz, true);
4286 SET_CLASS_FLAG(clazz, CLASS_ISOPTIMIZED);
4287 }
4288
Andy McFaddenfb119e62010-06-28 16:21:20 -07004289 /* update instruction stream now that verification + optimization is done */
Andy McFaddend22748a2010-04-22 17:08:11 -07004290 dvmFlushBreakpoints(clazz);
Andy McFaddend22748a2010-04-22 17:08:11 -07004291
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004292 if (clazz->status == CLASS_INITIALIZED)
4293 goto bail_unlock;
4294
4295 while (clazz->status == CLASS_INITIALIZING) {
4296 /* we caught somebody else in the act; was it us? */
4297 if (clazz->initThreadId == self->threadId) {
4298 //LOGV("HEY: found a recursive <clinit>\n");
4299 goto bail_unlock;
4300 }
4301
4302 if (dvmCheckException(self)) {
4303 LOGW("GLITCH: exception pending at start of class init\n");
4304 dvmAbort();
4305 }
4306
4307 /*
4308 * Wait for the other thread to finish initialization. We pass
4309 * "false" for the "interruptShouldThrow" arg so it doesn't throw
4310 * an exception on interrupt.
4311 */
4312 dvmObjectWait(self, (Object*) clazz, 0, 0, false);
4313
4314 /*
4315 * When we wake up, repeat the test for init-in-progress. If there's
4316 * an exception pending (only possible if "interruptShouldThrow"
4317 * was set), bail out.
4318 */
4319 if (dvmCheckException(self)) {
4320 LOGI("Class init of '%s' failing with wait() exception\n",
4321 clazz->descriptor);
4322 /*
4323 * TODO: this is bogus, because it means the two threads have a
4324 * different idea of the class status. We need to flag the
4325 * class as bad and ensure that the initializer thread respects
4326 * our notice. If we get lucky and wake up after the class has
4327 * finished initialization but before being woken, we have to
4328 * swallow the exception, perhaps raising thread->interrupted
4329 * to preserve semantics.
4330 *
4331 * Since we're not currently allowing interrupts, this should
4332 * never happen and we don't need to fix this.
4333 */
4334 assert(false);
4335 throwClinitError();
4336 clazz->status = CLASS_ERROR;
4337 goto bail_unlock;
4338 }
4339 if (clazz->status == CLASS_INITIALIZING) {
4340 LOGI("Waiting again for class init\n");
4341 continue;
4342 }
4343 assert(clazz->status == CLASS_INITIALIZED ||
4344 clazz->status == CLASS_ERROR);
4345 if (clazz->status == CLASS_ERROR) {
4346 /*
4347 * The caller wants an exception, but it was thrown in a
4348 * different thread. Synthesize one here.
4349 */
4350 dvmThrowException("Ljava/lang/UnsatisfiedLinkError;",
4351 "(<clinit> failed, see exception in other thread)");
4352 }
4353 goto bail_unlock;
4354 }
4355
4356 /* see if we failed previously */
4357 if (clazz->status == CLASS_ERROR) {
4358 // might be wise to unlock before throwing; depends on which class
4359 // it is that we have locked
4360 dvmUnlockObject(self, (Object*) clazz);
4361 throwEarlierClassFailure(clazz);
4362 return false;
4363 }
4364
Andy McFaddene15a8eb2010-02-22 17:07:23 -08004365 u8 startWhen = 0;
4366 if (gDvm.allocProf.enabled) {
4367 startWhen = dvmGetRelativeTimeNsec();
4368 }
4369
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004370 /*
4371 * We're ready to go, and have exclusive access to the class.
4372 *
4373 * Before we start initialization, we need to do one extra bit of
4374 * validation: make sure that the methods declared here match up
4375 * with our superclass and interfaces. We know that the UTF-8
4376 * descriptors match, but classes from different class loaders can
4377 * have the same name.
4378 *
4379 * We do this now, rather than at load/link time, for the same reason
4380 * that we defer verification.
4381 *
4382 * It's unfortunate that we need to do this at all, but we risk
4383 * mixing reference types with identical names (see Dalvik test 068).
4384 */
4385 if (!validateSuperDescriptors(clazz)) {
4386 assert(dvmCheckException(self));
4387 clazz->status = CLASS_ERROR;
4388 goto bail_unlock;
4389 }
4390
4391 /*
4392 * Let's initialize this thing.
4393 *
4394 * We unlock the object so that other threads can politely sleep on
4395 * our mutex with Object.wait(), instead of hanging or spinning trying
4396 * to grab our mutex.
4397 */
4398 assert(clazz->status < CLASS_INITIALIZING);
4399
4400#if LOG_CLASS_LOADING
4401 // We started initializing.
4402 logClassLoad('+', clazz);
4403 initializedByUs = true;
4404#endif
4405
4406 clazz->status = CLASS_INITIALIZING;
4407 clazz->initThreadId = self->threadId;
4408 dvmUnlockObject(self, (Object*) clazz);
4409
4410 /* init our superclass */
4411 if (clazz->super != NULL && clazz->super->status != CLASS_INITIALIZED) {
4412 assert(!dvmIsInterfaceClass(clazz));
4413 if (!dvmInitClass(clazz->super)) {
4414 assert(dvmCheckException(self));
4415 clazz->status = CLASS_ERROR;
4416 /* wake up anybody who started waiting while we were unlocked */
4417 dvmLockObject(self, (Object*) clazz);
4418 goto bail_notify;
4419 }
4420 }
4421
4422 /* Initialize any static fields whose values are
4423 * stored in the Dex file. This should include all of the
4424 * simple "final static" fields, which are required to
4425 * be initialized first. (vmspec 2 sec 2.17.5 item 8)
4426 * More-complicated final static fields should be set
4427 * at the beginning of <clinit>; all we can do is trust
4428 * that the compiler did the right thing.
4429 */
4430 initSFields(clazz);
4431
4432 /* Execute any static initialization code.
4433 */
4434 method = dvmFindDirectMethodByDescriptor(clazz, "<clinit>", "()V");
4435 if (method == NULL) {
4436 LOGVV("No <clinit> found for %s\n", clazz->descriptor);
4437 } else {
4438 LOGVV("Invoking %s.<clinit>\n", clazz->descriptor);
4439 JValue unused;
4440 dvmCallMethod(self, method, NULL, &unused);
4441 }
4442
4443 if (dvmCheckException(self)) {
4444 /*
4445 * We've had an exception thrown during static initialization. We
4446 * need to throw an ExceptionInInitializerError, but we want to
4447 * tuck the original exception into the "cause" field.
4448 */
Elliott Hughes22680ee2010-07-20 17:23:06 -07004449 LOGW("Exception %s thrown while initializing %s\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004450 (dvmGetException(self)->clazz)->descriptor, clazz->descriptor);
4451 throwClinitError();
4452 //LOGW("+++ replaced\n");
4453
4454 dvmLockObject(self, (Object*) clazz);
4455 clazz->status = CLASS_ERROR;
4456 } else {
4457 /* success! */
4458 dvmLockObject(self, (Object*) clazz);
4459 clazz->status = CLASS_INITIALIZED;
4460 LOGVV("Initialized class: %s\n", clazz->descriptor);
Andy McFaddene15a8eb2010-02-22 17:07:23 -08004461
4462 /*
4463 * Update alloc counters. TODO: guard with mutex.
4464 */
4465 if (gDvm.allocProf.enabled && startWhen != 0) {
4466 u8 initDuration = dvmGetRelativeTimeNsec() - startWhen;
4467 gDvm.allocProf.classInitTime += initDuration;
4468 self->allocProf.classInitTime += initDuration;
4469 gDvm.allocProf.classInitCount++;
4470 self->allocProf.classInitCount++;
4471 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004472 }
4473
4474bail_notify:
4475 /*
4476 * Notify anybody waiting on the object.
4477 */
4478 dvmObjectNotifyAll(self, (Object*) clazz);
4479
4480bail_unlock:
4481
4482#if LOG_CLASS_LOADING
4483 if (initializedByUs) {
4484 // We finished initializing.
4485 logClassLoad('-', clazz);
4486 }
4487#endif
4488
4489 dvmUnlockObject(self, (Object*) clazz);
4490
4491 return (clazz->status != CLASS_ERROR);
4492}
4493
4494/*
4495 * Replace method->nativeFunc and method->insns with new values. This is
Andy McFadden1e83b4d2010-07-15 17:20:24 -07004496 * commonly performed after successful resolution of a native method.
4497 *
4498 * There are three basic states:
4499 * (1) (initial) nativeFunc = dvmResolveNativeMethod, insns = NULL
4500 * (2) (internal native) nativeFunc = <impl>, insns = NULL
4501 * (3) (JNI) nativeFunc = JNI call bridge, insns = <impl>
4502 *
4503 * nativeFunc must never be NULL for a native method.
4504 *
4505 * The most common transitions are (1)->(2) and (1)->(3). The former is
4506 * atomic, since only one field is updated; the latter is not, but since
4507 * dvmResolveNativeMethod ignores the "insns" field we just need to make
4508 * sure the update happens in the correct order.
4509 *
4510 * A transition from (2)->(1) would work fine, but (3)->(1) will not,
4511 * because both fields change. If we did this while a thread was executing
4512 * in the call bridge, we could null out the "insns" field right before
4513 * the bridge tried to call through it. So, once "insns" is set, we do
4514 * not allow it to be cleared. A NULL value for the "insns" argument is
4515 * treated as "do not change existing value".
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004516 */
Andy McFadden1e83b4d2010-07-15 17:20:24 -07004517void dvmSetNativeFunc(Method* method, DalvikBridgeFunc func,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004518 const u2* insns)
4519{
4520 ClassObject* clazz = method->clazz;
4521
Andy McFadden1e83b4d2010-07-15 17:20:24 -07004522 assert(func != NULL);
4523
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004524 /* just open up both; easier that way */
4525 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4526 dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4527
Andy McFadden1e83b4d2010-07-15 17:20:24 -07004528 if (insns != NULL) {
4529 /* update both, ensuring that "insns" is observed first */
4530 method->insns = insns;
4531 android_atomic_release_store((int32_t) func,
4532 (void*) &method->nativeFunc);
4533 } else {
4534 /* only update nativeFunc */
4535 method->nativeFunc = func;
4536 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004537
4538 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4539 dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4540}
4541
4542/*
4543 * Add a RegisterMap to a Method. This is done when we verify the class
The Android Open Source Project99409882009-03-18 22:20:24 -07004544 * and compute the register maps at class initialization time (i.e. when
4545 * we don't have a pre-generated map). This means "pMap" is on the heap
4546 * and should be freed when the Method is discarded.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004547 */
4548void dvmSetRegisterMap(Method* method, const RegisterMap* pMap)
4549{
4550 ClassObject* clazz = method->clazz;
4551
4552 if (method->registerMap != NULL) {
Andy McFaddend45a8872009-03-24 20:41:52 -07004553 /* unexpected during class loading, okay on first use (uncompress) */
Andy McFadden9faa9e62009-04-08 00:35:55 -07004554 LOGV("NOTE: registerMap already set for %s.%s\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004555 method->clazz->descriptor, method->name);
4556 /* keep going */
4557 }
The Android Open Source Project99409882009-03-18 22:20:24 -07004558 assert(!dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004559
4560 /* might be virtual or direct */
4561 dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4562 dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4563
4564 method->registerMap = pMap;
4565
4566 dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4567 dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4568}
4569
4570/*
4571 * dvmHashForeach callback. A nonzero return value causes foreach to
4572 * bail out.
4573 */
4574static int findClassCallback(void* vclazz, void* arg)
4575{
4576 ClassObject* clazz = vclazz;
4577 const char* descriptor = (const char*) arg;
4578
4579 if (strcmp(clazz->descriptor, descriptor) == 0)
4580 return (int) clazz;
4581 return 0;
4582}
4583
4584/*
4585 * Find a loaded class by descriptor. Returns the first one found.
4586 * Because there can be more than one if class loaders are involved,
4587 * this is not an especially good API. (Currently only used by the
4588 * debugger and "checking" JNI.)
4589 *
4590 * "descriptor" should have the form "Ljava/lang/Class;" or
4591 * "[Ljava/lang/Class;", i.e. a descriptor and not an internal-form
4592 * class name.
4593 */
4594ClassObject* dvmFindLoadedClass(const char* descriptor)
4595{
4596 int result;
4597
4598 dvmHashTableLock(gDvm.loadedClasses);
4599 result = dvmHashForeach(gDvm.loadedClasses, findClassCallback,
4600 (void*) descriptor);
4601 dvmHashTableUnlock(gDvm.loadedClasses);
4602
4603 return (ClassObject*) result;
4604}
4605
4606/*
4607 * Retrieve the system (a/k/a application) class loader.
4608 */
4609Object* dvmGetSystemClassLoader(void)
4610{
4611 ClassObject* clazz;
4612 Method* getSysMeth;
4613 Object* loader;
4614
4615 clazz = dvmFindSystemClass("Ljava/lang/ClassLoader;");
4616 if (clazz == NULL)
4617 return NULL;
4618
4619 getSysMeth = dvmFindDirectMethodByDescriptor(clazz, "getSystemClassLoader",
4620 "()Ljava/lang/ClassLoader;");
4621 if (getSysMeth == NULL)
4622 return NULL;
4623
4624 JValue result;
4625 dvmCallMethod(dvmThreadSelf(), getSysMeth, NULL, &result);
4626 loader = (Object*)result.l;
4627 return loader;
4628}
4629
4630
4631/*
4632 * This is a dvmHashForeach callback.
4633 */
4634static int dumpClass(void* vclazz, void* varg)
4635{
4636 const ClassObject* clazz = (const ClassObject*) vclazz;
4637 const ClassObject* super;
4638 int flags = (int) varg;
4639 char* desc;
4640 int i;
4641
4642 if (clazz == NULL) {
4643 LOGI("dumpClass: ignoring request to dump null class\n");
4644 return 0;
4645 }
4646
4647 if ((flags & kDumpClassFullDetail) == 0) {
4648 bool showInit = (flags & kDumpClassInitialized) != 0;
4649 bool showLoader = (flags & kDumpClassClassLoader) != 0;
4650 const char* initStr;
4651
4652 initStr = dvmIsClassInitialized(clazz) ? "true" : "false";
4653
4654 if (showInit && showLoader)
4655 LOGI("%s %p %s\n", clazz->descriptor, clazz->classLoader, initStr);
4656 else if (showInit)
4657 LOGI("%s %s\n", clazz->descriptor, initStr);
4658 else if (showLoader)
4659 LOGI("%s %p\n", clazz->descriptor, clazz->classLoader);
4660 else
4661 LOGI("%s\n", clazz->descriptor);
4662
4663 return 0;
4664 }
4665
4666 /* clazz->super briefly holds the superclass index during class prep */
4667 if ((u4)clazz->super > 0x10000 && (u4) clazz->super != (u4)-1)
4668 super = clazz->super;
4669 else
4670 super = NULL;
4671
4672 LOGI("----- %s '%s' cl=%p ser=0x%08x -----\n",
4673 dvmIsInterfaceClass(clazz) ? "interface" : "class",
4674 clazz->descriptor, clazz->classLoader, clazz->serialNumber);
4675 LOGI(" objectSize=%d (%d from super)\n", (int) clazz->objectSize,
4676 super != NULL ? (int) super->objectSize : -1);
4677 LOGI(" access=0x%04x.%04x\n", clazz->accessFlags >> 16,
4678 clazz->accessFlags & JAVA_FLAGS_MASK);
4679 if (super != NULL)
4680 LOGI(" super='%s' (cl=%p)\n", super->descriptor, super->classLoader);
4681 if (dvmIsArrayClass(clazz)) {
4682 LOGI(" dimensions=%d elementClass=%s\n",
4683 clazz->arrayDim, clazz->elementClass->descriptor);
4684 }
4685 if (clazz->iftableCount > 0) {
4686 LOGI(" interfaces (%d):\n", clazz->iftableCount);
4687 for (i = 0; i < clazz->iftableCount; i++) {
4688 InterfaceEntry* ent = &clazz->iftable[i];
4689 int j;
4690
4691 LOGI(" %2d: %s (cl=%p)\n",
4692 i, ent->clazz->descriptor, ent->clazz->classLoader);
4693
4694 /* enable when needed */
4695 if (false && ent->methodIndexArray != NULL) {
4696 for (j = 0; j < ent->clazz->virtualMethodCount; j++)
4697 LOGI(" %2d: %d %s %s\n",
4698 j, ent->methodIndexArray[j],
4699 ent->clazz->virtualMethods[j].name,
4700 clazz->vtable[ent->methodIndexArray[j]]->name);
4701 }
4702 }
4703 }
4704 if (!dvmIsInterfaceClass(clazz)) {
4705 LOGI(" vtable (%d entries, %d in super):\n", clazz->vtableCount,
4706 super != NULL ? super->vtableCount : 0);
4707 for (i = 0; i < clazz->vtableCount; i++) {
4708 desc = dexProtoCopyMethodDescriptor(&clazz->vtable[i]->prototype);
4709 LOGI(" %s%2d: %p %20s %s\n",
4710 (i != clazz->vtable[i]->methodIndex) ? "*** " : "",
4711 (u4) clazz->vtable[i]->methodIndex, clazz->vtable[i],
4712 clazz->vtable[i]->name, desc);
4713 free(desc);
4714 }
4715 LOGI(" direct methods (%d entries):\n", clazz->directMethodCount);
4716 for (i = 0; i < clazz->directMethodCount; i++) {
4717 desc = dexProtoCopyMethodDescriptor(
4718 &clazz->directMethods[i].prototype);
4719 LOGI(" %2d: %20s %s\n", i, clazz->directMethods[i].name,
4720 desc);
4721 free(desc);
4722 }
4723 } else {
4724 LOGI(" interface methods (%d):\n", clazz->virtualMethodCount);
4725 for (i = 0; i < clazz->virtualMethodCount; i++) {
4726 desc = dexProtoCopyMethodDescriptor(
4727 &clazz->virtualMethods[i].prototype);
4728 LOGI(" %2d: %2d %20s %s\n", i,
4729 (u4) clazz->virtualMethods[i].methodIndex,
4730 clazz->virtualMethods[i].name,
4731 desc);
4732 free(desc);
4733 }
4734 }
4735 if (clazz->sfieldCount > 0) {
4736 LOGI(" static fields (%d entries):\n", clazz->sfieldCount);
4737 for (i = 0; i < clazz->sfieldCount; i++) {
4738 LOGI(" %2d: %20s %s\n", i, clazz->sfields[i].field.name,
4739 clazz->sfields[i].field.signature);
4740 }
4741 }
4742 if (clazz->ifieldCount > 0) {
4743 LOGI(" instance fields (%d entries):\n", clazz->ifieldCount);
4744 for (i = 0; i < clazz->ifieldCount; i++) {
4745 LOGI(" %2d: %20s %s\n", i, clazz->ifields[i].field.name,
4746 clazz->ifields[i].field.signature);
4747 }
4748 }
4749 return 0;
4750}
4751
4752/*
4753 * Dump the contents of a single class.
4754 *
4755 * Pass kDumpClassFullDetail into "flags" to get lots of detail.
4756 */
4757void dvmDumpClass(const ClassObject* clazz, int flags)
4758{
4759 dumpClass((void*) clazz, (void*) flags);
4760}
4761
4762/*
4763 * Dump the contents of all classes.
4764 */
4765void dvmDumpAllClasses(int flags)
4766{
4767 dvmHashTableLock(gDvm.loadedClasses);
4768 dvmHashForeach(gDvm.loadedClasses, dumpClass, (void*) flags);
4769 dvmHashTableUnlock(gDvm.loadedClasses);
4770}
4771
4772/*
4773 * Get the number of loaded classes
4774 */
4775int dvmGetNumLoadedClasses()
4776{
4777 int count;
4778 dvmHashTableLock(gDvm.loadedClasses);
4779 count = dvmHashTableNumEntries(gDvm.loadedClasses);
4780 dvmHashTableUnlock(gDvm.loadedClasses);
4781 return count;
4782}
4783
4784/*
4785 * Write some statistics to the log file.
4786 */
4787void dvmDumpLoaderStats(const char* msg)
4788{
4789 LOGV("VM stats (%s): cls=%d/%d meth=%d ifld=%d sfld=%d linear=%d\n",
4790 msg, gDvm.numLoadedClasses, dvmHashTableNumEntries(gDvm.loadedClasses),
4791 gDvm.numDeclaredMethods, gDvm.numDeclaredInstFields,
4792 gDvm.numDeclaredStaticFields, gDvm.pBootLoaderAlloc->curOffset);
4793#ifdef COUNT_PRECISE_METHODS
4794 LOGI("GC precise methods: %d\n",
4795 dvmPointerSetGetCount(gDvm.preciseMethods));
4796#endif
4797}
4798
4799#ifdef PROFILE_FIELD_ACCESS
4800/*
4801 * Dump the field access counts for all fields in this method.
4802 */
4803static int dumpAccessCounts(void* vclazz, void* varg)
4804{
4805 const ClassObject* clazz = (const ClassObject*) vclazz;
4806 int i;
4807
4808 for (i = 0; i < clazz->ifieldCount; i++) {
4809 Field* field = &clazz->ifields[i].field;
4810
4811 if (field->gets != 0)
4812 printf("GI %d %s.%s\n", field->gets,
4813 field->clazz->descriptor, field->name);
4814 if (field->puts != 0)
4815 printf("PI %d %s.%s\n", field->puts,
4816 field->clazz->descriptor, field->name);
4817 }
4818 for (i = 0; i < clazz->sfieldCount; i++) {
4819 Field* field = &clazz->sfields[i].field;
4820
4821 if (field->gets != 0)
4822 printf("GS %d %s.%s\n", field->gets,
4823 field->clazz->descriptor, field->name);
4824 if (field->puts != 0)
4825 printf("PS %d %s.%s\n", field->puts,
4826 field->clazz->descriptor, field->name);
4827 }
4828
4829 return 0;
4830}
4831
4832/*
4833 * Dump the field access counts for all loaded classes.
4834 */
4835void dvmDumpFieldAccessCounts(void)
4836{
4837 dvmHashTableLock(gDvm.loadedClasses);
4838 dvmHashForeach(gDvm.loadedClasses, dumpAccessCounts, NULL);
4839 dvmHashTableUnlock(gDvm.loadedClasses);
4840}
4841#endif
4842
4843
4844/*
4845 * Mark all classes associated with the built-in loader.
4846 */
4847static int markClassObject(void *clazz, void *arg)
4848{
4849 UNUSED_PARAMETER(arg);
4850
4851 dvmMarkObjectNonNull((Object *)clazz);
4852 return 0;
4853}
4854
4855/*
4856 * The garbage collector calls this to mark the class objects for all
4857 * loaded classes.
4858 */
4859void dvmGcScanRootClassLoader()
4860{
4861 /* dvmClassStartup() may not have been called before the first GC.
4862 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004863 if (gDvm.loadedClasses != NULL) {
4864 dvmHashTableLock(gDvm.loadedClasses);
4865 dvmHashForeach(gDvm.loadedClasses, markClassObject, NULL);
4866 dvmHashTableUnlock(gDvm.loadedClasses);
4867 }
4868}
4869
4870
4871/*
4872 * ===========================================================================
4873 * Method Prototypes and Descriptors
4874 * ===========================================================================
4875 */
4876
4877/*
4878 * Compare the two method names and prototypes, a la strcmp(). The
4879 * name is considered the "major" order and the prototype the "minor"
4880 * order. The prototypes are compared as if by dvmCompareMethodProtos().
4881 */
4882int dvmCompareMethodNamesAndProtos(const Method* method1,
4883 const Method* method2)
4884{
4885 int result = strcmp(method1->name, method2->name);
4886
4887 if (result != 0) {
4888 return result;
4889 }
4890
4891 return dvmCompareMethodProtos(method1, method2);
4892}
4893
4894/*
4895 * Compare the two method names and prototypes, a la strcmp(), ignoring
4896 * the return value. The name is considered the "major" order and the
4897 * prototype the "minor" order. The prototypes are compared as if by
4898 * dvmCompareMethodArgProtos().
4899 */
4900int dvmCompareMethodNamesAndParameterProtos(const Method* method1,
4901 const Method* method2)
4902{
4903 int result = strcmp(method1->name, method2->name);
4904
4905 if (result != 0) {
4906 return result;
4907 }
4908
4909 return dvmCompareMethodParameterProtos(method1, method2);
4910}
4911
4912/*
4913 * Compare a (name, prototype) pair with the (name, prototype) of
4914 * a method, a la strcmp(). The name is considered the "major" order and
4915 * the prototype the "minor" order. The descriptor and prototype are
4916 * compared as if by dvmCompareDescriptorAndMethodProto().
4917 */
4918int dvmCompareNameProtoAndMethod(const char* name,
4919 const DexProto* proto, const Method* method)
4920{
4921 int result = strcmp(name, method->name);
4922
4923 if (result != 0) {
4924 return result;
4925 }
4926
4927 return dexProtoCompare(proto, &method->prototype);
4928}
4929
4930/*
4931 * Compare a (name, method descriptor) pair with the (name, prototype) of
4932 * a method, a la strcmp(). The name is considered the "major" order and
4933 * the prototype the "minor" order. The descriptor and prototype are
4934 * compared as if by dvmCompareDescriptorAndMethodProto().
4935 */
4936int dvmCompareNameDescriptorAndMethod(const char* name,
4937 const char* descriptor, const Method* method)
4938{
4939 int result = strcmp(name, method->name);
4940
4941 if (result != 0) {
4942 return result;
4943 }
4944
4945 return dvmCompareDescriptorAndMethodProto(descriptor, method);
4946}