• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
Dalvik_java_lang_Class_desiredAssertionStatus(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_classForName(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getClassLoader(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getComponentType(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getDeclaredClasses(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getDeclaredConstructors(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getDeclaredFields(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getDeclaredMethods(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getInterfaces(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getModifiers(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getNameNative(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getSuperclass(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_isAssignableFrom(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_isInstance(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_isInterface(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_isPrimitive(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_newInstance(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getSignatureAnnotation(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getDeclaringClass(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getEnclosingClass(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getEnclosingConstructor(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getEnclosingMethod(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_isAnonymousClass(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getDeclaredAnnotations(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_getInnerClassName(const u4 * args,JValue * pResult)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  */
Dalvik_java_lang_Class_setAccessibleNoCheck(const u4 * args,JValue * pResult)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