Home | History | Annotate | Download | only in native
      1 /*
      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  * java.lang.Class
     19  */
     20 #include "Dalvik.h"
     21 #include "native/InternalNativePriv.h"
     22 
     23 
     24 /*
     25  * native public boolean desiredAssertionStatus()
     26  *
     27  * Determine the class-init-time assertion status of a class.  This is
     28  * called from <clinit> in javac-generated classes that use the Java
     29  * programming language "assert" keyword.
     30  */
     31 static void Dalvik_java_lang_Class_desiredAssertionStatus(const u4* args,
     32     JValue* pResult)
     33 {
     34     ClassObject* thisPtr = (ClassObject*) args[0];
     35     char* className = dvmDescriptorToName(thisPtr->descriptor);
     36     int i;
     37     bool enable = false;
     38 
     39     /*
     40      * Run through the list of arguments specified on the command line.  The
     41      * last matching argument takes precedence.
     42      */
     43     for (i = 0; i < gDvm.assertionCtrlCount; i++) {
     44         const AssertionControl* pCtrl = &gDvm.assertionCtrl[i];
     45 
     46         if (pCtrl->isPackage) {
     47             /*
     48              * Given "dalvik/system/Debug" or "MyStuff", compute the
     49              * length of the package portion of the class name string.
     50              *
     51              * Unlike most package operations, we allow matching on
     52              * "sub-packages", so "dalvik..." will match "dalvik.Foo"
     53              * and "dalvik.system.Foo".
     54              *
     55              * The pkgOrClass string looks like "dalvik/system/", i.e. it still
     56              * has the terminating slash, so we can be sure we're comparing
     57              * against full package component names.
     58              */
     59             const char* lastSlash;
     60             int pkgLen;
     61 
     62             lastSlash = strrchr(className, '/');
     63             if (lastSlash == NULL) {
     64                 pkgLen = 0;
     65             } else {
     66                 pkgLen = lastSlash - className +1;
     67             }
     68 
     69             if (pCtrl->pkgOrClassLen > pkgLen ||
     70                 memcmp(pCtrl->pkgOrClass, className, pCtrl->pkgOrClassLen) != 0)
     71             {
     72                 LOGV("ASRT: pkg no match: '%s'(%d) vs '%s'\n",
     73                     className, pkgLen, pCtrl->pkgOrClass);
     74             } else {
     75                 LOGV("ASRT: pkg match: '%s'(%d) vs '%s' --> %d\n",
     76                     className, pkgLen, pCtrl->pkgOrClass, pCtrl->enable);
     77                 enable = pCtrl->enable;
     78             }
     79         } else {
     80             /*
     81              * "pkgOrClass" holds a fully-qualified class name, converted from
     82              * dot-form to slash-form.  An empty string means all classes.
     83              */
     84             if (pCtrl->pkgOrClass == NULL) {
     85                 /* -esa/-dsa; see if class is a "system" class */
     86                 if (strncmp(className, "java/", 5) != 0) {
     87                     LOGV("ASRT: sys no match: '%s'\n", className);
     88                 } else {
     89                     LOGV("ASRT: sys match: '%s' --> %d\n",
     90                         className, pCtrl->enable);
     91                     enable = pCtrl->enable;
     92                 }
     93             } else if (*pCtrl->pkgOrClass == '\0') {
     94                 LOGV("ASRT: class all: '%s' --> %d\n",
     95                     className, pCtrl->enable);
     96                 enable = pCtrl->enable;
     97             } else {
     98                 if (strcmp(pCtrl->pkgOrClass, className) != 0) {
     99                     LOGV("ASRT: cls no match: '%s' vs '%s'\n",
    100                         className, pCtrl->pkgOrClass);
    101                 } else {
    102                     LOGV("ASRT: cls match: '%s' vs '%s' --> %d\n",
    103                         className, pCtrl->pkgOrClass, pCtrl->enable);
    104                     enable = pCtrl->enable;
    105                 }
    106             }
    107         }
    108     }
    109 
    110     free(className);
    111     RETURN_INT(enable);
    112 }
    113 
    114 /*
    115  * static public Class<?> classForName(String name, boolean initialize,
    116  *     ClassLoader loader)
    117  *
    118  * Return the Class object associated with the class or interface with
    119  * the specified name.
    120  *
    121  * "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
    122  */
    123 static void Dalvik_java_lang_Class_classForName(const u4* args, JValue* pResult)
    124 {
    125     StringObject* nameObj = (StringObject*) args[0];
    126     bool initialize = (args[1] != 0);
    127     Object* loader = (Object*) args[2];
    128 
    129     RETURN_PTR(dvmFindClassByName(nameObj, loader, initialize));
    130 }
    131 
    132 /*
    133  * static private ClassLoader getClassLoader(Class clazz)
    134  *
    135  * Return the class' defining class loader.
    136  */
    137 static void Dalvik_java_lang_Class_getClassLoader(const u4* args,
    138     JValue* pResult)
    139 {
    140     ClassObject* clazz = (ClassObject*) args[0];
    141 
    142     RETURN_PTR(clazz->classLoader);
    143 }
    144 
    145 /*
    146  * public Class<?> getComponentType()
    147  *
    148  * If this is an array type, return the class of the elements; otherwise
    149  * return NULL.
    150  */
    151 static void Dalvik_java_lang_Class_getComponentType(const u4* args,
    152     JValue* pResult)
    153 {
    154     ClassObject* thisPtr = (ClassObject*) args[0];
    155 
    156     if (!dvmIsArrayClass(thisPtr))
    157         RETURN_PTR(NULL);
    158 
    159     /*
    160      * We can't just return thisPtr->elementClass, because that gives
    161      * us the base type (e.g. X[][][] returns X).  If this is a multi-
    162      * dimensional array, we have to do the lookup by name.
    163      */
    164     if (thisPtr->descriptor[1] == '[')
    165         RETURN_PTR(dvmFindArrayClass(&thisPtr->descriptor[1],
    166                    thisPtr->classLoader));
    167     else
    168         RETURN_PTR(thisPtr->elementClass);
    169 }
    170 
    171 /*
    172  * private static Class<?>[] getDeclaredClasses(Class<?> clazz,
    173  *     boolean publicOnly)
    174  *
    175  * Return an array with the classes that are declared by the specified class.
    176  * If "publicOnly" is set, we strip out any classes that don't have "public"
    177  * access.
    178  */
    179 static void Dalvik_java_lang_Class_getDeclaredClasses(const u4* args,
    180     JValue* pResult)
    181 {
    182     ClassObject* clazz = (ClassObject*) args[0];
    183     bool publicOnly = (args[1] != 0);
    184     ArrayObject* classes;
    185 
    186     classes = dvmGetDeclaredClasses(clazz);
    187     if (classes == NULL) {
    188         if (!dvmCheckException(dvmThreadSelf())) {
    189             /* empty list, so create a zero-length array */
    190             classes = dvmAllocArrayByClass(gDvm.classJavaLangClassArray,
    191                         0, ALLOC_DEFAULT);
    192         }
    193     } else if (publicOnly) {
    194         u4 count, newIdx, publicCount = 0;
    195         ClassObject** pSource = (ClassObject**) classes->contents;
    196         u4 length = classes->length;
    197 
    198         /* count up public classes */
    199         for (count = 0; count < length; count++) {
    200             if (dvmIsPublicClass(pSource[count]))
    201                 publicCount++;
    202         }
    203 
    204         /* create a new array to hold them */
    205         ArrayObject* newClasses;
    206         newClasses = dvmAllocArrayByClass(gDvm.classJavaLangClassArray,
    207                         publicCount, ALLOC_DEFAULT);
    208 
    209         /* copy them over */
    210         for (count = newIdx = 0; count < length; count++) {
    211             if (dvmIsPublicClass(pSource[count])) {
    212                 dvmSetObjectArrayElement(newClasses, newIdx,
    213                                          (Object *)pSource[count]);
    214                 newIdx++;
    215             }
    216         }
    217         assert(newIdx == publicCount);
    218         dvmReleaseTrackedAlloc((Object*) classes, NULL);
    219         classes = newClasses;
    220     }
    221 
    222     dvmReleaseTrackedAlloc((Object*) classes, NULL);
    223     RETURN_PTR(classes);
    224 }
    225 
    226 /*
    227  * static Constructor[] getDeclaredConstructors(Class clazz, boolean publicOnly)
    228  *     throws SecurityException
    229  */
    230 static void Dalvik_java_lang_Class_getDeclaredConstructors(const u4* args,
    231     JValue* pResult)
    232 {
    233     ClassObject* clazz = (ClassObject*) args[0];
    234     bool publicOnly = (args[1] != 0);
    235     ArrayObject* constructors;
    236 
    237     constructors = dvmGetDeclaredConstructors(clazz, publicOnly);
    238     dvmReleaseTrackedAlloc((Object*) constructors, NULL);
    239 
    240     RETURN_PTR(constructors);
    241 }
    242 
    243 /*
    244  * static Field[] getDeclaredFields(Class klass, boolean publicOnly)
    245  *     throws SecurityException
    246  */
    247 static void Dalvik_java_lang_Class_getDeclaredFields(const u4* args,
    248     JValue* pResult)
    249 {
    250     ClassObject* clazz = (ClassObject*) args[0];
    251     bool publicOnly = (args[1] != 0);
    252     ArrayObject* fields;
    253 
    254     fields = dvmGetDeclaredFields(clazz, publicOnly);
    255     dvmReleaseTrackedAlloc((Object*) fields, NULL);
    256 
    257     RETURN_PTR(fields);
    258 }
    259 
    260 /*
    261  * static Method[] getDeclaredMethods(Class clazz, boolean publicOnly)
    262  *     throws SecurityException
    263  */
    264 static void Dalvik_java_lang_Class_getDeclaredMethods(const u4* args,
    265     JValue* pResult)
    266 {
    267     ClassObject* clazz = (ClassObject*) args[0];
    268     bool publicOnly = (args[1] != 0);
    269     ArrayObject* methods;
    270 
    271     methods = dvmGetDeclaredMethods(clazz, publicOnly);
    272     dvmReleaseTrackedAlloc((Object*) methods, NULL);
    273 
    274     RETURN_PTR(methods);
    275 }
    276 
    277 /*
    278  * Class[] getInterfaces()
    279  */
    280 static void Dalvik_java_lang_Class_getInterfaces(const u4* args,
    281     JValue* pResult)
    282 {
    283     ClassObject* clazz = (ClassObject*) args[0];
    284     ArrayObject* interfaces;
    285 
    286     interfaces = dvmGetInterfaces(clazz);
    287     dvmReleaseTrackedAlloc((Object*) interfaces, NULL);
    288 
    289     RETURN_PTR(interfaces);
    290 }
    291 
    292 /*
    293  * private static int getModifiers(Class klass, boolean
    294  *     ignoreInnerClassesAttrib)
    295  *
    296  * Return the class' modifier flags.  If "ignoreInnerClassesAttrib" is false,
    297  * and this is an inner class, we return the access flags from the inner class
    298  * attribute.
    299  */
    300 static void Dalvik_java_lang_Class_getModifiers(const u4* args, JValue* pResult)
    301 {
    302     ClassObject* clazz = (ClassObject*) args[0];
    303     bool ignoreInner = args[1];
    304     u4 accessFlags;
    305 
    306     accessFlags = clazz->accessFlags & JAVA_FLAGS_MASK;
    307 
    308     if (!ignoreInner) {
    309         /* see if we have an InnerClass annotation with flags in it */
    310         StringObject* className = NULL;
    311         int innerFlags;
    312 
    313         if (dvmGetInnerClass(clazz, &className, &innerFlags))
    314             accessFlags = innerFlags & JAVA_FLAGS_MASK;
    315 
    316         dvmReleaseTrackedAlloc((Object*) className, NULL);
    317     }
    318 
    319     RETURN_INT(accessFlags);
    320 }
    321 
    322 /*
    323  * private native String getNameNative()
    324  *
    325  * Return the class' name.
    326  */
    327 static void Dalvik_java_lang_Class_getNameNative(const u4* args, JValue* pResult)
    328 {
    329     ClassObject* clazz = (ClassObject*) args[0];
    330     const char* descriptor = clazz->descriptor;
    331     StringObject* nameObj;
    332 
    333     if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
    334         /*
    335          * The descriptor indicates that this is the class for
    336          * a primitive type; special-case the return value.
    337          */
    338         const char* name;
    339         switch (descriptor[0]) {
    340             case 'Z': name = "boolean"; break;
    341             case 'B': name = "byte";    break;
    342             case 'C': name = "char";    break;
    343             case 'S': name = "short";   break;
    344             case 'I': name = "int";     break;
    345             case 'J': name = "long";    break;
    346             case 'F': name = "float";   break;
    347             case 'D': name = "double";  break;
    348             case 'V': name = "void";    break;
    349             default: {
    350                 LOGE("Unknown primitive type '%c'\n", descriptor[0]);
    351                 assert(false);
    352                 RETURN_PTR(NULL);
    353             }
    354         }
    355 
    356         nameObj = dvmCreateStringFromCstr(name);
    357     } else {
    358         /*
    359          * Convert the UTF-8 name to a java.lang.String. The
    360          * name must use '.' to separate package components.
    361          *
    362          * TODO: this could be more efficient. Consider a custom
    363          * conversion function here that walks the string once and
    364          * avoids the allocation for the common case (name less than,
    365          * say, 128 bytes).
    366          */
    367         char* dotName = dvmDescriptorToDot(clazz->descriptor);
    368         nameObj = dvmCreateStringFromCstr(dotName);
    369         free(dotName);
    370     }
    371 
    372     dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
    373 
    374 #if 0
    375     /* doesn't work -- need "java.lang.String" not "java/lang/String" */
    376     {
    377         /*
    378          * Find the string in the DEX file and use the copy in the intern
    379          * table if it already exists (else put one there).  Only works
    380          * for strings in the DEX file, e.g. not arrays.
    381          *
    382          * We have to do the class lookup by name in the DEX file because
    383          * we don't have a DexClassDef pointer in the ClassObject, and it's
    384          * not worth adding one there just for this.  Should be cheaper
    385          * to do this than the string-creation above.
    386          */
    387         const DexFile* pDexFile = clazz->pDexFile;
    388         const DexClassDef* pClassDef;
    389         const DexClassId* pClassId;
    390 
    391         pDexFile = clazz->pDexFile;
    392         pClassDef = dvmDexFindClass(pDexFile, clazz->descriptor);
    393         pClassId = dvmDexGetClassId(pDexFile, pClassDef->classIdx);
    394         nameObj = dvmDexGetResolvedString(pDexFile, pClassId->nameIdx);
    395         if (nameObj == NULL) {
    396             nameObj = dvmResolveString(clazz, pClassId->nameIdx);
    397             if (nameObj == NULL)
    398                 LOGW("WARNING: couldn't find string %u for '%s'\n",
    399                     pClassId->nameIdx, clazz->name);
    400         }
    401     }
    402 #endif
    403 
    404     RETURN_PTR(nameObj);
    405 }
    406 
    407 /*
    408  * Return the superclass for instances of this class.
    409  *
    410  * If the class represents a java/lang/Object, an interface, a primitive
    411  * type, or void (which *is* a primitive type??), return NULL.
    412  *
    413  * For an array, return the java/lang/Object ClassObject.
    414  */
    415 static void Dalvik_java_lang_Class_getSuperclass(const u4* args,
    416     JValue* pResult)
    417 {
    418     ClassObject* clazz = (ClassObject*) args[0];
    419 
    420     if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz))
    421         RETURN_PTR(NULL);
    422     else
    423         RETURN_PTR(clazz->super);
    424 }
    425 
    426 /*
    427  * public boolean isAssignableFrom(Class<?> cls)
    428  *
    429  * Determine if this class is either the same as, or is a superclass or
    430  * superinterface of, the class specified in the "cls" parameter.
    431  */
    432 static void Dalvik_java_lang_Class_isAssignableFrom(const u4* args,
    433     JValue* pResult)
    434 {
    435     ClassObject* thisPtr = (ClassObject*) args[0];
    436     ClassObject* testClass = (ClassObject*) args[1];
    437 
    438     if (testClass == NULL) {
    439         dvmThrowException("Ljava/lang/NullPointerException;", NULL);
    440         RETURN_INT(false);
    441     }
    442     RETURN_INT(dvmInstanceof(testClass, thisPtr));
    443 }
    444 
    445 /*
    446  * public boolean isInstance(Object o)
    447  *
    448  * Dynamic equivalent of Java programming language "instanceof".
    449  */
    450 static void Dalvik_java_lang_Class_isInstance(const u4* args,
    451     JValue* pResult)
    452 {
    453     ClassObject* thisPtr = (ClassObject*) args[0];
    454     Object* testObj = (Object*) args[1];
    455 
    456     if (testObj == NULL)
    457         RETURN_INT(false);
    458     RETURN_INT(dvmInstanceof(testObj->clazz, thisPtr));
    459 }
    460 
    461 /*
    462  * public boolean isInterface()
    463  */
    464 static void Dalvik_java_lang_Class_isInterface(const u4* args,
    465     JValue* pResult)
    466 {
    467     ClassObject* thisPtr = (ClassObject*) args[0];
    468 
    469     RETURN_INT(dvmIsInterfaceClass(thisPtr));
    470 }
    471 
    472 /*
    473  * public boolean isPrimitive()
    474  */
    475 static void Dalvik_java_lang_Class_isPrimitive(const u4* args,
    476     JValue* pResult)
    477 {
    478     ClassObject* thisPtr = (ClassObject*) args[0];
    479 
    480     RETURN_INT(dvmIsPrimitiveClass(thisPtr));
    481 }
    482 
    483 /*
    484  * public T newInstance() throws InstantiationException, IllegalAccessException
    485  *
    486  * Create a new instance of this class.
    487  */
    488 static void Dalvik_java_lang_Class_newInstance(const u4* args, JValue* pResult)
    489 {
    490     Thread* self = dvmThreadSelf();
    491     ClassObject* clazz = (ClassObject*) args[0];
    492     Method* init;
    493     Object* newObj;
    494 
    495     /* can't instantiate these */
    496     if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz)
    497         || dvmIsArrayClass(clazz) || dvmIsAbstractClass(clazz))
    498     {
    499         LOGD("newInstance failed: p%d i%d [%d a%d\n",
    500             dvmIsPrimitiveClass(clazz), dvmIsInterfaceClass(clazz),
    501             dvmIsArrayClass(clazz), dvmIsAbstractClass(clazz));
    502         dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;",
    503             clazz->descriptor);
    504         RETURN_VOID();
    505     }
    506 
    507     /* initialize the class if it hasn't been already */
    508     if (!dvmIsClassInitialized(clazz)) {
    509         if (!dvmInitClass(clazz)) {
    510             LOGW("Class init failed in newInstance call (%s)\n",
    511                 clazz->descriptor);
    512             assert(dvmCheckException(self));
    513             RETURN_VOID();
    514         }
    515     }
    516 
    517     /* find the "nullary" constructor */
    518     init = dvmFindDirectMethodByDescriptor(clazz, "<init>", "()V");
    519     if (init == NULL) {
    520         /* common cause: secret "this" arg on non-static inner class ctor */
    521         LOGD("newInstance failed: no <init>()\n");
    522         dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;",
    523             clazz->descriptor);
    524         RETURN_VOID();
    525     }
    526 
    527     /*
    528      * Verify access from the call site.
    529      *
    530      * First, make sure the method invoking Class.newInstance() has permission
    531      * to access the class.
    532      *
    533      * Second, make sure it has permission to invoke the constructor.  The
    534      * constructor must be public or, if the caller is in the same package,
    535      * have package scope.
    536      */
    537     ClassObject* callerClass = dvmGetCaller2Class(self->curFrame);
    538 
    539     if (!dvmCheckClassAccess(callerClass, clazz)) {
    540         LOGD("newInstance failed: %s not accessible to %s\n",
    541             clazz->descriptor, callerClass->descriptor);
    542         dvmThrowException("Ljava/lang/IllegalAccessException;",
    543             "access to class not allowed");
    544         RETURN_VOID();
    545     }
    546     if (!dvmCheckMethodAccess(callerClass, init)) {
    547         LOGD("newInstance failed: %s.<init>() not accessible to %s\n",
    548             clazz->descriptor, callerClass->descriptor);
    549         dvmThrowException("Ljava/lang/IllegalAccessException;",
    550             "access to constructor not allowed");
    551         RETURN_VOID();
    552     }
    553 
    554     newObj = dvmAllocObject(clazz, ALLOC_DEFAULT);
    555     JValue unused;
    556 
    557     /* invoke constructor; unlike reflection calls, we don't wrap exceptions */
    558     dvmCallMethod(self, init, newObj, &unused);
    559     dvmReleaseTrackedAlloc(newObj, NULL);
    560 
    561     RETURN_PTR(newObj);
    562 }
    563 
    564 /*
    565  * private Object[] getSignatureAnnotation()
    566  *
    567  * Returns the signature annotation array.
    568  */
    569 static void Dalvik_java_lang_Class_getSignatureAnnotation(const u4* args,
    570     JValue* pResult)
    571 {
    572     ClassObject* clazz = (ClassObject*) args[0];
    573     ArrayObject* arr = dvmGetClassSignatureAnnotation(clazz);
    574 
    575     dvmReleaseTrackedAlloc((Object*) arr, NULL);
    576     RETURN_PTR(arr);
    577 }
    578 
    579 /*
    580  * public Class getDeclaringClass()
    581  *
    582  * Get the class that encloses this class (if any).
    583  */
    584 static void Dalvik_java_lang_Class_getDeclaringClass(const u4* args,
    585     JValue* pResult)
    586 {
    587     ClassObject* clazz = (ClassObject*) args[0];
    588 
    589     ClassObject* enclosing = dvmGetDeclaringClass(clazz);
    590     dvmReleaseTrackedAlloc((Object*) enclosing, NULL);
    591     RETURN_PTR(enclosing);
    592 }
    593 
    594 /*
    595  * public Class getEnclosingClass()
    596  *
    597  * Get the class that encloses this class (if any).
    598  */
    599 static void Dalvik_java_lang_Class_getEnclosingClass(const u4* args,
    600     JValue* pResult)
    601 {
    602     ClassObject* clazz = (ClassObject*) args[0];
    603 
    604     ClassObject* enclosing = dvmGetEnclosingClass(clazz);
    605     dvmReleaseTrackedAlloc((Object*) enclosing, NULL);
    606     RETURN_PTR(enclosing);
    607 }
    608 
    609 /*
    610  * public Constructor getEnclosingConstructor()
    611  *
    612  * Get the constructor that encloses this class (if any).
    613  */
    614 static void Dalvik_java_lang_Class_getEnclosingConstructor(const u4* args,
    615     JValue* pResult)
    616 {
    617     ClassObject* clazz = (ClassObject*) args[0];
    618 
    619     Object* enclosing = dvmGetEnclosingMethod(clazz);
    620     if (enclosing != NULL) {
    621         dvmReleaseTrackedAlloc(enclosing, NULL);
    622         if (enclosing->clazz == gDvm.classJavaLangReflectConstructor) {
    623             RETURN_PTR(enclosing);
    624         }
    625         assert(enclosing->clazz == gDvm.classJavaLangReflectMethod);
    626     }
    627     RETURN_PTR(NULL);
    628 }
    629 
    630 /*
    631  * public Method getEnclosingMethod()
    632  *
    633  * Get the method that encloses this class (if any).
    634  */
    635 static void Dalvik_java_lang_Class_getEnclosingMethod(const u4* args,
    636     JValue* pResult)
    637 {
    638     ClassObject* clazz = (ClassObject*) args[0];
    639 
    640     Object* enclosing = dvmGetEnclosingMethod(clazz);
    641     if (enclosing != NULL) {
    642         dvmReleaseTrackedAlloc(enclosing, NULL);
    643         if (enclosing->clazz == gDvm.classJavaLangReflectMethod) {
    644             RETURN_PTR(enclosing);
    645         }
    646         assert(enclosing->clazz == gDvm.classJavaLangReflectConstructor);
    647     }
    648     RETURN_PTR(NULL);
    649 }
    650 
    651 #if 0
    652 static void Dalvik_java_lang_Class_getGenericInterfaces(const u4* args,
    653     JValue* pResult)
    654 {
    655     dvmThrowException("Ljava/lang/UnsupportedOperationException;",
    656         "native method not implemented");
    657 
    658     RETURN_PTR(NULL);
    659 }
    660 
    661 static void Dalvik_java_lang_Class_getGenericSuperclass(const u4* args,
    662     JValue* pResult)
    663 {
    664     dvmThrowException("Ljava/lang/UnsupportedOperationException;",
    665         "native method not implemented");
    666 
    667     RETURN_PTR(NULL);
    668 }
    669 
    670 static void Dalvik_java_lang_Class_getTypeParameters(const u4* args,
    671     JValue* pResult)
    672 {
    673     dvmThrowException("Ljava/lang/UnsupportedOperationException;",
    674         "native method not implemented");
    675 
    676     RETURN_PTR(NULL);
    677 }
    678 #endif
    679 
    680 /*
    681  * public boolean isAnonymousClass()
    682  *
    683  * Returns true if this is an "anonymous" class.
    684  */
    685 static void Dalvik_java_lang_Class_isAnonymousClass(const u4* args,
    686     JValue* pResult)
    687 {
    688     ClassObject* clazz = (ClassObject*) args[0];
    689     StringObject* className = NULL;
    690     int accessFlags;
    691 
    692     /*
    693      * If this has an InnerClass annotation, pull it out.  Lack of the
    694      * annotation, or an annotation with a NULL class name, indicates
    695      * that this is an anonymous inner class.
    696      */
    697     if (!dvmGetInnerClass(clazz, &className, &accessFlags))
    698         RETURN_BOOLEAN(false);
    699 
    700     dvmReleaseTrackedAlloc((Object*) className, NULL);
    701     RETURN_BOOLEAN(className == NULL);
    702 }
    703 
    704 /*
    705  * private Annotation[] getDeclaredAnnotations()
    706  *
    707  * Return the annotations declared on this class.
    708  */
    709 static void Dalvik_java_lang_Class_getDeclaredAnnotations(const u4* args,
    710     JValue* pResult)
    711 {
    712     ClassObject* clazz = (ClassObject*) args[0];
    713 
    714     ArrayObject* annos = dvmGetClassAnnotations(clazz);
    715     dvmReleaseTrackedAlloc((Object*) annos, NULL);
    716     RETURN_PTR(annos);
    717 }
    718 
    719 /*
    720  * public String getInnerClassName()
    721  *
    722  * Returns the simple name of a member class or local class, or null otherwise.
    723  */
    724 static void Dalvik_java_lang_Class_getInnerClassName(const u4* args,
    725     JValue* pResult)
    726 {
    727     ClassObject* clazz = (ClassObject*) args[0];
    728     StringObject* nameObj;
    729     int flags;
    730 
    731     if (dvmGetInnerClass(clazz, &nameObj, &flags)) {
    732         dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
    733         RETURN_PTR(nameObj);
    734     } else {
    735         RETURN_PTR(NULL);
    736     }
    737 }
    738 
    739 /*
    740  * static native void setAccessibleNoCheck(AccessibleObject ao, boolean flag);
    741  */
    742 static void Dalvik_java_lang_Class_setAccessibleNoCheck(const u4* args,
    743     JValue* pResult)
    744 {
    745     Object* target = (Object*) args[0];
    746     u4 flag = (u4) args[1];
    747 
    748     dvmSetFieldBoolean(target, gDvm.offJavaLangReflectAccessibleObject_flag,
    749             flag);
    750 }
    751 
    752 const DalvikNativeMethod dvm_java_lang_Class[] = {
    753     { "desiredAssertionStatus", "()Z",
    754         Dalvik_java_lang_Class_desiredAssertionStatus },
    755     { "classForName",           "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;",
    756         Dalvik_java_lang_Class_classForName },
    757     { "getClassLoader",         "(Ljava/lang/Class;)Ljava/lang/ClassLoader;",
    758         Dalvik_java_lang_Class_getClassLoader },
    759     { "getComponentType",       "()Ljava/lang/Class;",
    760         Dalvik_java_lang_Class_getComponentType },
    761     { "getSignatureAnnotation",  "()[Ljava/lang/Object;",
    762         Dalvik_java_lang_Class_getSignatureAnnotation },
    763     { "getDeclaredClasses",     "(Ljava/lang/Class;Z)[Ljava/lang/Class;",
    764         Dalvik_java_lang_Class_getDeclaredClasses },
    765     { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;",
    766         Dalvik_java_lang_Class_getDeclaredConstructors },
    767     { "getDeclaredFields",      "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;",
    768         Dalvik_java_lang_Class_getDeclaredFields },
    769     { "getDeclaredMethods",     "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;",
    770         Dalvik_java_lang_Class_getDeclaredMethods },
    771     { "getInterfaces",          "()[Ljava/lang/Class;",
    772         Dalvik_java_lang_Class_getInterfaces },
    773     { "getModifiers",           "(Ljava/lang/Class;Z)I",
    774         Dalvik_java_lang_Class_getModifiers },
    775     { "getNameNative",                "()Ljava/lang/String;",
    776         Dalvik_java_lang_Class_getNameNative },
    777     { "getSuperclass",          "()Ljava/lang/Class;",
    778         Dalvik_java_lang_Class_getSuperclass },
    779     { "isAssignableFrom",       "(Ljava/lang/Class;)Z",
    780         Dalvik_java_lang_Class_isAssignableFrom },
    781     { "isInstance",             "(Ljava/lang/Object;)Z",
    782         Dalvik_java_lang_Class_isInstance },
    783     { "isInterface",            "()Z",
    784         Dalvik_java_lang_Class_isInterface },
    785     { "isPrimitive",            "()Z",
    786         Dalvik_java_lang_Class_isPrimitive },
    787     { "newInstanceImpl",        "()Ljava/lang/Object;",
    788         Dalvik_java_lang_Class_newInstance },
    789     { "getDeclaringClass",      "()Ljava/lang/Class;",
    790         Dalvik_java_lang_Class_getDeclaringClass },
    791     { "getEnclosingClass",      "()Ljava/lang/Class;",
    792         Dalvik_java_lang_Class_getEnclosingClass },
    793     { "getEnclosingConstructor", "()Ljava/lang/reflect/Constructor;",
    794         Dalvik_java_lang_Class_getEnclosingConstructor },
    795     { "getEnclosingMethod",     "()Ljava/lang/reflect/Method;",
    796         Dalvik_java_lang_Class_getEnclosingMethod },
    797 #if 0
    798     { "getGenericInterfaces",   "()[Ljava/lang/reflect/Type;",
    799         Dalvik_java_lang_Class_getGenericInterfaces },
    800     { "getGenericSuperclass",   "()Ljava/lang/reflect/Type;",
    801         Dalvik_java_lang_Class_getGenericSuperclass },
    802     { "getTypeParameters",      "()Ljava/lang/reflect/TypeVariable;",
    803         Dalvik_java_lang_Class_getTypeParameters },
    804 #endif
    805     { "isAnonymousClass",       "()Z",
    806         Dalvik_java_lang_Class_isAnonymousClass },
    807     { "getDeclaredAnnotations", "()[Ljava/lang/annotation/Annotation;",
    808         Dalvik_java_lang_Class_getDeclaredAnnotations },
    809     { "getInnerClassName",       "()Ljava/lang/String;",
    810         Dalvik_java_lang_Class_getInnerClassName },
    811     { "setAccessibleNoCheck",   "(Ljava/lang/reflect/AccessibleObject;Z)V",
    812         Dalvik_java_lang_Class_setAccessibleNoCheck },
    813     { NULL, NULL, NULL },
    814 };
    815