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 #include "ScopedPthreadMutexLock.h"
     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                 ALOGV("ASRT: pkg no match: '%s'(%d) vs '%s'",
     73                     className, pkgLen, pCtrl->pkgOrClass);
     74             } else {
     75                 ALOGV("ASRT: pkg match: '%s'(%d) vs '%s' --> %d",
     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                     ALOGV("ASRT: sys no match: '%s'", className);
     88                 } else {
     89                     ALOGV("ASRT: sys match: '%s' --> %d",
     90                         className, pCtrl->enable);
     91                     enable = pCtrl->enable;
     92                 }
     93             } else if (*pCtrl->pkgOrClass == '\0') {
     94                 ALOGV("ASRT: class all: '%s' --> %d",
     95                     className, pCtrl->enable);
     96                 enable = pCtrl->enable;
     97             } else {
     98                 if (strcmp(pCtrl->pkgOrClass, className) != 0) {
     99                     ALOGV("ASRT: cls no match: '%s' vs '%s'",
    100                         className, pCtrl->pkgOrClass);
    101                 } else {
    102                     ALOGV("ASRT: cls match: '%s' vs '%s' --> %d",
    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**)(void*)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  */
    246 static void Dalvik_java_lang_Class_getDeclaredFields(const u4* args,
    247     JValue* pResult)
    248 {
    249     ClassObject* clazz = (ClassObject*) args[0];
    250     bool publicOnly = (args[1] != 0);
    251     ArrayObject* fields;
    252 
    253     fields = dvmGetDeclaredFields(clazz, publicOnly);
    254     dvmReleaseTrackedAlloc((Object*) fields, NULL);
    255 
    256     RETURN_PTR(fields);
    257 }
    258 
    259 /*
    260  * static Field getDeclaredField(Class klass, String name)
    261  */
    262 static void Dalvik_java_lang_Class_getDeclaredField(const u4* args,
    263     JValue* pResult)
    264 {
    265     ClassObject* clazz = (ClassObject*) args[0];
    266     StringObject* nameObj = (StringObject*) args[1];
    267     Object* fieldObj = dvmGetDeclaredField(clazz, nameObj);
    268     dvmReleaseTrackedAlloc((Object*) fieldObj, NULL);
    269     RETURN_PTR(fieldObj);
    270 }
    271 
    272 /*
    273  * static Method[] getDeclaredMethods(Class clazz, boolean publicOnly)
    274  *     throws SecurityException
    275  */
    276 static void Dalvik_java_lang_Class_getDeclaredMethods(const u4* args,
    277     JValue* pResult)
    278 {
    279     ClassObject* clazz = (ClassObject*) args[0];
    280     bool publicOnly = (args[1] != 0);
    281     ArrayObject* methods;
    282 
    283     methods = dvmGetDeclaredMethods(clazz, publicOnly);
    284     dvmReleaseTrackedAlloc((Object*) methods, NULL);
    285 
    286     RETURN_PTR(methods);
    287 }
    288 
    289 /*
    290  * static native Member getDeclaredConstructorOrMethod(
    291  *     Class clazz, String name, Class[] args);
    292  */
    293 static void Dalvik_java_lang_Class_getDeclaredConstructorOrMethod(
    294     const u4* args, JValue* pResult)
    295 {
    296     ClassObject* clazz = (ClassObject*) args[0];
    297     StringObject* nameObj = (StringObject*) args[1];
    298     ArrayObject* methodArgs = (ArrayObject*) args[2];
    299 
    300     Object* methodObj;
    301 
    302     methodObj = dvmGetDeclaredConstructorOrMethod(clazz, nameObj, methodArgs);
    303     dvmReleaseTrackedAlloc(methodObj, NULL);
    304 
    305     RETURN_PTR(methodObj);
    306 }
    307 
    308 /*
    309  * Class[] getInterfaces()
    310  */
    311 static void Dalvik_java_lang_Class_getInterfaces(const u4* args,
    312     JValue* pResult)
    313 {
    314     ClassObject* clazz = (ClassObject*) args[0];
    315     ArrayObject* interfaces;
    316 
    317     interfaces = dvmGetInterfaces(clazz);
    318     dvmReleaseTrackedAlloc((Object*) interfaces, NULL);
    319 
    320     RETURN_PTR(interfaces);
    321 }
    322 
    323 /*
    324  * private static int getModifiers(Class klass, boolean
    325  *     ignoreInnerClassesAttrib)
    326  *
    327  * Return the class' modifier flags.  If "ignoreInnerClassesAttrib" is false,
    328  * and this is an inner class, we return the access flags from the inner class
    329  * attribute.
    330  */
    331 static void Dalvik_java_lang_Class_getModifiers(const u4* args, JValue* pResult)
    332 {
    333     ClassObject* clazz = (ClassObject*) args[0];
    334     bool ignoreInner = args[1];
    335     u4 accessFlags;
    336 
    337     accessFlags = clazz->accessFlags & JAVA_FLAGS_MASK;
    338 
    339     if (!ignoreInner) {
    340         /* see if we have an InnerClass annotation with flags in it */
    341         StringObject* className = NULL;
    342         int innerFlags;
    343 
    344         if (dvmGetInnerClass(clazz, &className, &innerFlags))
    345             accessFlags = innerFlags & JAVA_FLAGS_MASK;
    346 
    347         dvmReleaseTrackedAlloc((Object*) className, NULL);
    348     }
    349 
    350     RETURN_INT(accessFlags);
    351 }
    352 
    353 /*
    354  * private native String getNameNative()
    355  *
    356  * Return the class' name. The exact format is bizarre, but it's the specified
    357  * behavior: keywords for primitive types, regular "[I" form for primitive
    358  * arrays (so "int" but "[I"), and arrays of reference types written
    359  * between "L" and ";" but with dots rather than slashes (so "java.lang.String"
    360  * but "[Ljava.lang.String;"). Madness.
    361  */
    362 static void Dalvik_java_lang_Class_getNameNative(const u4* args, JValue* pResult)
    363 {
    364     ClassObject* clazz = (ClassObject*) args[0];
    365     const char* descriptor = clazz->descriptor;
    366     StringObject* nameObj;
    367 
    368     if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
    369         /*
    370          * The descriptor indicates that this is the class for
    371          * a primitive type; special-case the return value.
    372          */
    373         const char* name;
    374         switch (descriptor[0]) {
    375             case 'Z': name = "boolean"; break;
    376             case 'B': name = "byte";    break;
    377             case 'C': name = "char";    break;
    378             case 'S': name = "short";   break;
    379             case 'I': name = "int";     break;
    380             case 'J': name = "long";    break;
    381             case 'F': name = "float";   break;
    382             case 'D': name = "double";  break;
    383             case 'V': name = "void";    break;
    384             default: {
    385                 ALOGE("Unknown primitive type '%c'", descriptor[0]);
    386                 assert(false);
    387                 RETURN_PTR(NULL);
    388             }
    389         }
    390 
    391         nameObj = dvmCreateStringFromCstr(name);
    392     } else {
    393         /*
    394          * Convert the UTF-8 name to a java.lang.String. The
    395          * name must use '.' to separate package components.
    396          *
    397          * TODO: this could be more efficient. Consider a custom
    398          * conversion function here that walks the string once and
    399          * avoids the allocation for the common case (name less than,
    400          * say, 128 bytes).
    401          */
    402         char* dotName = dvmDescriptorToDot(clazz->descriptor);
    403         nameObj = dvmCreateStringFromCstr(dotName);
    404         free(dotName);
    405     }
    406 
    407     dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
    408     RETURN_PTR(nameObj);
    409 }
    410 
    411 /*
    412  * Return the superclass for instances of this class.
    413  *
    414  * If the class represents a java/lang/Object, an interface, a primitive
    415  * type, or void (which *is* a primitive type??), return NULL.
    416  *
    417  * For an array, return the java/lang/Object ClassObject.
    418  */
    419 static void Dalvik_java_lang_Class_getSuperclass(const u4* args,
    420     JValue* pResult)
    421 {
    422     ClassObject* clazz = (ClassObject*) args[0];
    423 
    424     if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz))
    425         RETURN_PTR(NULL);
    426     else
    427         RETURN_PTR(clazz->super);
    428 }
    429 
    430 /*
    431  * public boolean isAssignableFrom(Class<?> cls)
    432  *
    433  * Determine if this class is either the same as, or is a superclass or
    434  * superinterface of, the class specified in the "cls" parameter.
    435  */
    436 static void Dalvik_java_lang_Class_isAssignableFrom(const u4* args,
    437     JValue* pResult)
    438 {
    439     ClassObject* thisPtr = (ClassObject*) args[0];
    440     ClassObject* testClass = (ClassObject*) args[1];
    441 
    442     if (testClass == NULL) {
    443         dvmThrowNullPointerException("cls == null");
    444         RETURN_INT(false);
    445     }
    446     RETURN_INT(dvmInstanceof(testClass, thisPtr));
    447 }
    448 
    449 /*
    450  * public boolean isInstance(Object o)
    451  *
    452  * Dynamic equivalent of Java programming language "instanceof".
    453  */
    454 static void Dalvik_java_lang_Class_isInstance(const u4* args,
    455     JValue* pResult)
    456 {
    457     ClassObject* thisPtr = (ClassObject*) args[0];
    458     Object* testObj = (Object*) args[1];
    459 
    460     if (testObj == NULL)
    461         RETURN_INT(false);
    462     RETURN_INT(dvmInstanceof(testObj->clazz, thisPtr));
    463 }
    464 
    465 /*
    466  * public boolean isInterface()
    467  */
    468 static void Dalvik_java_lang_Class_isInterface(const u4* args,
    469     JValue* pResult)
    470 {
    471     ClassObject* thisPtr = (ClassObject*) args[0];
    472 
    473     RETURN_INT(dvmIsInterfaceClass(thisPtr));
    474 }
    475 
    476 /*
    477  * public boolean isPrimitive()
    478  */
    479 static void Dalvik_java_lang_Class_isPrimitive(const u4* args,
    480     JValue* pResult)
    481 {
    482     ClassObject* thisPtr = (ClassObject*) args[0];
    483 
    484     RETURN_INT(dvmIsPrimitiveClass(thisPtr));
    485 }
    486 
    487 /*
    488  * public T newInstance() throws InstantiationException, IllegalAccessException
    489  *
    490  * Create a new instance of this class.
    491  */
    492 static void Dalvik_java_lang_Class_newInstance(const u4* args, JValue* pResult)
    493 {
    494     Thread* self = dvmThreadSelf();
    495     ClassObject* clazz = (ClassObject*) args[0];
    496     Method* init;
    497     Object* newObj;
    498 
    499     /* can't instantiate these */
    500     if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz)
    501         || dvmIsArrayClass(clazz) || dvmIsAbstractClass(clazz))
    502     {
    503         ALOGD("newInstance failed: p%d i%d [%d a%d",
    504             dvmIsPrimitiveClass(clazz), dvmIsInterfaceClass(clazz),
    505             dvmIsArrayClass(clazz), dvmIsAbstractClass(clazz));
    506         dvmThrowInstantiationException(clazz, NULL);
    507         RETURN_VOID();
    508     }
    509 
    510     /* initialize the class if it hasn't been already */
    511     if (!dvmIsClassInitialized(clazz)) {
    512         if (!dvmInitClass(clazz)) {
    513             ALOGW("Class init failed in newInstance call (%s)",
    514                 clazz->descriptor);
    515             assert(dvmCheckException(self));
    516             RETURN_VOID();
    517         }
    518     }
    519 
    520     /* find the "nullary" constructor */
    521     init = dvmFindDirectMethodByDescriptor(clazz, "<init>", "()V");
    522     if (init == NULL) {
    523         /* common cause: secret "this" arg on non-static inner class ctor */
    524         ALOGD("newInstance failed: no <init>()");
    525         dvmThrowInstantiationException(clazz, "no empty constructor");
    526         RETURN_VOID();
    527     }
    528 
    529     /*
    530      * Verify access from the call site.
    531      *
    532      * First, make sure the method invoking Class.newInstance() has permission
    533      * to access the class.
    534      *
    535      * Second, make sure it has permission to invoke the constructor.  The
    536      * constructor must be public or, if the caller is in the same package,
    537      * have package scope.
    538      */
    539     ClassObject* callerClass = dvmGetCaller2Class(self->interpSave.curFrame);
    540 
    541     if (!dvmCheckClassAccess(callerClass, clazz)) {
    542         ALOGD("newInstance failed: %s not accessible to %s",
    543             clazz->descriptor, callerClass->descriptor);
    544         dvmThrowIllegalAccessException("access to class not allowed");
    545         RETURN_VOID();
    546     }
    547     if (!dvmCheckMethodAccess(callerClass, init)) {
    548         ALOGD("newInstance failed: %s.<init>() not accessible to %s",
    549             clazz->descriptor, callerClass->descriptor);
    550         dvmThrowIllegalAccessException("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     dvmThrowUnsupportedOperationException("native method not implemented");
    656 
    657     RETURN_PTR(NULL);
    658 }
    659 
    660 static void Dalvik_java_lang_Class_getGenericSuperclass(const u4* args,
    661     JValue* pResult)
    662 {
    663     dvmThrowUnsupportedOperationException("native method not implemented");
    664 
    665     RETURN_PTR(NULL);
    666 }
    667 
    668 static void Dalvik_java_lang_Class_getTypeParameters(const u4* args,
    669     JValue* pResult)
    670 {
    671     dvmThrowUnsupportedOperationException("native method not implemented");
    672 
    673     RETURN_PTR(NULL);
    674 }
    675 #endif
    676 
    677 /*
    678  * public boolean isAnonymousClass()
    679  *
    680  * Returns true if this is an "anonymous" class.
    681  */
    682 static void Dalvik_java_lang_Class_isAnonymousClass(const u4* args,
    683     JValue* pResult)
    684 {
    685     ClassObject* clazz = (ClassObject*) args[0];
    686     StringObject* className = NULL;
    687     int accessFlags;
    688 
    689     /*
    690      * If this has an InnerClass annotation, pull it out.  Lack of the
    691      * annotation, or an annotation with a NULL class name, indicates
    692      * that this is an anonymous inner class.
    693      */
    694     if (!dvmGetInnerClass(clazz, &className, &accessFlags))
    695         RETURN_BOOLEAN(false);
    696 
    697     dvmReleaseTrackedAlloc((Object*) className, NULL);
    698     RETURN_BOOLEAN(className == NULL);
    699 }
    700 
    701 /*
    702  * private Annotation[] getDeclaredAnnotations()
    703  *
    704  * Return the annotations declared on this class.
    705  */
    706 static void Dalvik_java_lang_Class_getDeclaredAnnotations(const u4* args,
    707     JValue* pResult)
    708 {
    709     ClassObject* clazz = (ClassObject*) args[0];
    710 
    711     ArrayObject* annos = dvmGetClassAnnotations(clazz);
    712     dvmReleaseTrackedAlloc((Object*) annos, NULL);
    713     RETURN_PTR(annos);
    714 }
    715 
    716 /*
    717  * private Annotation getDeclaredAnnotation(Class annotationClass)
    718  */
    719 static void Dalvik_java_lang_Class_getDeclaredAnnotation(const u4* args,
    720     JValue* pResult)
    721 {
    722     ClassObject* clazz = (ClassObject*) args[0];
    723     ClassObject* annotationClazz = (ClassObject*) args[1];
    724 
    725     RETURN_PTR(dvmGetClassAnnotation(clazz, annotationClazz));
    726 }
    727 
    728 /*
    729  * private boolean isDeclaredAnnotationPresent(Class annotationClass);
    730  */
    731 static void Dalvik_java_lang_Class_isDeclaredAnnotationPresent(const u4* args,
    732     JValue* pResult)
    733 {
    734     ClassObject* clazz = (ClassObject*) args[0];
    735     ClassObject* annotationClazz = (ClassObject*) args[1];
    736 
    737     RETURN_BOOLEAN(dvmIsClassAnnotationPresent(clazz, annotationClazz));
    738 }
    739 
    740 /*
    741  * public String getInnerClassName()
    742  *
    743  * Returns the simple name of a member class or local class, or null otherwise.
    744  */
    745 static void Dalvik_java_lang_Class_getInnerClassName(const u4* args,
    746     JValue* pResult)
    747 {
    748     ClassObject* clazz = (ClassObject*) args[0];
    749     StringObject* nameObj;
    750     int flags;
    751 
    752     if (dvmGetInnerClass(clazz, &nameObj, &flags)) {
    753         dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
    754         RETURN_PTR(nameObj);
    755     } else {
    756         RETURN_PTR(NULL);
    757     }
    758 }
    759 
    760 JNIEXPORT jobject JNICALL Java_java_lang_Class_getDex(JNIEnv* env, jclass javaClass) {
    761     Thread* self = dvmThreadSelf();
    762     ClassObject* c = (ClassObject*) dvmDecodeIndirectRef(self, javaClass);
    763 
    764     DvmDex* dvm_dex = c->pDvmDex;
    765     if (dvm_dex == NULL) {
    766         return NULL;
    767     }
    768     // Already cached?
    769     if (dvm_dex->dex_object != NULL) {
    770         return dvm_dex->dex_object;
    771     }
    772     jobject byte_buffer = env->NewDirectByteBuffer(dvm_dex->memMap.addr, dvm_dex->memMap.length);
    773     if (byte_buffer == NULL) {
    774         return NULL;
    775     }
    776 
    777     jclass com_android_dex_Dex = env->FindClass("com/android/dex/Dex");
    778     if (com_android_dex_Dex == NULL) {
    779         return NULL;
    780     }
    781 
    782     jmethodID com_android_dex_Dex_create =
    783             env->GetStaticMethodID(com_android_dex_Dex,
    784                                    "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
    785     if (com_android_dex_Dex_create == NULL) {
    786         return NULL;
    787     }
    788 
    789     jvalue args[1];
    790     args[0].l = byte_buffer;
    791     jobject local_ref = env->CallStaticObjectMethodA(com_android_dex_Dex,
    792                                                      com_android_dex_Dex_create,
    793                                                      args);
    794     if (local_ref == NULL) {
    795         return NULL;
    796     }
    797 
    798     // Check another thread didn't cache an object, if we've won install the object.
    799     ScopedPthreadMutexLock lock(&dvm_dex->modLock);
    800 
    801     if (dvm_dex->dex_object == NULL) {
    802         dvm_dex->dex_object = env->NewGlobalRef(local_ref);
    803     }
    804     return dvm_dex->dex_object;
    805 }
    806 
    807 const DalvikNativeMethod dvm_java_lang_Class[] = {
    808     { "desiredAssertionStatus", "()Z",
    809         Dalvik_java_lang_Class_desiredAssertionStatus },
    810     { "classForName",           "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;",
    811         Dalvik_java_lang_Class_classForName },
    812     { "getClassLoader",         "(Ljava/lang/Class;)Ljava/lang/ClassLoader;",
    813         Dalvik_java_lang_Class_getClassLoader },
    814     { "getComponentType",       "()Ljava/lang/Class;",
    815         Dalvik_java_lang_Class_getComponentType },
    816     { "getSignatureAnnotation",  "()[Ljava/lang/Object;",
    817         Dalvik_java_lang_Class_getSignatureAnnotation },
    818     { "getDeclaredClasses",     "(Ljava/lang/Class;Z)[Ljava/lang/Class;",
    819         Dalvik_java_lang_Class_getDeclaredClasses },
    820     { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;",
    821         Dalvik_java_lang_Class_getDeclaredConstructors },
    822     { "getDeclaredFields",      "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;",
    823         Dalvik_java_lang_Class_getDeclaredFields },
    824     { "getDeclaredMethods",     "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;",
    825         Dalvik_java_lang_Class_getDeclaredMethods },
    826     { "getDeclaredField",      "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;",
    827         Dalvik_java_lang_Class_getDeclaredField },
    828     { "getDeclaredConstructorOrMethod", "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;",
    829         Dalvik_java_lang_Class_getDeclaredConstructorOrMethod },
    830     { "getInterfaces",          "()[Ljava/lang/Class;",
    831         Dalvik_java_lang_Class_getInterfaces },
    832     { "getModifiers",           "(Ljava/lang/Class;Z)I",
    833         Dalvik_java_lang_Class_getModifiers },
    834     { "getNameNative",                "()Ljava/lang/String;",
    835         Dalvik_java_lang_Class_getNameNative },
    836     { "getSuperclass",          "()Ljava/lang/Class;",
    837         Dalvik_java_lang_Class_getSuperclass },
    838     { "isAssignableFrom",       "(Ljava/lang/Class;)Z",
    839         Dalvik_java_lang_Class_isAssignableFrom },
    840     { "isInstance",             "(Ljava/lang/Object;)Z",
    841         Dalvik_java_lang_Class_isInstance },
    842     { "isInterface",            "()Z",
    843         Dalvik_java_lang_Class_isInterface },
    844     { "isPrimitive",            "()Z",
    845         Dalvik_java_lang_Class_isPrimitive },
    846     { "newInstanceImpl",        "()Ljava/lang/Object;",
    847         Dalvik_java_lang_Class_newInstance },
    848     { "getDeclaringClass",      "()Ljava/lang/Class;",
    849         Dalvik_java_lang_Class_getDeclaringClass },
    850     { "getEnclosingClass",      "()Ljava/lang/Class;",
    851         Dalvik_java_lang_Class_getEnclosingClass },
    852     { "getEnclosingConstructor", "()Ljava/lang/reflect/Constructor;",
    853         Dalvik_java_lang_Class_getEnclosingConstructor },
    854     { "getEnclosingMethod",     "()Ljava/lang/reflect/Method;",
    855         Dalvik_java_lang_Class_getEnclosingMethod },
    856 #if 0
    857     { "getGenericInterfaces",   "()[Ljava/lang/reflect/Type;",
    858         Dalvik_java_lang_Class_getGenericInterfaces },
    859     { "getGenericSuperclass",   "()Ljava/lang/reflect/Type;",
    860         Dalvik_java_lang_Class_getGenericSuperclass },
    861     { "getTypeParameters",      "()Ljava/lang/reflect/TypeVariable;",
    862         Dalvik_java_lang_Class_getTypeParameters },
    863 #endif
    864     { "isAnonymousClass",       "()Z",
    865         Dalvik_java_lang_Class_isAnonymousClass },
    866     { "getDeclaredAnnotations", "()[Ljava/lang/annotation/Annotation;",
    867         Dalvik_java_lang_Class_getDeclaredAnnotations },
    868     { "getDeclaredAnnotation", "(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;",
    869         Dalvik_java_lang_Class_getDeclaredAnnotation },
    870     { "isDeclaredAnnotationPresent", "(Ljava/lang/Class;)Z",
    871         Dalvik_java_lang_Class_isDeclaredAnnotationPresent },
    872     { "getInnerClassName",       "()Ljava/lang/String;",
    873         Dalvik_java_lang_Class_getInnerClassName },
    874     { NULL, NULL, NULL },
    875 };
    876