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