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