2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * Code to initialize references to classes and members for use by
19 * lower-level VM facilities
24 static bool initClassReference(ClassObject** pClass, const char* name) {
27 assert(*pClass == NULL);
30 result = dvmFindArrayClass(name, NULL);
32 result = dvmFindSystemClassNoInit(name);
36 ALOGE("Could not find essential class %s", name);
44 static bool initClassReferences() {
45 static struct { ClassObject** ref; const char* name; } classes[] = {
47 * Note: The class Class gets special treatment during initial
48 * VM startup, so there is no need to list it here.
51 /* The corest of the core classes */
52 { &gDvm.classJavaLangObject, "Ljava/lang/Object;" },
53 { &gDvm.exThrowable, "Ljava/lang/Throwable;" },
55 /* Slightly less core, but still down there, classes */
56 { &gDvm.classJavaLangClassArray, "[Ljava/lang/Class;" },
57 { &gDvm.classJavaLangClassLoader, "Ljava/lang/ClassLoader;" },
58 { &gDvm.classJavaLangObjectArray, "[Ljava/lang/Object;"},
59 { &gDvm.classJavaLangStackTraceElement, "Ljava/lang/StackTraceElement;" },
60 { &gDvm.classJavaLangStackTraceElementArray, "[Ljava/lang/StackTraceElement;" },
61 { &gDvm.classJavaLangString, "Ljava/lang/String;" },
62 { &gDvm.classJavaLangThread, "Ljava/lang/Thread;" },
63 { &gDvm.classJavaLangThreadGroup, "Ljava/lang/ThreadGroup;" },
64 { &gDvm.classJavaLangVMThread, "Ljava/lang/VMThread;" },
66 /* Arrays of primitive types */
67 { &gDvm.classArrayBoolean, "[Z" },
68 { &gDvm.classArrayByte, "[B" },
69 { &gDvm.classArrayShort, "[S" },
70 { &gDvm.classArrayChar, "[C" },
71 { &gDvm.classArrayInt, "[I" },
72 { &gDvm.classArrayLong, "[J" },
73 { &gDvm.classArrayFloat, "[F" },
74 { &gDvm.classArrayDouble, "[D" },
76 /* Exception classes */
77 { &gDvm.exAbstractMethodError, "Ljava/lang/AbstractMethodError;" },
78 { &gDvm.exArithmeticException, "Ljava/lang/ArithmeticException;" },
79 { &gDvm.exArrayIndexOutOfBoundsException, "Ljava/lang/ArrayIndexOutOfBoundsException;" },
80 { &gDvm.exArrayStoreException, "Ljava/lang/ArrayStoreException;" },
81 { &gDvm.exClassCastException, "Ljava/lang/ClassCastException;" },
82 { &gDvm.exClassCircularityError, "Ljava/lang/ClassCircularityError;" },
83 { &gDvm.exClassNotFoundException, "Ljava/lang/ClassNotFoundException;" },
84 { &gDvm.exClassFormatError, "Ljava/lang/ClassFormatError;" },
85 { &gDvm.exError, "Ljava/lang/Error;" },
86 { &gDvm.exExceptionInInitializerError, "Ljava/lang/ExceptionInInitializerError;" },
87 { &gDvm.exFileNotFoundException, "Ljava/io/FileNotFoundException;" },
88 { &gDvm.exIOException, "Ljava/io/IOException;" },
89 { &gDvm.exIllegalAccessError, "Ljava/lang/IllegalAccessError;" },
90 { &gDvm.exIllegalAccessException, "Ljava/lang/IllegalAccessException;" },
91 { &gDvm.exIllegalArgumentException, "Ljava/lang/IllegalArgumentException;" },
92 { &gDvm.exIllegalMonitorStateException, "Ljava/lang/IllegalMonitorStateException;" },
93 { &gDvm.exIllegalStateException, "Ljava/lang/IllegalStateException;" },
94 { &gDvm.exIllegalThreadStateException, "Ljava/lang/IllegalThreadStateException;" },
95 { &gDvm.exIncompatibleClassChangeError, "Ljava/lang/IncompatibleClassChangeError;" },
96 { &gDvm.exInstantiationError, "Ljava/lang/InstantiationError;" },
97 { &gDvm.exInstantiationException, "Ljava/lang/InstantiationException;" },
98 { &gDvm.exInternalError, "Ljava/lang/InternalError;" },
99 { &gDvm.exInterruptedException, "Ljava/lang/InterruptedException;" },
100 { &gDvm.exLinkageError, "Ljava/lang/LinkageError;" },
101 { &gDvm.exNegativeArraySizeException, "Ljava/lang/NegativeArraySizeException;" },
102 { &gDvm.exNoClassDefFoundError, "Ljava/lang/NoClassDefFoundError;" },
103 { &gDvm.exNoSuchFieldError, "Ljava/lang/NoSuchFieldError;" },
104 { &gDvm.exNoSuchFieldException, "Ljava/lang/NoSuchFieldException;" },
105 { &gDvm.exNoSuchMethodError, "Ljava/lang/NoSuchMethodError;" },
106 { &gDvm.exNullPointerException, "Ljava/lang/NullPointerException;" },
107 { &gDvm.exOutOfMemoryError, "Ljava/lang/OutOfMemoryError;" },
108 { &gDvm.exRuntimeException, "Ljava/lang/RuntimeException;" },
109 { &gDvm.exStackOverflowError, "Ljava/lang/StackOverflowError;" },
110 { &gDvm.exStaleDexCacheError, "Ldalvik/system/StaleDexCacheError;" },
111 { &gDvm.exStringIndexOutOfBoundsException, "Ljava/lang/StringIndexOutOfBoundsException;" },
112 { &gDvm.exTypeNotPresentException, "Ljava/lang/TypeNotPresentException;" },
113 { &gDvm.exUnsatisfiedLinkError, "Ljava/lang/UnsatisfiedLinkError;" },
114 { &gDvm.exUnsupportedOperationException, "Ljava/lang/UnsupportedOperationException;" },
115 { &gDvm.exVerifyError, "Ljava/lang/VerifyError;" },
116 { &gDvm.exVirtualMachineError, "Ljava/lang/VirtualMachineError;" },
119 { &gDvm.classJavaLangAnnotationAnnotationArray, "[Ljava/lang/annotation/Annotation;" },
120 { &gDvm.classJavaLangAnnotationAnnotationArrayArray,
121 "[[Ljava/lang/annotation/Annotation;" },
122 { &gDvm.classJavaLangReflectAccessibleObject, "Ljava/lang/reflect/AccessibleObject;" },
123 { &gDvm.classJavaLangReflectConstructor, "Ljava/lang/reflect/Constructor;" },
124 { &gDvm.classJavaLangReflectConstructorArray, "[Ljava/lang/reflect/Constructor;" },
125 { &gDvm.classJavaLangReflectField, "Ljava/lang/reflect/Field;" },
126 { &gDvm.classJavaLangReflectFieldArray, "[Ljava/lang/reflect/Field;" },
127 { &gDvm.classJavaLangReflectMethod, "Ljava/lang/reflect/Method;" },
128 { &gDvm.classJavaLangReflectMethodArray, "[Ljava/lang/reflect/Method;"},
129 { &gDvm.classJavaLangReflectProxy, "Ljava/lang/reflect/Proxy;" },
130 { &gDvm.classJavaNioDirectByteBuffer, "Ljava/nio/DirectByteBuffer;" },
131 { &gDvm.classOrgApacheHarmonyDalvikDdmcChunk, "Lorg/apache/harmony/dalvik/ddmc/Chunk;" },
132 { &gDvm.classOrgApacheHarmonyDalvikDdmcDdmServer,
133 "Lorg/apache/harmony/dalvik/ddmc/DdmServer;" },
134 { &gDvm.classLibcoreReflectAnnotationFactory, "Llibcore/reflect/AnnotationFactory;" },
135 { &gDvm.classLibcoreReflectAnnotationMember, "Llibcore/reflect/AnnotationMember;" },
136 { &gDvm.classLibcoreReflectAnnotationMemberArray, "[Llibcore/reflect/AnnotationMember;" },
142 for (i = 0; classes[i].ref != NULL; i++) {
143 if (!initClassReference(classes[i].ref, classes[i].name)) {
151 static bool initFieldOffset(ClassObject* clazz, int *pOffset,
152 const char* name, const char* type) {
153 int offset = dvmFindFieldOffset(clazz, name, type);
155 ALOGE("Could not find essential field %s.%s of type %s", clazz->descriptor, name, type);
163 static bool initFieldOffsets() {
170 static struct FieldInfo infoDdmcChunk[] = {
171 { &gDvm.offDalvikDdmcChunk_type, "type", "I" },
172 { &gDvm.offDalvikDdmcChunk_data, "data", "[B" },
173 { &gDvm.offDalvikDdmcChunk_offset, "offset", "I" },
174 { &gDvm.offDalvikDdmcChunk_length, "length", "I" },
178 static struct FieldInfo infoFileDescriptor[] = {
179 { &gDvm.offJavaIoFileDescriptor_descriptor, "descriptor", "I" },
183 static struct FieldInfo infoString[] = {
184 { &gDvm.offJavaLangString_value, "value", "[C" },
185 { &gDvm.offJavaLangString_count, "count", "I" },
186 { &gDvm.offJavaLangString_offset, "offset", "I" },
187 { &gDvm.offJavaLangString_hashCode, "hashCode", "I" },
191 static struct FieldInfo infoThread[] = {
192 { &gDvm.offJavaLangThread_vmThread, "vmThread", "Ljava/lang/VMThread;" },
193 { &gDvm.offJavaLangThread_group, "group", "Ljava/lang/ThreadGroup;" },
194 { &gDvm.offJavaLangThread_daemon, "daemon", "Z" },
195 { &gDvm.offJavaLangThread_name, "name", "Ljava/lang/String;" },
196 { &gDvm.offJavaLangThread_priority, "priority", "I" },
197 { &gDvm.offJavaLangThread_uncaughtHandler, "uncaughtHandler", "Ljava/lang/Thread$UncaughtExceptionHandler;" },
198 { &gDvm.offJavaLangThread_contextClassLoader, "contextClassLoader", "Ljava/lang/ClassLoader;" },
202 static struct FieldInfo infoThreadGroup[] = {
203 { &gDvm.offJavaLangThreadGroup_name, "name", "Ljava/lang/String;" },
204 { &gDvm.offJavaLangThreadGroup_parent, "parent", "Ljava/lang/ThreadGroup;" },
208 static struct FieldInfo infoThrowable[] = {
209 { &gDvm.offJavaLangThrowable_stackState, "stackState", "Ljava/lang/Object;" },
210 { &gDvm.offJavaLangThrowable_cause, "cause", "Ljava/lang/Throwable;" },
214 static struct FieldInfo infoVMThread[] = {
215 { &gDvm.offJavaLangVMThread_thread, "thread", "Ljava/lang/Thread;" },
216 { &gDvm.offJavaLangVMThread_vmData, "vmData", "I" },
220 static struct FieldInfo infoFinalizerReference[] = {
221 { &gDvm.offJavaLangRefFinalizerReference_zombie, "zombie", "Ljava/lang/Object;" },
225 static struct FieldInfo infoConstructor[] = {
226 { &gDvm.offJavaLangReflectConstructor_slot, "slot", "I" },
227 { &gDvm.offJavaLangReflectConstructor_declClass, "declaringClass", "Ljava/lang/Class;" },
231 static struct FieldInfo infoField[] = {
232 { &gDvm.offJavaLangReflectField_slot, "slot", "I" },
233 { &gDvm.offJavaLangReflectField_declClass, "declaringClass", "Ljava/lang/Class;" },
237 static struct FieldInfo infoMethod[] = {
238 { &gDvm.offJavaLangReflectMethod_slot, "slot", "I" },
239 { &gDvm.offJavaLangReflectMethod_declClass, "declaringClass", "Ljava/lang/Class;" },
243 static struct FieldInfo infoProxy[] = {
244 { &gDvm.offJavaLangReflectProxy_h, "h", "Ljava/lang/reflect/InvocationHandler;" },
248 static struct FieldInfo infoBuffer[] = {
249 { &gDvm.offJavaNioBuffer_capacity, "capacity", "I" },
250 { &gDvm.offJavaNioBuffer_effectiveDirectAddress, "effectiveDirectAddress", "J" },
254 static struct { const char* name; const struct FieldInfo* fields; } classes[] = {
255 { "Lorg/apache/harmony/dalvik/ddmc/Chunk;", infoDdmcChunk },
256 { "Ljava/io/FileDescriptor;", infoFileDescriptor },
257 { "Ljava/lang/String;", infoString },
258 { "Ljava/lang/Thread;", infoThread },
259 { "Ljava/lang/ThreadGroup;", infoThreadGroup },
260 { "Ljava/lang/Throwable;", infoThrowable },
261 { "Ljava/lang/VMThread;", infoVMThread },
262 { "Ljava/lang/ref/FinalizerReference;", infoFinalizerReference },
263 { "Ljava/lang/reflect/Constructor;", infoConstructor },
264 { "Ljava/lang/reflect/Field;", infoField },
265 { "Ljava/lang/reflect/Method;", infoMethod },
266 { "Ljava/lang/reflect/Proxy;", infoProxy },
267 { "Ljava/nio/Buffer;", infoBuffer },
272 for (i = 0; classes[i].name != NULL; i++) {
273 const char* className = classes[i].name;
274 ClassObject* clazz = dvmFindSystemClassNoInit(className);
275 const struct FieldInfo* fields = classes[i].fields;
278 ALOGE("Could not find essential class %s for field lookup", className);
283 for (j = 0; fields[j].offset != NULL; j++) {
284 if (!initFieldOffset(clazz, fields[j].offset, fields[j].name, fields[j].type)) {
293 static bool initDirectMethodReferenceByClass(Method** pMethod, ClassObject* clazz,
294 const char* name, const char* descriptor) {
295 Method* method = dvmFindDirectMethodByDescriptor(clazz, name, descriptor);
297 if (method == NULL) {
298 ALOGE("Could not find essential direct method %s.%s with descriptor %s",
299 clazz->descriptor, name, descriptor);
307 static bool initDirectMethodReference(Method** pMethod, const char* className,
308 const char* name, const char* descriptor) {
309 ClassObject* clazz = dvmFindSystemClassNoInit(className);
312 ALOGE("Could not find essential class %s for direct method lookup", className);
316 return initDirectMethodReferenceByClass(pMethod, clazz, name, descriptor);
319 static bool initConstructorReferences() {
320 static struct { Method** method; const char* name; const char* descriptor; } constructors[] = {
321 { &gDvm.methJavaLangStackTraceElement_init, "Ljava/lang/StackTraceElement;",
322 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V" },
323 { &gDvm.methJavaLangReflectConstructor_init, "Ljava/lang/reflect/Constructor;",
324 "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;I)V" },
325 { &gDvm.methJavaLangReflectField_init, "Ljava/lang/reflect/Field;",
326 "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;I)V" },
327 { &gDvm.methJavaLangReflectMethod_init, "Ljava/lang/reflect/Method;",
328 "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;"
329 "Ljava/lang/String;I)V" },
330 { &gDvm.methJavaNioDirectByteBuffer_init, "Ljava/nio/DirectByteBuffer;",
332 { &gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init,
333 "Llibcore/reflect/AnnotationMember;",
334 "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/reflect/Method;)V" },
339 for (i = 0; constructors[i].method != NULL; i++) {
340 if (!initDirectMethodReference(constructors[i].method, constructors[i].name,
341 "<init>", constructors[i].descriptor)) {
349 static bool initDirectMethodReferences() {
352 const char* className;
354 const char* descriptor;
356 { &gDvm.methJavaLangClassLoader_getSystemClassLoader, "Ljava/lang/ClassLoader;",
357 "getSystemClassLoader", "()Ljava/lang/ClassLoader;" },
358 { &gDvm.methJavaLangReflectProxy_constructorPrototype, "Ljava/lang/reflect/Proxy;",
359 "constructorPrototype", "(Ljava/lang/reflect/InvocationHandler;)V" },
360 { &gDvm.methodTraceGcMethod, "Ldalvik/system/VMDebug;", "startGC", "()V" },
361 { &gDvm.methodTraceClassPrepMethod, "Ldalvik/system/VMDebug;", "startClassPrep", "()V" },
362 { &gDvm.methOrgApacheHarmonyLangAnnotationAnnotationFactory_createAnnotation,
363 "Llibcore/reflect/AnnotationFactory;", "createAnnotation",
364 "(Ljava/lang/Class;[Llibcore/reflect/AnnotationMember;)"
365 "Ljava/lang/annotation/Annotation;" },
366 { &gDvm.methDalvikSystemNativeStart_main, "Ldalvik/system/NativeStart;", "main", "([Ljava/lang/String;)V" },
367 { &gDvm.methDalvikSystemNativeStart_run, "Ldalvik/system/NativeStart;", "run", "()V" },
368 { &gDvm.methJavaLangRefFinalizerReferenceAdd,
369 "Ljava/lang/ref/FinalizerReference;", "add", "(Ljava/lang/Object;)V" },
370 { &gDvm.methDalvikDdmcServer_dispatch,
371 "Lorg/apache/harmony/dalvik/ddmc/DdmServer;", "dispatch", "(I[BII)Lorg/apache/harmony/dalvik/ddmc/Chunk;" },
372 { &gDvm.methDalvikDdmcServer_broadcast,
373 "Lorg/apache/harmony/dalvik/ddmc/DdmServer;", "broadcast", "(I)V" },
374 { &gDvm.methJavaLangRefReferenceQueueAdd,
375 "Ljava/lang/ref/ReferenceQueue;", "add", "(Ljava/lang/ref/Reference;)V" },
376 { NULL, NULL, NULL, NULL }
380 for (i = 0; methods[i].method != NULL; i++) {
381 if (!initDirectMethodReference(methods[i].method, methods[i].className,
382 methods[i].name, methods[i].descriptor)) {
390 static bool initVirtualMethodOffset(int* pOffset, const char* className,
391 const char* name, const char* descriptor) {
392 ClassObject* clazz = dvmFindSystemClassNoInit(className);
395 ALOGE("Could not find essential class %s for virtual method lookup", className);
399 Method* method = dvmFindVirtualMethodByDescriptor(clazz, name, descriptor);
401 if (method == NULL) {
402 ALOGE("Could not find essential virtual method %s.%s with descriptor %s",
403 clazz->descriptor, name, descriptor);
407 *pOffset = method->methodIndex;
411 static bool initVirtualMethodOffsets() {
414 const char* className;
416 const char* descriptor;
418 { &gDvm.voffJavaLangClassLoader_loadClass, "Ljava/lang/ClassLoader;", "loadClass",
419 "(Ljava/lang/String;)Ljava/lang/Class;" },
420 { &gDvm.voffJavaLangObject_equals, "Ljava/lang/Object;", "equals",
421 "(Ljava/lang/Object;)Z" },
422 { &gDvm.voffJavaLangObject_hashCode, "Ljava/lang/Object;", "hashCode", "()I" },
423 { &gDvm.voffJavaLangObject_toString, "Ljava/lang/Object;", "toString",
424 "()Ljava/lang/String;" },
425 { &gDvm.voffJavaLangThread_run, "Ljava/lang/Thread;", "run", "()V" },
426 { &gDvm.voffJavaLangThreadGroup_removeThread, "Ljava/lang/ThreadGroup;",
427 "removeThread", "(Ljava/lang/Thread;)V" },
428 { NULL, NULL, NULL, NULL }
432 for (i = 0; methods[i].offset != NULL; i++) {
433 if (!initVirtualMethodOffset(methods[i].offset, methods[i].className,
434 methods[i].name, methods[i].descriptor)) {
442 static bool initFinalizerReference()
444 gDvm.classJavaLangRefFinalizerReference =
445 dvmFindSystemClass("Ljava/lang/ref/FinalizerReference;");
446 return gDvm.classJavaLangRefFinalizerReference != NULL;
449 static bool verifyStringOffset(const char* name, int actual, int expected) {
450 if (actual != expected) {
451 ALOGE("InitRefs: String.%s offset = %d; expected %d", name, actual, expected);
458 static bool verifyStringOffsets() {
460 * Various parts of the system use predefined constants for the
461 * offsets to a few fields of the class String. This code verifies
462 * that the predefined offsets match what is actually defined by
467 ok &= verifyStringOffset("value", gDvm.offJavaLangString_value, STRING_FIELDOFF_VALUE);
468 ok &= verifyStringOffset("count", gDvm.offJavaLangString_count, STRING_FIELDOFF_COUNT);
469 ok &= verifyStringOffset("offset", gDvm.offJavaLangString_offset, STRING_FIELDOFF_OFFSET);
470 ok &= verifyStringOffset("hashCode", gDvm.offJavaLangString_hashCode,
471 STRING_FIELDOFF_HASHCODE);
476 /* (documented in header) */
477 bool dvmFindRequiredClassesAndMembers() {
479 * Note: Under normal VM use, this is called by dvmStartup()
480 * in Init.c. For dex optimization, this is called as well, but in
481 * that case, the call is made from DexPrepare.c.
484 return initClassReferences()
485 && initFieldOffsets()
486 && initConstructorReferences()
487 && initDirectMethodReferences()
488 && initVirtualMethodOffsets()
489 && initFinalizerReference()
490 && verifyStringOffsets();
493 /* (documented in header) */
494 bool dvmFindReferenceMembers(ClassObject* classReference) {
495 if (strcmp(classReference->descriptor, "Ljava/lang/ref/Reference;") != 0) {
496 ALOGE("Attempt to set up the wrong class as Reference");
499 return initFieldOffset(classReference, &gDvm.offJavaLangRefReference_pendingNext,
500 "pendingNext", "Ljava/lang/ref/Reference;")
501 && initFieldOffset(classReference, &gDvm.offJavaLangRefReference_queue,
502 "queue", "Ljava/lang/ref/ReferenceQueue;")
503 && initFieldOffset(classReference, &gDvm.offJavaLangRefReference_queueNext,
504 "queueNext", "Ljava/lang/ref/Reference;")
505 && initFieldOffset(classReference, &gDvm.offJavaLangRefReference_referent,
506 "referent", "Ljava/lang/Object;");