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