blob: beca5366735f4bb9970d48f56a8c154c4f4c6483 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Code to initialize references to classes and members for use by
* lower-level VM facilities
*/
#include "Dalvik.h"
/*
* Helper for dvmInitRequiredClassesAndMembers(), which looks up
* classes and stores them to the indicated pointer, returning a
* failure code (false == failure).
*/
static bool initRef(ClassObject** pClass, const char* name) {
ClassObject* result;
if (*pClass != NULL) {
/*
* There are a couple cases where it's legit to call this
* function with an already-initialized reference, so just
* silently tolerate this instead of complaining loudly.
*/
return true;
}
if (name[0] == '[') {
result = dvmFindArrayClass(name, NULL);
} else {
result = dvmFindSystemClassNoInit(name);
}
if (result == NULL) {
LOGE("Could not find essential class %s\n", name);
return false;
}
*pClass = result;
return true;
}
static bool find1(void) {
/*
* Note: Under normal VM use, this is called by dvmStartup()
* in Init.c. For dex optimization, this is called as well, but in
* that case, the call is made from DexPrepare.c.
*/
bool ok = true;
/* The corest of the core classes */
ok &= initRef(&gDvm.classJavaLangClass, "Ljava/lang/Class;");
ok &= initRef(&gDvm.classJavaLangObject, "Ljava/lang/Object;");
ok &= initRef(&gDvm.exThrowable, "Ljava/lang/Throwable;");
ok &= initRef(&gDvm.classJavaLangString, "Ljava/lang/String;");
ok &= initRef(&gDvm.classJavaLangThread, "Ljava/lang/Thread;");
ok &= initRef(&gDvm.classJavaLangThreadGroup, "Ljava/lang/ThreadGroup;");
ok &= initRef(&gDvm.classJavaLangVMThread, "Ljava/lang/VMThread;");
/* Exception classes and related support classes */
ok &= initRef(&gDvm.exAbstractMethodError,
"Ljava/lang/AbstractMethodError;");
ok &= initRef(&gDvm.exArithmeticException,
"Ljava/lang/ArithmeticException;");
ok &= initRef(&gDvm.exArrayIndexOutOfBoundsException,
"Ljava/lang/ArrayIndexOutOfBoundsException;");
ok &= initRef(&gDvm.exArrayStoreException,
"Ljava/lang/ArrayStoreException;");
ok &= initRef(&gDvm.exClassCastException,
"Ljava/lang/ClassCastException;");
ok &= initRef(&gDvm.exClassCircularityError,
"Ljava/lang/ClassCircularityError;");
ok &= initRef(&gDvm.exClassNotFoundException,
"Ljava/lang/ClassNotFoundException;");
ok &= initRef(&gDvm.exClassFormatError, "Ljava/lang/ClassFormatError;");
ok &= initRef(&gDvm.exError, "Ljava/lang/Error;");
ok &= initRef(&gDvm.exExceptionInInitializerError,
"Ljava/lang/ExceptionInInitializerError;");
ok &= initRef(&gDvm.exFileNotFoundException,
"Ljava/io/FileNotFoundException;");
ok &= initRef(&gDvm.exIOException, "Ljava/io/IOException;");
ok &= initRef(&gDvm.exIllegalAccessError,
"Ljava/lang/IllegalAccessError;");
ok &= initRef(&gDvm.exIllegalAccessException,
"Ljava/lang/IllegalAccessException;");
ok &= initRef(&gDvm.exIllegalArgumentException,
"Ljava/lang/IllegalArgumentException;");
ok &= initRef(&gDvm.exIllegalMonitorStateException,
"Ljava/lang/IllegalMonitorStateException;");
ok &= initRef(&gDvm.exIllegalStateException,
"Ljava/lang/IllegalStateException;");
ok &= initRef(&gDvm.exIllegalThreadStateException,
"Ljava/lang/IllegalThreadStateException;");
ok &= initRef(&gDvm.exIncompatibleClassChangeError,
"Ljava/lang/IncompatibleClassChangeError;");
ok &= initRef(&gDvm.exInstantiationError,
"Ljava/lang/InstantiationError;");
ok &= initRef(&gDvm.exInstantiationException,
"Ljava/lang/InstantiationException;");
ok &= initRef(&gDvm.exInternalError,
"Ljava/lang/InternalError;");
ok &= initRef(&gDvm.exInterruptedException,
"Ljava/lang/InterruptedException;");
ok &= initRef(&gDvm.exLinkageError,
"Ljava/lang/LinkageError;");
ok &= initRef(&gDvm.exNegativeArraySizeException,
"Ljava/lang/NegativeArraySizeException;");
ok &= initRef(&gDvm.exNoClassDefFoundError,
"Ljava/lang/NoClassDefFoundError;");
ok &= initRef(&gDvm.exNoSuchFieldError,
"Ljava/lang/NoSuchFieldError;");
ok &= initRef(&gDvm.exNoSuchFieldException,
"Ljava/lang/NoSuchFieldException;");
ok &= initRef(&gDvm.exNoSuchMethodError,
"Ljava/lang/NoSuchMethodError;");
ok &= initRef(&gDvm.exNullPointerException,
"Ljava/lang/NullPointerException;");
ok &= initRef(&gDvm.exOutOfMemoryError,
"Ljava/lang/OutOfMemoryError;");
ok &= initRef(&gDvm.exRuntimeException, "Ljava/lang/RuntimeException;");
ok &= initRef(&gDvm.exStackOverflowError,
"Ljava/lang/StackOverflowError;");
ok &= initRef(&gDvm.exStaleDexCacheError,
"Ldalvik/system/StaleDexCacheError;");
ok &= initRef(&gDvm.exStringIndexOutOfBoundsException,
"Ljava/lang/StringIndexOutOfBoundsException;");
ok &= initRef(&gDvm.exTypeNotPresentException,
"Ljava/lang/TypeNotPresentException;");
ok &= initRef(&gDvm.exUnsatisfiedLinkError,
"Ljava/lang/UnsatisfiedLinkError;");
ok &= initRef(&gDvm.exUnsupportedOperationException,
"Ljava/lang/UnsupportedOperationException;");
ok &= initRef(&gDvm.exVerifyError,
"Ljava/lang/VerifyError;");
ok &= initRef(&gDvm.exVirtualMachineError,
"Ljava/lang/VirtualMachineError;");
ok &= initRef(&gDvm.classJavaLangStackTraceElement,
"Ljava/lang/StackTraceElement;");
ok &= initRef(&gDvm.classJavaLangStackTraceElementArray,
"[Ljava/lang/StackTraceElement;");
if (!ok) {
return false;
}
/*
* Find the StackTraceElement constructor. Note that, unlike other
* saved method lookups, we're using a Method* instead of a vtable
* offset. This is because constructors don't have vtable offsets.
* (Also, since we're creating the object in question, it's
* impossible for anyone to sub-class it.)
*/
Method* meth;
meth = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangStackTraceElement,
"<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
if (meth == NULL) {
LOGE("Unable to find constructor for StackTraceElement\n");
return false;
}
gDvm.methJavaLangStackTraceElement_init = meth;
/* grab an offset for the field Throwable.stackState */
gDvm.offJavaLangThrowable_stackState =
dvmFindFieldOffset(gDvm.exThrowable,
"stackState", "Ljava/lang/Object;");
if (gDvm.offJavaLangThrowable_stackState < 0) {
LOGE("Unable to find Throwable.stackState\n");
return false;
}
/* and one for the field Throwable.cause, just 'cause */
gDvm.offJavaLangThrowable_cause =
dvmFindFieldOffset(gDvm.exThrowable,
"cause", "Ljava/lang/Throwable;");
if (gDvm.offJavaLangThrowable_cause < 0) {
LOGE("Unable to find Throwable.cause\n");
return false;
}
return true;
}
static bool find2(void) {
ClassObject* clClass = dvmFindSystemClassNoInit("Ljava/lang/ClassLoader;");
Method* meth = dvmFindVirtualMethodByDescriptor(clClass, "loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;");
if (meth == NULL) {
LOGE("Unable to find loadClass() in java.lang.ClassLoader\n");
return false;
}
gDvm.voffJavaLangClassLoader_loadClass = meth->methodIndex;
return true;
}
static bool find3(void) {
assert(gDvm.classJavaLangThread != NULL);
assert(gDvm.classJavaLangThreadGroup != NULL);
assert(gDvm.classJavaLangVMThread != NULL);
/*
* Cache field offsets. This makes things a little faster, at the
* expense of hard-coding non-public field names into the VM.
*/
gDvm.offJavaLangThread_vmThread =
dvmFindFieldOffset(gDvm.classJavaLangThread,
"vmThread", "Ljava/lang/VMThread;");
gDvm.offJavaLangThread_group =
dvmFindFieldOffset(gDvm.classJavaLangThread,
"group", "Ljava/lang/ThreadGroup;");
gDvm.offJavaLangThread_daemon =
dvmFindFieldOffset(gDvm.classJavaLangThread, "daemon", "Z");
gDvm.offJavaLangThread_name =
dvmFindFieldOffset(gDvm.classJavaLangThread,
"name", "Ljava/lang/String;");
gDvm.offJavaLangThread_priority =
dvmFindFieldOffset(gDvm.classJavaLangThread, "priority", "I");
if (gDvm.offJavaLangThread_vmThread < 0 ||
gDvm.offJavaLangThread_group < 0 ||
gDvm.offJavaLangThread_daemon < 0 ||
gDvm.offJavaLangThread_name < 0 ||
gDvm.offJavaLangThread_priority < 0)
{
LOGE("Unable to find all fields in java.lang.Thread\n");
return false;
}
gDvm.offJavaLangVMThread_thread =
dvmFindFieldOffset(gDvm.classJavaLangVMThread,
"thread", "Ljava/lang/Thread;");
gDvm.offJavaLangVMThread_vmData =
dvmFindFieldOffset(gDvm.classJavaLangVMThread, "vmData", "I");
if (gDvm.offJavaLangVMThread_thread < 0 ||
gDvm.offJavaLangVMThread_vmData < 0)
{
LOGE("Unable to find all fields in java.lang.VMThread\n");
return false;
}
/*
* Cache the vtable offset for "run()".
*
* We don't want to keep the Method* because then we won't find see
* methods defined in subclasses.
*/
Method* meth;
meth = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangThread, "run", "()V");
if (meth == NULL) {
LOGE("Unable to find run() in java.lang.Thread\n");
return false;
}
gDvm.voffJavaLangThread_run = meth->methodIndex;
/*
* Cache vtable offsets for ThreadGroup methods.
*/
meth = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangThreadGroup,
"removeThread", "(Ljava/lang/Thread;)V");
if (meth == NULL) {
LOGE("Unable to find removeThread(Thread) in java.lang.ThreadGroup\n");
return false;
}
gDvm.voffJavaLangThreadGroup_removeThread = meth->methodIndex;
return true;
}
static bool find4(void) {
Method* meth;
/*
* Look up and cache pointers to some direct buffer classes, fields,
* and methods.
*/
ClassObject* readWriteBufferClass =
dvmFindSystemClassNoInit("Ljava/nio/ReadWriteDirectByteBuffer;");
ClassObject* bufferClass =
dvmFindSystemClassNoInit("Ljava/nio/Buffer;");
if (readWriteBufferClass == NULL || bufferClass == NULL) {
LOGE("Unable to find internal direct buffer classes\n");
return false;
}
gDvm.classJavaNioReadWriteDirectByteBuffer = readWriteBufferClass;
meth = dvmFindDirectMethodByDescriptor(readWriteBufferClass,
"<init>",
"(II)V");
if (meth == NULL) {
LOGE("Unable to find ReadWriteDirectByteBuffer.<init>\n");
return false;
}
gDvm.methJavaNioReadWriteDirectByteBuffer_init = meth;
gDvm.offJavaNioBuffer_capacity =
dvmFindFieldOffset(bufferClass, "capacity", "I");
if (gDvm.offJavaNioBuffer_capacity < 0) {
LOGE("Unable to find Buffer.capacity\n");
return false;
}
gDvm.offJavaNioBuffer_effectiveDirectAddress =
dvmFindFieldOffset(bufferClass, "effectiveDirectAddress", "I");
if (gDvm.offJavaNioBuffer_effectiveDirectAddress < 0) {
LOGE("Unable to find Buffer.effectiveDirectAddress\n");
return false;
}
return true;
}
static bool find5(void)
{
gDvm.classJavaLangReflectAccessibleObject =
dvmFindSystemClassNoInit("Ljava/lang/reflect/AccessibleObject;");
gDvm.classJavaLangReflectConstructor =
dvmFindSystemClassNoInit("Ljava/lang/reflect/Constructor;");
gDvm.classJavaLangReflectConstructorArray =
dvmFindArrayClass("[Ljava/lang/reflect/Constructor;", NULL);
gDvm.classJavaLangReflectField =
dvmFindSystemClassNoInit("Ljava/lang/reflect/Field;");
gDvm.classJavaLangReflectFieldArray =
dvmFindArrayClass("[Ljava/lang/reflect/Field;", NULL);
gDvm.classJavaLangReflectMethod =
dvmFindSystemClassNoInit("Ljava/lang/reflect/Method;");
gDvm.classJavaLangReflectMethodArray =
dvmFindArrayClass("[Ljava/lang/reflect/Method;", NULL);
gDvm.classJavaLangReflectProxy =
dvmFindSystemClassNoInit("Ljava/lang/reflect/Proxy;");
if (gDvm.classJavaLangReflectAccessibleObject == NULL ||
gDvm.classJavaLangReflectConstructor == NULL ||
gDvm.classJavaLangReflectConstructorArray == NULL ||
gDvm.classJavaLangReflectField == NULL ||
gDvm.classJavaLangReflectFieldArray == NULL ||
gDvm.classJavaLangReflectMethod == NULL ||
gDvm.classJavaLangReflectMethodArray == NULL ||
gDvm.classJavaLangReflectProxy == NULL)
{
LOGE("Could not find one or more reflection classes\n");
return false;
}
gDvm.methJavaLangReflectConstructor_init =
dvmFindDirectMethodByDescriptor(gDvm.classJavaLangReflectConstructor, "<init>",
"(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;I)V");
gDvm.methJavaLangReflectField_init =
dvmFindDirectMethodByDescriptor(gDvm.classJavaLangReflectField, "<init>",
"(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;I)V");
gDvm.methJavaLangReflectMethod_init =
dvmFindDirectMethodByDescriptor(gDvm.classJavaLangReflectMethod, "<init>",
"(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;I)V");
if (gDvm.methJavaLangReflectConstructor_init == NULL ||
gDvm.methJavaLangReflectField_init == NULL ||
gDvm.methJavaLangReflectMethod_init == NULL)
{
LOGE("Could not find reflection constructors\n");
return false;
}
gDvm.classJavaLangClassArray =
dvmFindArrayClass("[Ljava/lang/Class;", NULL);
gDvm.classJavaLangObjectArray =
dvmFindArrayClass("[Ljava/lang/Object;", NULL);
if (gDvm.classJavaLangClassArray == NULL ||
gDvm.classJavaLangObjectArray == NULL)
{
LOGE("Could not find class-array or object-array class\n");
return false;
}
gDvm.offJavaLangReflectAccessibleObject_flag =
dvmFindFieldOffset(gDvm.classJavaLangReflectAccessibleObject, "flag",
"Z");
gDvm.offJavaLangReflectConstructor_slot =
dvmFindFieldOffset(gDvm.classJavaLangReflectConstructor, "slot", "I");
gDvm.offJavaLangReflectConstructor_declClass =
dvmFindFieldOffset(gDvm.classJavaLangReflectConstructor,
"declaringClass", "Ljava/lang/Class;");
gDvm.offJavaLangReflectField_slot =
dvmFindFieldOffset(gDvm.classJavaLangReflectField, "slot", "I");
gDvm.offJavaLangReflectField_declClass =
dvmFindFieldOffset(gDvm.classJavaLangReflectField,
"declaringClass", "Ljava/lang/Class;");
gDvm.offJavaLangReflectMethod_slot =
dvmFindFieldOffset(gDvm.classJavaLangReflectMethod, "slot", "I");
gDvm.offJavaLangReflectMethod_declClass =
dvmFindFieldOffset(gDvm.classJavaLangReflectMethod,
"declaringClass", "Ljava/lang/Class;");
if (gDvm.offJavaLangReflectAccessibleObject_flag < 0 ||
gDvm.offJavaLangReflectConstructor_slot < 0 ||
gDvm.offJavaLangReflectConstructor_declClass < 0 ||
gDvm.offJavaLangReflectField_slot < 0 ||
gDvm.offJavaLangReflectField_declClass < 0 ||
gDvm.offJavaLangReflectMethod_slot < 0 ||
gDvm.offJavaLangReflectMethod_declClass < 0)
{
LOGE("Could not find reflection fields\n");
return false;
}
return true;
}
static bool find6()
{
/*
* Standard methods we must provide in our proxy.
*/
Method* methE;
Method* methH;
Method* methT;
Method* methF;
methE = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
"equals", "(Ljava/lang/Object;)Z");
methH = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
"hashCode", "()I");
methT = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
"toString", "()Ljava/lang/String;");
methF = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
"finalize", "()V");
if (methE == NULL || methH == NULL || methT == NULL || methF == NULL) {
LOGE("Could not find equals/hashCode/toString/finalize in Object\n");
return false;
}
gDvm.voffJavaLangObject_equals = methE->methodIndex;
gDvm.voffJavaLangObject_hashCode = methH->methodIndex;
gDvm.voffJavaLangObject_toString = methT->methodIndex;
gDvm.voffJavaLangObject_finalize = methF->methodIndex;
/*
* The prototype signature needs to be cloned from a method in a
* "real" DEX file. We declared this otherwise unused method just
* for this purpose.
*/
ClassObject* proxyClass;
Method* meth;
proxyClass = dvmFindSystemClassNoInit("Ljava/lang/reflect/Proxy;");
if (proxyClass == NULL) {
LOGE("No java.lang.reflect.Proxy\n");
return false;
}
meth = dvmFindDirectMethodByDescriptor(proxyClass, "constructorPrototype",
"(Ljava/lang/reflect/InvocationHandler;)V");
if (meth == NULL) {
LOGE("Could not find java.lang.Proxy.constructorPrototype()\n");
return false;
}
gDvm.methJavaLangReflectProxy_constructorPrototype = meth;
/*
* Get the offset of the "h" field in Proxy.
*/
gDvm.offJavaLangReflectProxy_h = dvmFindFieldOffset(proxyClass, "h",
"Ljava/lang/reflect/InvocationHandler;");
if (gDvm.offJavaLangReflectProxy_h < 0) {
LOGE("Unable to find 'h' field in java.lang.Proxy\n");
return false;
}
return true;
}
/*
* Perform Annotation setup.
*/
static bool find7(void)
{
Method* meth;
/*
* Find some standard Annotation classes.
*/
gDvm.classJavaLangAnnotationAnnotationArray =
dvmFindArrayClass("[Ljava/lang/annotation/Annotation;", NULL);
gDvm.classJavaLangAnnotationAnnotationArrayArray =
dvmFindArrayClass("[[Ljava/lang/annotation/Annotation;", NULL);
if (gDvm.classJavaLangAnnotationAnnotationArray == NULL ||
gDvm.classJavaLangAnnotationAnnotationArrayArray == NULL)
{
LOGE("Could not find Annotation-array classes\n");
return false;
}
/*
* VM-specific annotation classes.
*/
gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory =
dvmFindSystemClassNoInit("Lorg/apache/harmony/lang/annotation/AnnotationFactory;");
gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember =
dvmFindSystemClassNoInit("Lorg/apache/harmony/lang/annotation/AnnotationMember;");
gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray =
dvmFindArrayClass("[Lorg/apache/harmony/lang/annotation/AnnotationMember;", NULL);
if (gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory == NULL ||
gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember == NULL ||
gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray == NULL)
{
LOGE("Could not find android.lang annotation classes\n");
return false;
}
meth = dvmFindDirectMethodByDescriptor(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory,
"createAnnotation",
"(Ljava/lang/Class;[Lorg/apache/harmony/lang/annotation/AnnotationMember;)Ljava/lang/annotation/Annotation;");
if (meth == NULL) {
LOGE("Unable to find createAnnotation() in android AnnotationFactory\n");
return false;
}
gDvm.methOrgApacheHarmonyLangAnnotationAnnotationFactory_createAnnotation = meth;
meth = dvmFindDirectMethodByDescriptor(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember,
"<init>",
"(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/reflect/Method;)V");
if (meth == NULL) {
LOGE("Unable to find 4-arg constructor in android AnnotationMember\n");
return false;
}
gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init = meth;
return true;
}
static bool find8(void) {
ClassObject* clazz =
dvmFindClassNoInit("Ldalvik/system/VMDebug;", NULL);
assert(clazz != NULL);
gDvm.methodTraceGcMethod =
dvmFindDirectMethodByDescriptor(clazz, "startGC", "()V");
gDvm.methodTraceClassPrepMethod =
dvmFindDirectMethodByDescriptor(clazz, "startClassPrep", "()V");
if (gDvm.methodTraceGcMethod == NULL ||
gDvm.methodTraceClassPrepMethod == NULL)
{
LOGE("Unable to find startGC or startClassPrep\n");
return false;
}
return true;
}
static bool find9(void) {
gDvm.offJavaLangString_value =
dvmFindFieldOffset(gDvm.classJavaLangString, "value", "[C");
gDvm.offJavaLangString_count =
dvmFindFieldOffset(gDvm.classJavaLangString, "count", "I");
gDvm.offJavaLangString_offset =
dvmFindFieldOffset(gDvm.classJavaLangString, "offset", "I");
gDvm.offJavaLangString_hashCode =
dvmFindFieldOffset(gDvm.classJavaLangString, "hashCode", "I");
if (gDvm.offJavaLangString_value < 0 ||
gDvm.offJavaLangString_count < 0 ||
gDvm.offJavaLangString_offset < 0 ||
gDvm.offJavaLangString_hashCode < 0)
{
LOGE("VM-required field missing from java/lang/String\n");
return false;
}
bool badValue = false;
if (gDvm.offJavaLangString_value != STRING_FIELDOFF_VALUE) {
LOGE("InlineNative: String.value offset = %d, expected %d\n",
gDvm.offJavaLangString_value, STRING_FIELDOFF_VALUE);
badValue = true;
}
if (gDvm.offJavaLangString_count != STRING_FIELDOFF_COUNT) {
LOGE("InlineNative: String.count offset = %d, expected %d\n",
gDvm.offJavaLangString_count, STRING_FIELDOFF_COUNT);
badValue = true;
}
if (gDvm.offJavaLangString_offset != STRING_FIELDOFF_OFFSET) {
LOGE("InlineNative: String.offset offset = %d, expected %d\n",
gDvm.offJavaLangString_offset, STRING_FIELDOFF_OFFSET);
badValue = true;
}
if (gDvm.offJavaLangString_hashCode != STRING_FIELDOFF_HASHCODE) {
LOGE("InlineNative: String.hashCode offset = %d, expected %d\n",
gDvm.offJavaLangString_hashCode, STRING_FIELDOFF_HASHCODE);
badValue = true;
}
if (badValue)
return false;
return true;
}
/* (documented in header) */
bool dvmFindRequiredClassesAndMembers(void) {
bool ok = true;
ok &= find1();
ok &= find2();
ok &= find3();
ok &= find4();
ok &= find5();
ok &= find6();
ok &= find7();
ok &= find8();
ok &= find9();
return ok;
}
/* (documented in header) */
bool dvmFindReferenceMembers(ClassObject* classReference) {
if (gDvm.methJavaLangRefReference_enqueueInternal != NULL) {
LOGE("Attempt to set up class Reference more than once\n");
return false;
}
if (strcmp(classReference->descriptor, "Ljava/lang/ref/Reference;") != 0) {
LOGE("Attempt to set up the wrong class as Reference\n");
return false;
}
bool ok = true;
gDvm.offJavaLangRefReference_referent =
dvmFindFieldOffset(classReference, "referent", "Ljava/lang/Object;");
ok &= (gDvm.offJavaLangRefReference_referent >= 0);
gDvm.offJavaLangRefReference_queue =
dvmFindFieldOffset(classReference, "queue", "Ljava/lang/ref/ReferenceQueue;");
ok &= (gDvm.offJavaLangRefReference_queue >= 0);
gDvm.offJavaLangRefReference_queueNext =
dvmFindFieldOffset(classReference, "queueNext", "Ljava/lang/ref/Reference;");
ok &= (gDvm.offJavaLangRefReference_queueNext >= 0);
gDvm.offJavaLangRefReference_pendingNext =
dvmFindFieldOffset(classReference, "pendingNext", "Ljava/lang/ref/Reference;");
ok &= (gDvm.offJavaLangRefReference_pendingNext >= 0);
/* enqueueInternal() is private and thus a direct method. */
Method *meth = dvmFindDirectMethodByDescriptor(classReference, "enqueueInternal", "()Z");
ok &= (meth != NULL);
gDvm.methJavaLangRefReference_enqueueInternal = meth;
return ok;
}