/* * Copyright (C) 2008 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. */ /* * java.lang.Class */ #include "Dalvik.h" #include "native/InternalNativePriv.h" /* * native public boolean desiredAssertionStatus() * * Determine the class-init-time assertion status of a class. This is * called from <clinit> in javac-generated classes that use the Java * programming language "assert" keyword. */ static void Dalvik_java_lang_Class_desiredAssertionStatus(const u4* args, JValue* pResult) { ClassObject* thisPtr = (ClassObject*) args[0]; char* className = dvmDescriptorToName(thisPtr->descriptor); int i; bool enable = false; /* * Run through the list of arguments specified on the command line. The * last matching argument takes precedence. */ for (i = 0; i < gDvm.assertionCtrlCount; i++) { const AssertionControl* pCtrl = &gDvm.assertionCtrl[i]; if (pCtrl->isPackage) { /* * Given "dalvik/system/Debug" or "MyStuff", compute the * length of the package portion of the class name string. * * Unlike most package operations, we allow matching on * "sub-packages", so "dalvik..." will match "dalvik.Foo" * and "dalvik.system.Foo". * * The pkgOrClass string looks like "dalvik/system/", i.e. it still * has the terminating slash, so we can be sure we're comparing * against full package component names. */ const char* lastSlash; int pkgLen; lastSlash = strrchr(className, '/'); if (lastSlash == NULL) { pkgLen = 0; } else { pkgLen = lastSlash - className +1; } if (pCtrl->pkgOrClassLen > pkgLen || memcmp(pCtrl->pkgOrClass, className, pCtrl->pkgOrClassLen) != 0) { LOGV("ASRT: pkg no match: '%s'(%d) vs '%s'\n", className, pkgLen, pCtrl->pkgOrClass); } else { LOGV("ASRT: pkg match: '%s'(%d) vs '%s' --> %d\n", className, pkgLen, pCtrl->pkgOrClass, pCtrl->enable); enable = pCtrl->enable; } } else { /* * "pkgOrClass" holds a fully-qualified class name, converted from * dot-form to slash-form. An empty string means all classes. */ if (pCtrl->pkgOrClass == NULL) { /* -esa/-dsa; see if class is a "system" class */ if (strncmp(className, "java/", 5) != 0) { LOGV("ASRT: sys no match: '%s'\n", className); } else { LOGV("ASRT: sys match: '%s' --> %d\n", className, pCtrl->enable); enable = pCtrl->enable; } } else if (*pCtrl->pkgOrClass == '\0') { LOGV("ASRT: class all: '%s' --> %d\n", className, pCtrl->enable); enable = pCtrl->enable; } else { if (strcmp(pCtrl->pkgOrClass, className) != 0) { LOGV("ASRT: cls no match: '%s' vs '%s'\n", className, pCtrl->pkgOrClass); } else { LOGV("ASRT: cls match: '%s' vs '%s' --> %d\n", className, pCtrl->pkgOrClass, pCtrl->enable); enable = pCtrl->enable; } } } } free(className); RETURN_INT(enable); } /* * static public Class<?> classForName(String name, boolean initialize, * ClassLoader loader) * * Return the Class object associated with the class or interface with * the specified name. * * "name" is in "binary name" format, e.g. "dalvik.system.Debug$1". */ static void Dalvik_java_lang_Class_classForName(const u4* args, JValue* pResult) { StringObject* nameObj = (StringObject*) args[0]; bool initialize = (args[1] != 0); Object* loader = (Object*) args[2]; RETURN_PTR(dvmFindClassByName(nameObj, loader, initialize)); } /* * static private ClassLoader getClassLoader(Class clazz) * * Return the class' defining class loader. */ static void Dalvik_java_lang_Class_getClassLoader(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; RETURN_PTR(clazz->classLoader); } /* * public Class<?> getComponentType() * * If this is an array type, return the class of the elements; otherwise * return NULL. */ static void Dalvik_java_lang_Class_getComponentType(const u4* args, JValue* pResult) { ClassObject* thisPtr = (ClassObject*) args[0]; if (!dvmIsArrayClass(thisPtr)) RETURN_PTR(NULL); /* * We can't just return thisPtr->elementClass, because that gives * us the base type (e.g. X[][][] returns X). If this is a multi- * dimensional array, we have to do the lookup by name. */ if (thisPtr->descriptor[1] == '[') RETURN_PTR(dvmFindArrayClass(&thisPtr->descriptor[1], thisPtr->classLoader)); else RETURN_PTR(thisPtr->elementClass); } /* * private static Class<?>[] getDeclaredClasses(Class<?> clazz, * boolean publicOnly) * * Return an array with the classes that are declared by the specified class. * If "publicOnly" is set, we strip out any classes that don't have "public" * access. */ static void Dalvik_java_lang_Class_getDeclaredClasses(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; bool publicOnly = (args[1] != 0); ArrayObject* classes; classes = dvmGetDeclaredClasses(clazz); if (classes == NULL) { if (!dvmCheckException(dvmThreadSelf())) { /* empty list, so create a zero-length array */ classes = dvmAllocArrayByClass(gDvm.classJavaLangClassArray, 0, ALLOC_DEFAULT); } } else if (publicOnly) { int i, newIdx, publicCount = 0; ClassObject** pSource = (ClassObject**) classes->contents; /* count up public classes */ for (i = 0; i < (int)classes->length; i++) { if (dvmIsPublicClass(pSource[i])) publicCount++; } /* create a new array to hold them */ ArrayObject* newClasses; newClasses = dvmAllocArrayByClass(gDvm.classJavaLangClassArray, publicCount, ALLOC_DEFAULT); /* copy them over */ ClassObject** pDest = (ClassObject**) newClasses->contents; for (i = newIdx = 0; i < (int)classes->length; i++) { if (dvmIsPublicClass(pSource[i])) pDest[newIdx++] = pSource[i]; } assert(newIdx == publicCount); dvmReleaseTrackedAlloc((Object*) classes, NULL); classes = newClasses; } dvmReleaseTrackedAlloc((Object*) classes, NULL); RETURN_PTR(classes); } /* * static Constructor[] getDeclaredConstructors(Class clazz, boolean publicOnly) * throws SecurityException */ static void Dalvik_java_lang_Class_getDeclaredConstructors(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; bool publicOnly = (args[1] != 0); ArrayObject* constructors; constructors = dvmGetDeclaredConstructors(clazz, publicOnly); dvmReleaseTrackedAlloc((Object*) constructors, NULL); RETURN_PTR(constructors); } /* * static Field[] getDeclaredFields(Class klass, boolean publicOnly) * throws SecurityException */ static void Dalvik_java_lang_Class_getDeclaredFields(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; bool publicOnly = (args[1] != 0); ArrayObject* fields; fields = dvmGetDeclaredFields(clazz, publicOnly); dvmReleaseTrackedAlloc((Object*) fields, NULL); RETURN_PTR(fields); } /* * static Method[] getDeclaredMethods(Class clazz, boolean publicOnly) * throws SecurityException */ static void Dalvik_java_lang_Class_getDeclaredMethods(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; bool publicOnly = (args[1] != 0); ArrayObject* methods; methods = dvmGetDeclaredMethods(clazz, publicOnly); dvmReleaseTrackedAlloc((Object*) methods, NULL); RETURN_PTR(methods); } /* * Class[] getInterfaces() */ static void Dalvik_java_lang_Class_getInterfaces(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; ArrayObject* interfaces; interfaces = dvmGetInterfaces(clazz); dvmReleaseTrackedAlloc((Object*) interfaces, NULL); RETURN_PTR(interfaces); } /* * private static int getModifiers(Class klass, boolean * ignoreInnerClassesAttrib) * * Return the class' modifier flags. If "ignoreInnerClassesAttrib" is false, * and this is an inner class, we return the access flags from the inner class * attribute. */ static void Dalvik_java_lang_Class_getModifiers(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; bool ignoreInner = args[1]; u4 accessFlags; accessFlags = clazz->accessFlags & JAVA_FLAGS_MASK; if (!ignoreInner) { /* see if we have an InnerClass annotation with flags in it */ StringObject* className = NULL; int innerFlags; if (dvmGetInnerClass(clazz, &className, &innerFlags)) accessFlags = innerFlags & JAVA_FLAGS_MASK; dvmReleaseTrackedAlloc((Object*) className, NULL); } RETURN_INT(accessFlags); } /* * public String getName() * * Return the class' name. */ static void Dalvik_java_lang_Class_getName(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; const char* descriptor = clazz->descriptor; StringObject* nameObj; if ((descriptor[0] != 'L') && (descriptor[0] != '[')) { /* * The descriptor indicates that this is the class for * a primitive type; special-case the return value. */ const char* name; switch (descriptor[0]) { case 'Z': name = "boolean"; break; case 'B': name = "byte"; break; case 'C': name = "char"; break; case 'S': name = "short"; break; case 'I': name = "int"; break; case 'J': name = "long"; break; case 'F': name = "float"; break; case 'D': name = "double"; break; case 'V': name = "void"; break; default: { LOGE("Unknown primitive type '%c'\n", descriptor[0]); assert(false); RETURN_PTR(NULL); } } nameObj = dvmCreateStringFromCstr(name, ALLOC_DEFAULT); } else { /* * Convert the UTF-8 name to a java.lang.String. The * name must use '.' to separate package components. * * TODO: this could be more efficient. Consider a custom * conversion function here that walks the string once and * avoids the allocation for the common case (name less than, * say, 128 bytes). */ char* dotName = dvmDescriptorToDot(clazz->descriptor); nameObj = dvmCreateStringFromCstr(dotName, ALLOC_DEFAULT); free(dotName); } dvmReleaseTrackedAlloc((Object*) nameObj, NULL); #if 0 /* doesn't work -- need "java.lang.String" not "java/lang/String" */ { /* * Find the string in the DEX file and use the copy in the intern * table if it already exists (else put one there). Only works * for strings in the DEX file, e.g. not arrays. * * We have to do the class lookup by name in the DEX file because * we don't have a DexClassDef pointer in the ClassObject, and it's * not worth adding one there just for this. Should be cheaper * to do this than the string-creation above. */ const DexFile* pDexFile = clazz->pDexFile; const DexClassDef* pClassDef; const DexClassId* pClassId; pDexFile = clazz->pDexFile; pClassDef = dvmDexFindClass(pDexFile, clazz->descriptor); pClassId = dvmDexGetClassId(pDexFile, pClassDef->classIdx); nameObj = dvmDexGetResolvedString(pDexFile, pClassId->nameIdx); if (nameObj == NULL) { nameObj = dvmResolveString(clazz, pClassId->nameIdx); if (nameObj == NULL) LOGW("WARNING: couldn't find string %u for '%s'\n", pClassId->nameIdx, clazz->name); } } #endif RETURN_PTR(nameObj); } /* * Return the superclass for instances of this class. * * If the class represents a java/lang/Object, an interface, a primitive * type, or void (which *is* a primitive type??), return NULL. * * For an array, return the java/lang/Object ClassObject. */ static void Dalvik_java_lang_Class_getSuperclass(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz)) RETURN_PTR(NULL); else RETURN_PTR(clazz->super); } /* * public boolean isAssignableFrom(Class<?> cls) * * Determine if this class is either the same as, or is a superclass or * superinterface of, the class specified in the "cls" parameter. */ static void Dalvik_java_lang_Class_isAssignableFrom(const u4* args, JValue* pResult) { ClassObject* thisPtr = (ClassObject*) args[0]; ClassObject* testClass = (ClassObject*) args[1]; if (testClass == NULL) { dvmThrowException("Ljava/lang/NullPointerException;", NULL); RETURN_INT(false); } RETURN_INT(dvmInstanceof(testClass, thisPtr)); } /* * public boolean isInstance(Object o) * * Dynamic equivalent of Java programming language "instanceof". */ static void Dalvik_java_lang_Class_isInstance(const u4* args, JValue* pResult) { ClassObject* thisPtr = (ClassObject*) args[0]; Object* testObj = (Object*) args[1]; if (testObj == NULL) RETURN_INT(false); RETURN_INT(dvmInstanceof(testObj->clazz, thisPtr)); } /* * public boolean isInterface() */ static void Dalvik_java_lang_Class_isInterface(const u4* args, JValue* pResult) { ClassObject* thisPtr = (ClassObject*) args[0]; RETURN_INT(dvmIsInterfaceClass(thisPtr)); } /* * public boolean isPrimitive() */ static void Dalvik_java_lang_Class_isPrimitive(const u4* args, JValue* pResult) { ClassObject* thisPtr = (ClassObject*) args[0]; RETURN_INT(dvmIsPrimitiveClass(thisPtr)); } /* * public T newInstance() throws InstantiationException, IllegalAccessException * * Create a new instance of this class. */ static void Dalvik_java_lang_Class_newInstance(const u4* args, JValue* pResult) { Thread* self = dvmThreadSelf(); ClassObject* clazz = (ClassObject*) args[0]; Method* init; Object* newObj; /* can't instantiate these */ if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz) || dvmIsArrayClass(clazz) || dvmIsAbstractClass(clazz)) { LOGD("newInstance failed: p%d i%d [%d a%d\n", dvmIsPrimitiveClass(clazz), dvmIsInterfaceClass(clazz), dvmIsArrayClass(clazz), dvmIsAbstractClass(clazz)); dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;", clazz->descriptor); RETURN_VOID(); } /* initialize the class if it hasn't been already */ if (!dvmIsClassInitialized(clazz)) { if (!dvmInitClass(clazz)) { LOGW("Class init failed in newInstance call (%s)\n", clazz->descriptor); assert(dvmCheckException(self)); RETURN_VOID(); } } /* find the "nullary" constructor */ init = dvmFindDirectMethodByDescriptor(clazz, "<init>", "()V"); if (init == NULL) { /* common cause: secret "this" arg on non-static inner class ctor */ LOGD("newInstance failed: no <init>()\n"); dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;", clazz->descriptor); RETURN_VOID(); } /* * Verify access from the call site. * * First, make sure the method invoking Class.newInstance() has permission * to access the class. * * Second, make sure it has permission to invoke the constructor. The * constructor must be public or, if the caller is in the same package, * have package scope. */ ClassObject* callerClass = dvmGetCaller2Class(self->curFrame); if (!dvmCheckClassAccess(callerClass, clazz)) { LOGD("newInstance failed: %s not accessible to %s\n", clazz->descriptor, callerClass->descriptor); dvmThrowException("Ljava/lang/IllegalAccessException;", "access to class not allowed"); RETURN_VOID(); } if (!dvmCheckMethodAccess(callerClass, init)) { LOGD("newInstance failed: %s.<init>() not accessible to %s\n", clazz->descriptor, callerClass->descriptor); dvmThrowException("Ljava/lang/IllegalAccessException;", "access to constructor not allowed"); RETURN_VOID(); } newObj = dvmAllocObject(clazz, ALLOC_DEFAULT); JValue unused; /* invoke constructor; unlike reflection calls, we don't wrap exceptions */ dvmCallMethod(self, init, newObj, &unused); dvmReleaseTrackedAlloc(newObj, NULL); RETURN_PTR(newObj); } /* * private Object[] getSignatureAnnotation() * * Returns the signature annotation array. */ static void Dalvik_java_lang_Class_getSignatureAnnotation(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; ArrayObject* arr = dvmGetClassSignatureAnnotation(clazz); dvmReleaseTrackedAlloc((Object*) arr, NULL); RETURN_PTR(arr); } /* * public Class getDeclaringClass() * * Get the class that encloses this class (if any). */ static void Dalvik_java_lang_Class_getDeclaringClass(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; ClassObject* enclosing = dvmGetDeclaringClass(clazz); dvmReleaseTrackedAlloc((Object*) enclosing, NULL); RETURN_PTR(enclosing); } /* * public Class getEnclosingClass() * * Get the class that encloses this class (if any). */ static void Dalvik_java_lang_Class_getEnclosingClass(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; ClassObject* enclosing = dvmGetEnclosingClass(clazz); dvmReleaseTrackedAlloc((Object*) enclosing, NULL); RETURN_PTR(enclosing); } /* * public Constructor getEnclosingConstructor() * * Get the constructor that encloses this class (if any). */ static void Dalvik_java_lang_Class_getEnclosingConstructor(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; Object* enclosing = dvmGetEnclosingMethod(clazz); if (enclosing != NULL) { dvmReleaseTrackedAlloc(enclosing, NULL); if (enclosing->clazz == gDvm.classJavaLangReflectConstructor) { RETURN_PTR(enclosing); } assert(enclosing->clazz == gDvm.classJavaLangReflectMethod); } RETURN_PTR(NULL); } /* * public Method getEnclosingMethod() * * Get the method that encloses this class (if any). */ static void Dalvik_java_lang_Class_getEnclosingMethod(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; Object* enclosing = dvmGetEnclosingMethod(clazz); if (enclosing != NULL) { dvmReleaseTrackedAlloc(enclosing, NULL); if (enclosing->clazz == gDvm.classJavaLangReflectMethod) { RETURN_PTR(enclosing); } assert(enclosing->clazz == gDvm.classJavaLangReflectConstructor); } RETURN_PTR(NULL); } #if 0 static void Dalvik_java_lang_Class_getGenericInterfaces(const u4* args, JValue* pResult) { dvmThrowException("Ljava/lang/UnsupportedOperationException;", "native method not implemented"); RETURN_PTR(NULL); } static void Dalvik_java_lang_Class_getGenericSuperclass(const u4* args, JValue* pResult) { dvmThrowException("Ljava/lang/UnsupportedOperationException;", "native method not implemented"); RETURN_PTR(NULL); } static void Dalvik_java_lang_Class_getTypeParameters(const u4* args, JValue* pResult) { dvmThrowException("Ljava/lang/UnsupportedOperationException;", "native method not implemented"); RETURN_PTR(NULL); } #endif /* * public boolean isAnonymousClass() * * Returns true if this is an "anonymous" class. */ static void Dalvik_java_lang_Class_isAnonymousClass(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; StringObject* className = NULL; int accessFlags; /* * If this has an InnerClass annotation, pull it out. Lack of the * annotation, or an annotation with a NULL class name, indicates * that this is an anonymous inner class. */ if (!dvmGetInnerClass(clazz, &className, &accessFlags)) RETURN_BOOLEAN(false); dvmReleaseTrackedAlloc((Object*) className, NULL); RETURN_BOOLEAN(className == NULL); } /* * private Annotation[] getDeclaredAnnotations() * * Return the annotations declared on this class. */ static void Dalvik_java_lang_Class_getDeclaredAnnotations(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; ArrayObject* annos = dvmGetClassAnnotations(clazz); dvmReleaseTrackedAlloc((Object*) annos, NULL); RETURN_PTR(annos); } /* * public String getInnerClassName() * * Returns the simple name of a member class or local class, or null otherwise. */ static void Dalvik_java_lang_Class_getInnerClassName(const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; StringObject* nameObj; int flags; if (dvmGetInnerClass(clazz, &nameObj, &flags)) { dvmReleaseTrackedAlloc((Object*) nameObj, NULL); RETURN_PTR(nameObj); } else { RETURN_PTR(NULL); } } /* * static native void setAccessibleNoCheck(AccessibleObject ao, boolean flag); */ static void Dalvik_java_lang_Class_setAccessibleNoCheck(const u4* args, JValue* pResult) { Object* target = (Object*) args[0]; u4 flag = (u4) args[1]; dvmSetFieldBoolean(target, gDvm.offJavaLangReflectAccessibleObject_flag, flag); } const DalvikNativeMethod dvm_java_lang_Class[] = { { "desiredAssertionStatus", "()Z", Dalvik_java_lang_Class_desiredAssertionStatus }, { "classForName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", Dalvik_java_lang_Class_classForName }, { "getClassLoader", "(Ljava/lang/Class;)Ljava/lang/ClassLoader;", Dalvik_java_lang_Class_getClassLoader }, { "getComponentType", "()Ljava/lang/Class;", Dalvik_java_lang_Class_getComponentType }, { "getSignatureAnnotation", "()[Ljava/lang/Object;", Dalvik_java_lang_Class_getSignatureAnnotation }, { "getDeclaredClasses", "(Ljava/lang/Class;Z)[Ljava/lang/Class;", Dalvik_java_lang_Class_getDeclaredClasses }, { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;", Dalvik_java_lang_Class_getDeclaredConstructors }, { "getDeclaredFields", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;", Dalvik_java_lang_Class_getDeclaredFields }, { "getDeclaredMethods", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;", Dalvik_java_lang_Class_getDeclaredMethods }, { "getInterfaces", "()[Ljava/lang/Class;", Dalvik_java_lang_Class_getInterfaces }, { "getModifiers", "(Ljava/lang/Class;Z)I", Dalvik_java_lang_Class_getModifiers }, { "getName", "()Ljava/lang/String;", Dalvik_java_lang_Class_getName }, { "getSuperclass", "()Ljava/lang/Class;", Dalvik_java_lang_Class_getSuperclass }, { "isAssignableFrom", "(Ljava/lang/Class;)Z", Dalvik_java_lang_Class_isAssignableFrom }, { "isInstance", "(Ljava/lang/Object;)Z", Dalvik_java_lang_Class_isInstance }, { "isInterface", "()Z", Dalvik_java_lang_Class_isInterface }, { "isPrimitive", "()Z", Dalvik_java_lang_Class_isPrimitive }, { "newInstanceImpl", "()Ljava/lang/Object;", Dalvik_java_lang_Class_newInstance }, { "getDeclaringClass", "()Ljava/lang/Class;", Dalvik_java_lang_Class_getDeclaringClass }, { "getEnclosingClass", "()Ljava/lang/Class;", Dalvik_java_lang_Class_getEnclosingClass }, { "getEnclosingConstructor", "()Ljava/lang/reflect/Constructor;", Dalvik_java_lang_Class_getEnclosingConstructor }, { "getEnclosingMethod", "()Ljava/lang/reflect/Method;", Dalvik_java_lang_Class_getEnclosingMethod }, #if 0 { "getGenericInterfaces", "()[Ljava/lang/reflect/Type;", Dalvik_java_lang_Class_getGenericInterfaces }, { "getGenericSuperclass", "()Ljava/lang/reflect/Type;", Dalvik_java_lang_Class_getGenericSuperclass }, { "getTypeParameters", "()Ljava/lang/reflect/TypeVariable;", Dalvik_java_lang_Class_getTypeParameters }, #endif { "isAnonymousClass", "()Z", Dalvik_java_lang_Class_isAnonymousClass }, { "getDeclaredAnnotations", "()[Ljava/lang/annotation/Annotation;", Dalvik_java_lang_Class_getDeclaredAnnotations }, { "getInnerClassName", "()Ljava/lang/String;", Dalvik_java_lang_Class_getInnerClassName }, { "setAccessibleNoCheck", "(Ljava/lang/reflect/AccessibleObject;Z)V", Dalvik_java_lang_Class_setAccessibleNoCheck }, { NULL, NULL, NULL }, };