InitRefs.cpp revision 60fc806b679a3655c228b4093058c59941a49cfe
1/*
2 * Copyright (C) 2011 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 * Code to initialize references to classes and members for use by
19 * lower-level VM facilities
20 */
21
22#include "Dalvik.h"
23
24static bool initClassReference(ClassObject** pClass, const char* name) {
25    ClassObject* result;
26
27    assert(*pClass == NULL);
28
29    if (name[0] == '[') {
30        result = dvmFindArrayClass(name, NULL);
31    } else {
32        result = dvmFindSystemClassNoInit(name);
33    }
34
35    if (result == NULL) {
36        LOGE("Could not find essential class %s", name);
37        return false;
38    }
39
40    *pClass = result;
41    return true;
42}
43
44static bool initClassReferences() {
45    static struct { ClassObject** ref; const char* name; } classes[] = {
46        /*
47         * Note: The class Class gets special treatment during initial
48         * VM startup, so there is no need to list it here.
49         */
50
51        /* The corest of the core classes */
52        { &gDvm.classJavaLangObject, "Ljava/lang/Object;" },
53        { &gDvm.exThrowable,         "Ljava/lang/Throwable;" },
54
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;" },
65
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" },
75
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;" },
117
118        /* Other classes */
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.classJavaNioReadWriteDirectByteBuffer,  "Ljava/nio/ReadWriteDirectByteBuffer;" },
131        { &gDvm.classOrgApacheHarmonyDalvikDdmcChunk,
132          "Lorg/apache/harmony/dalvik/ddmc/Chunk;" },
133        { &gDvm.classOrgApacheHarmonyDalvikDdmcDdmServer,
134          "Lorg/apache/harmony/dalvik/ddmc/DdmServer;" },
135        { &gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory,
136          "Lorg/apache/harmony/lang/annotation/AnnotationFactory;" },
137        { &gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember,
138          "Lorg/apache/harmony/lang/annotation/AnnotationMember;" },
139        { &gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray,
140          "[Lorg/apache/harmony/lang/annotation/AnnotationMember;" },
141
142        { NULL, NULL }
143    };
144
145    int i;
146    for (i = 0; classes[i].ref != NULL; i++) {
147        if (!initClassReference(classes[i].ref, classes[i].name)) {
148            return false;
149        }
150    }
151
152    return true;
153}
154
155static bool initFieldOffset(ClassObject* clazz, int *pOffset,
156        const char* name, const char* type) {
157    int offset = dvmFindFieldOffset(clazz, name, type);
158    if (offset < 0) {
159        LOGE("Could not find essential field %s.%s of type %s", clazz->descriptor, name, type);
160        return false;
161    }
162
163    *pOffset = offset;
164    return true;
165}
166
167static bool initFieldOffsets() {
168    struct FieldInfo {
169        int* offset;
170        const char* name;
171        const char* type;
172    };
173
174    static struct FieldInfo infoDdmcChunk[] = {
175        { &gDvm.offDalvikDdmcChunk_type,   "type",   "I" },
176        { &gDvm.offDalvikDdmcChunk_data,   "data",   "[B" },
177        { &gDvm.offDalvikDdmcChunk_offset, "offset", "I" },
178        { &gDvm.offDalvikDdmcChunk_length, "length", "I" },
179        { NULL, NULL, NULL }
180    };
181
182    static struct FieldInfo infoFileDescriptor[] = {
183        { &gDvm.offJavaIoFileDescriptor_descriptor, "descriptor", "I" },
184        { NULL, NULL, NULL }
185    };
186
187    static struct FieldInfo infoString[] = {
188        { &gDvm.offJavaLangString_value,    "value",    "[C" },
189        { &gDvm.offJavaLangString_count,    "count",    "I" },
190        { &gDvm.offJavaLangString_offset,   "offset",   "I" },
191        { &gDvm.offJavaLangString_hashCode, "hashCode", "I" },
192        { NULL, NULL, NULL }
193    };
194
195    static struct FieldInfo infoThread[] = {
196        { &gDvm.offJavaLangThread_vmThread,           "vmThread",           "Ljava/lang/VMThread;" },
197        { &gDvm.offJavaLangThread_group,              "group",              "Ljava/lang/ThreadGroup;" },
198        { &gDvm.offJavaLangThread_daemon,             "daemon",             "Z" },
199        { &gDvm.offJavaLangThread_name,               "name",               "Ljava/lang/String;" },
200        { &gDvm.offJavaLangThread_priority,           "priority",           "I" },
201        { &gDvm.offJavaLangThread_uncaughtHandler,    "uncaughtHandler",    "Ljava/lang/Thread$UncaughtExceptionHandler;" },
202        { &gDvm.offJavaLangThread_contextClassLoader, "contextClassLoader", "Ljava/lang/ClassLoader;" },
203        { NULL, NULL, NULL }
204    };
205
206    static struct FieldInfo infoThreadGroup[] = {
207        { &gDvm.offJavaLangThreadGroup_name,   "name",   "Ljava/lang/String;" },
208        { &gDvm.offJavaLangThreadGroup_parent, "parent", "Ljava/lang/ThreadGroup;" },
209        { NULL, NULL, NULL }
210    };
211
212    static struct FieldInfo infoThrowable[] = {
213        { &gDvm.offJavaLangThrowable_stackState, "stackState", "Ljava/lang/Object;" },
214        { &gDvm.offJavaLangThrowable_cause,      "cause",      "Ljava/lang/Throwable;" },
215        { NULL, NULL, NULL }
216    };
217
218    static struct FieldInfo infoVMThread[] = {
219        { &gDvm.offJavaLangVMThread_thread, "thread", "Ljava/lang/Thread;" },
220        { &gDvm.offJavaLangVMThread_vmData, "vmData", "I" },
221        { NULL, NULL, NULL }
222    };
223
224    static struct FieldInfo infoFinalizerReference[] = {
225        { &gDvm.offJavaLangRefFinalizerReference_zombie, "zombie", "Ljava/lang/Object;" },
226        { NULL, NULL, NULL }
227    };
228
229    static struct FieldInfo infoConstructor[] = {
230        { &gDvm.offJavaLangReflectConstructor_slot,      "slot",           "I" },
231        { &gDvm.offJavaLangReflectConstructor_declClass, "declaringClass", "Ljava/lang/Class;" },
232        { NULL, NULL, NULL }
233    };
234
235    static struct FieldInfo infoField[] = {
236        { &gDvm.offJavaLangReflectField_slot,      "slot",           "I" },
237        { &gDvm.offJavaLangReflectField_declClass, "declaringClass", "Ljava/lang/Class;" },
238        { NULL, NULL, NULL }
239    };
240
241    static struct FieldInfo infoMethod[] = {
242        { &gDvm.offJavaLangReflectMethod_slot,      "slot",           "I" },
243        { &gDvm.offJavaLangReflectMethod_declClass, "declaringClass", "Ljava/lang/Class;" },
244        { NULL, NULL, NULL }
245    };
246
247    static struct FieldInfo infoProxy[] = {
248        { &gDvm.offJavaLangReflectProxy_h, "h", "Ljava/lang/reflect/InvocationHandler;" },
249        { NULL, NULL, NULL }
250    };
251
252    static struct FieldInfo infoBuffer[] = {
253        { &gDvm.offJavaNioBuffer_capacity,               "capacity",               "I" },
254        { &gDvm.offJavaNioBuffer_effectiveDirectAddress, "effectiveDirectAddress", "I" },
255        { NULL, NULL, NULL }
256    };
257
258    static struct { const char* name; const struct FieldInfo* fields; } classes[] = {
259        { "Lorg/apache/harmony/dalvik/ddmc/Chunk;", infoDdmcChunk },
260        { "Ljava/io/FileDescriptor;",               infoFileDescriptor },
261        { "Ljava/lang/String;",                     infoString },
262        { "Ljava/lang/Thread;",                     infoThread },
263        { "Ljava/lang/ThreadGroup;",                infoThreadGroup },
264        { "Ljava/lang/Throwable;",                  infoThrowable },
265        { "Ljava/lang/VMThread;",                   infoVMThread },
266        { "Ljava/lang/ref/FinalizerReference;", infoFinalizerReference },
267        { "Ljava/lang/reflect/Constructor;",        infoConstructor },
268        { "Ljava/lang/reflect/Field;",              infoField },
269        { "Ljava/lang/reflect/Method;",             infoMethod },
270        { "Ljava/lang/reflect/Proxy;",              infoProxy },
271        { "Ljava/nio/Buffer;",                      infoBuffer },
272        { NULL, NULL }
273    };
274
275    int i;
276    for (i = 0; classes[i].name != NULL; i++) {
277        const char* className = classes[i].name;
278        ClassObject* clazz = dvmFindSystemClassNoInit(className);
279        const struct FieldInfo* fields = classes[i].fields;
280
281        if (clazz == NULL) {
282            LOGE("Could not find essential class %s for field lookup", className);
283            return false;
284        }
285
286        int j;
287        for (j = 0; fields[j].offset != NULL; j++) {
288            if (!initFieldOffset(clazz, fields[j].offset, fields[j].name, fields[j].type)) {
289                return false;
290            }
291        }
292    }
293
294    return true;
295}
296
297static bool initDirectMethodReferenceByClass(Method** pMethod, ClassObject* clazz,
298        const char* name, const char* descriptor) {
299    Method* method = dvmFindDirectMethodByDescriptor(clazz, name, descriptor);
300
301    if (method == NULL) {
302        LOGE("Could not find essential direct method %s.%s with descriptor %s",
303                clazz->descriptor, name, descriptor);
304        return false;
305    }
306
307    *pMethod = method;
308    return true;
309}
310
311static bool initDirectMethodReference(Method** pMethod, const char* className,
312        const char* name, const char* descriptor) {
313    ClassObject* clazz = dvmFindSystemClassNoInit(className);
314
315    if (clazz == NULL) {
316        LOGE("Could not find essential class %s for direct method lookup", className);
317        return false;
318    }
319
320    return initDirectMethodReferenceByClass(pMethod, clazz, name, descriptor);
321}
322
323static bool initConstructorReferences() {
324    static struct { Method** method; const char* name; const char* descriptor; } constructors[] = {
325        { &gDvm.methJavaLangStackTraceElement_init, "Ljava/lang/StackTraceElement;",
326          "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V" },
327        { &gDvm.methJavaLangReflectConstructor_init, "Ljava/lang/reflect/Constructor;",
328          "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;I)V" },
329        { &gDvm.methJavaLangReflectField_init, "Ljava/lang/reflect/Field;",
330          "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;I)V" },
331        { &gDvm.methJavaLangReflectMethod_init, "Ljava/lang/reflect/Method;",
332          "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;"
333          "Ljava/lang/String;I)V" },
334        { &gDvm.methJavaNioReadWriteDirectByteBuffer_init, "Ljava/nio/ReadWriteDirectByteBuffer;",
335          "(II)V" },
336        { &gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init,
337          "Lorg/apache/harmony/lang/annotation/AnnotationMember;",
338          "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/reflect/Method;)V" },
339        { NULL, NULL, NULL }
340    };
341
342    int i;
343    for (i = 0; constructors[i].method != NULL; i++) {
344        if (!initDirectMethodReference(constructors[i].method, constructors[i].name,
345                "<init>", constructors[i].descriptor)) {
346            return false;
347        }
348    }
349
350    return true;
351}
352
353static bool initDirectMethodReferences() {
354    static struct {
355        Method** method;
356        const char* className;
357        const char* name;
358        const char* descriptor;
359    } methods[] = {
360        { &gDvm.methJavaLangClassLoader_getSystemClassLoader, "Ljava/lang/ClassLoader;",
361          "getSystemClassLoader", "()Ljava/lang/ClassLoader;" },
362        { &gDvm.methJavaLangReflectProxy_constructorPrototype, "Ljava/lang/reflect/Proxy;",
363          "constructorPrototype", "(Ljava/lang/reflect/InvocationHandler;)V" },
364        { &gDvm.methodTraceGcMethod, "Ldalvik/system/VMDebug;", "startGC", "()V" },
365        { &gDvm.methodTraceClassPrepMethod, "Ldalvik/system/VMDebug;", "startClassPrep", "()V" },
366        { &gDvm.methOrgApacheHarmonyLangAnnotationAnnotationFactory_createAnnotation,
367          "Lorg/apache/harmony/lang/annotation/AnnotationFactory;", "createAnnotation",
368          "(Ljava/lang/Class;[Lorg/apache/harmony/lang/annotation/AnnotationMember;)"
369          "Ljava/lang/annotation/Annotation;" },
370        { &gDvm.methDalvikSystemNativeStart_main, "Ldalvik/system/NativeStart;", "main", "([Ljava/lang/String;)V" },
371        { &gDvm.methDalvikSystemNativeStart_run, "Ldalvik/system/NativeStart;", "run", "()V" },
372        { &gDvm.methJavaLangRefFinalizerReferenceAdd,
373          "Ljava/lang/ref/FinalizerReference;", "add", "(Ljava/lang/Object;)V" },
374        { &gDvm.methDalvikDdmcServer_dispatch,
375          "Lorg/apache/harmony/dalvik/ddmc/DdmServer;", "dispatch", "(I[BII)Lorg/apache/harmony/dalvik/ddmc/Chunk;" },
376        { &gDvm.methDalvikDdmcServer_broadcast,
377          "Lorg/apache/harmony/dalvik/ddmc/DdmServer;", "broadcast", "(I)V" },
378        { &gDvm.methJavaLangRefReferenceQueueAdd,
379          "Ljava/lang/ref/ReferenceQueue;", "add", "(Ljava/lang/ref/Reference;)V" },
380        { NULL, NULL, NULL, NULL }
381    };
382
383    int i;
384    for (i = 0; methods[i].method != NULL; i++) {
385        if (!initDirectMethodReference(methods[i].method, methods[i].className,
386                methods[i].name, methods[i].descriptor)) {
387            return false;
388        }
389    }
390
391    return true;
392}
393
394static bool initVirtualMethodOffset(int* pOffset, const char* className,
395        const char* name, const char* descriptor) {
396    ClassObject* clazz = dvmFindSystemClassNoInit(className);
397
398    if (clazz == NULL) {
399        LOGE("Could not find essential class %s for virtual method lookup", className);
400        return false;
401    }
402
403    Method* method = dvmFindVirtualMethodByDescriptor(clazz, name, descriptor);
404
405    if (method == NULL) {
406        LOGE("Could not find essential virtual method %s.%s with descriptor %s",
407                clazz->descriptor, name, descriptor);
408        return false;
409    }
410
411    *pOffset = method->methodIndex;
412    return true;
413}
414
415static bool initVirtualMethodOffsets() {
416    static struct {
417        int* offset;
418        const char* className;
419        const char* name;
420        const char* descriptor;
421    } methods[] = {
422        { &gDvm.voffJavaLangClassLoader_loadClass, "Ljava/lang/ClassLoader;", "loadClass",
423          "(Ljava/lang/String;)Ljava/lang/Class;" },
424        { &gDvm.voffJavaLangObject_equals, "Ljava/lang/Object;", "equals",
425          "(Ljava/lang/Object;)Z" },
426        { &gDvm.voffJavaLangObject_hashCode, "Ljava/lang/Object;", "hashCode", "()I" },
427        { &gDvm.voffJavaLangObject_toString, "Ljava/lang/Object;", "toString",
428          "()Ljava/lang/String;" },
429        { &gDvm.voffJavaLangThread_run, "Ljava/lang/Thread;", "run", "()V" },
430        { &gDvm.voffJavaLangThreadGroup_removeThread, "Ljava/lang/ThreadGroup;",
431          "removeThread", "(Ljava/lang/Thread;)V" },
432        { NULL, NULL, NULL, NULL }
433    };
434
435    int i;
436    for (i = 0; methods[i].offset != NULL; i++) {
437        if (!initVirtualMethodOffset(methods[i].offset, methods[i].className,
438                methods[i].name, methods[i].descriptor)) {
439            return false;
440        }
441    }
442
443    return true;
444}
445
446static bool initFinalizerReference()
447{
448    gDvm.classJavaLangRefFinalizerReference =
449        dvmFindSystemClass("Ljava/lang/ref/FinalizerReference;");
450    return gDvm.classJavaLangRefFinalizerReference != NULL;
451}
452
453static bool verifyStringOffset(const char* name, int actual, int expected) {
454    if (actual != expected) {
455        LOGE("InitRefs: String.%s offset = %d; expected %d", name, actual, expected);
456        return false;
457    }
458
459    return true;
460}
461
462static bool verifyStringOffsets() {
463    /*
464     * Various parts of the system use predefined constants for the
465     * offsets to a few fields of the class String. This code verifies
466     * that the predefined offsets match what is actually defined by
467     * the class.
468     */
469
470    bool ok = true;
471    ok &= verifyStringOffset("value",    gDvm.offJavaLangString_value,  STRING_FIELDOFF_VALUE);
472    ok &= verifyStringOffset("count",    gDvm.offJavaLangString_count,  STRING_FIELDOFF_COUNT);
473    ok &= verifyStringOffset("offset",   gDvm.offJavaLangString_offset, STRING_FIELDOFF_OFFSET);
474    ok &= verifyStringOffset("hashCode", gDvm.offJavaLangString_hashCode,
475            STRING_FIELDOFF_HASHCODE);
476
477    return ok;
478}
479
480/* (documented in header) */
481bool dvmFindRequiredClassesAndMembers() {
482    /*
483     * Note: Under normal VM use, this is called by dvmStartup()
484     * in Init.c. For dex optimization, this is called as well, but in
485     * that case, the call is made from DexPrepare.c.
486     */
487
488    return initClassReferences()
489        && initFieldOffsets()
490        && initConstructorReferences()
491        && initDirectMethodReferences()
492        && initVirtualMethodOffsets()
493        && initFinalizerReference()
494        && verifyStringOffsets();
495}
496
497/* (documented in header) */
498bool dvmFindReferenceMembers(ClassObject* classReference) {
499    if (strcmp(classReference->descriptor, "Ljava/lang/ref/Reference;") != 0) {
500        LOGE("Attempt to set up the wrong class as Reference");
501        return false;
502    }
503    return initFieldOffset(classReference, &gDvm.offJavaLangRefReference_pendingNext,
504                "pendingNext", "Ljava/lang/ref/Reference;")
505        && initFieldOffset(classReference, &gDvm.offJavaLangRefReference_queue,
506                "queue", "Ljava/lang/ref/ReferenceQueue;")
507        && initFieldOffset(classReference, &gDvm.offJavaLangRefReference_queueNext,
508                "queueNext", "Ljava/lang/ref/Reference;")
509        && initFieldOffset(classReference, &gDvm.offJavaLangRefReference_referent,
510                "referent", "Ljava/lang/Object;");
511}
512