• 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         int i, newIdx, publicCount = 0;
195         ClassObject** pSource = (ClassObject**) classes->contents;
196 
197         /* count up public classes */
198         for (i = 0; i < (int)classes->length; i++) {
199             if (dvmIsPublicClass(pSource[i]))
200                 publicCount++;
201         }
202 
203         /* create a new array to hold them */
204         ArrayObject* newClasses;
205         newClasses = dvmAllocArrayByClass(gDvm.classJavaLangClassArray,
206                         publicCount, ALLOC_DEFAULT);
207 
208         /* copy them over */
209         ClassObject** pDest = (ClassObject**) newClasses->contents;
210         for (i = newIdx = 0; i < (int)classes->length; i++) {
211             if (dvmIsPublicClass(pSource[i]))
212                 pDest[newIdx++] = pSource[i];
213         }
214 
215         assert(newIdx == publicCount);
216         dvmReleaseTrackedAlloc((Object*) classes, NULL);
217         classes = newClasses;
218     }
219 
220     dvmReleaseTrackedAlloc((Object*) classes, NULL);
221     RETURN_PTR(classes);
222 }
223 
224 /*
225  * static Constructor[] getDeclaredConstructors(Class clazz, boolean publicOnly)
226  *     throws SecurityException
227  */
Dalvik_java_lang_Class_getDeclaredConstructors(const u4 * args,JValue * pResult)228 static void Dalvik_java_lang_Class_getDeclaredConstructors(const u4* args,
229     JValue* pResult)
230 {
231     ClassObject* clazz = (ClassObject*) args[0];
232     bool publicOnly = (args[1] != 0);
233     ArrayObject* constructors;
234 
235     constructors = dvmGetDeclaredConstructors(clazz, publicOnly);
236     dvmReleaseTrackedAlloc((Object*) constructors, NULL);
237 
238     RETURN_PTR(constructors);
239 }
240 
241 /*
242  * static Field[] getDeclaredFields(Class klass, boolean publicOnly)
243  *     throws SecurityException
244  */
Dalvik_java_lang_Class_getDeclaredFields(const u4 * args,JValue * pResult)245 static void Dalvik_java_lang_Class_getDeclaredFields(const u4* args,
246     JValue* pResult)
247 {
248     ClassObject* clazz = (ClassObject*) args[0];
249     bool publicOnly = (args[1] != 0);
250     ArrayObject* fields;
251 
252     fields = dvmGetDeclaredFields(clazz, publicOnly);
253     dvmReleaseTrackedAlloc((Object*) fields, NULL);
254 
255     RETURN_PTR(fields);
256 }
257 
258 /*
259  * static Method[] getDeclaredMethods(Class clazz, boolean publicOnly)
260  *     throws SecurityException
261  */
Dalvik_java_lang_Class_getDeclaredMethods(const u4 * args,JValue * pResult)262 static void Dalvik_java_lang_Class_getDeclaredMethods(const u4* args,
263     JValue* pResult)
264 {
265     ClassObject* clazz = (ClassObject*) args[0];
266     bool publicOnly = (args[1] != 0);
267     ArrayObject* methods;
268 
269     methods = dvmGetDeclaredMethods(clazz, publicOnly);
270     dvmReleaseTrackedAlloc((Object*) methods, NULL);
271 
272     RETURN_PTR(methods);
273 }
274 
275 /*
276  * Class[] getInterfaces()
277  */
Dalvik_java_lang_Class_getInterfaces(const u4 * args,JValue * pResult)278 static void Dalvik_java_lang_Class_getInterfaces(const u4* args,
279     JValue* pResult)
280 {
281     ClassObject* clazz = (ClassObject*) args[0];
282     ArrayObject* interfaces;
283 
284     interfaces = dvmGetInterfaces(clazz);
285     dvmReleaseTrackedAlloc((Object*) interfaces, NULL);
286 
287     RETURN_PTR(interfaces);
288 }
289 
290 /*
291  * private static int getModifiers(Class klass, boolean
292  *     ignoreInnerClassesAttrib)
293  *
294  * Return the class' modifier flags.  If "ignoreInnerClassesAttrib" is false,
295  * and this is an inner class, we return the access flags from the inner class
296  * attribute.
297  */
Dalvik_java_lang_Class_getModifiers(const u4 * args,JValue * pResult)298 static void Dalvik_java_lang_Class_getModifiers(const u4* args, JValue* pResult)
299 {
300     ClassObject* clazz = (ClassObject*) args[0];
301     bool ignoreInner = args[1];
302     u4 accessFlags;
303 
304     accessFlags = clazz->accessFlags & JAVA_FLAGS_MASK;
305 
306     if (!ignoreInner) {
307         /* see if we have an InnerClass annotation with flags in it */
308         StringObject* className = NULL;
309         int innerFlags;
310 
311         if (dvmGetInnerClass(clazz, &className, &innerFlags))
312             accessFlags = innerFlags & JAVA_FLAGS_MASK;
313 
314         dvmReleaseTrackedAlloc((Object*) className, NULL);
315     }
316 
317     RETURN_INT(accessFlags);
318 }
319 
320 /*
321  * public String getName()
322  *
323  * Return the class' name.
324  */
Dalvik_java_lang_Class_getName(const u4 * args,JValue * pResult)325 static void Dalvik_java_lang_Class_getName(const u4* args, JValue* pResult)
326 {
327     ClassObject* clazz = (ClassObject*) args[0];
328     const char* descriptor = clazz->descriptor;
329     StringObject* nameObj;
330 
331     if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
332         /*
333          * The descriptor indicates that this is the class for
334          * a primitive type; special-case the return value.
335          */
336         const char* name;
337         switch (descriptor[0]) {
338             case 'Z': name = "boolean"; break;
339             case 'B': name = "byte";    break;
340             case 'C': name = "char";    break;
341             case 'S': name = "short";   break;
342             case 'I': name = "int";     break;
343             case 'J': name = "long";    break;
344             case 'F': name = "float";   break;
345             case 'D': name = "double";  break;
346             case 'V': name = "void";    break;
347             default: {
348                 LOGE("Unknown primitive type '%c'\n", descriptor[0]);
349                 assert(false);
350                 RETURN_PTR(NULL);
351             }
352         }
353 
354         nameObj = dvmCreateStringFromCstr(name, ALLOC_DEFAULT);
355     } else {
356         /*
357          * Convert the UTF-8 name to a java.lang.String. The
358          * name must use '.' to separate package components.
359          *
360          * TODO: this could be more efficient. Consider a custom
361          * conversion function here that walks the string once and
362          * avoids the allocation for the common case (name less than,
363          * say, 128 bytes).
364          */
365         char* dotName = dvmDescriptorToDot(clazz->descriptor);
366         nameObj = dvmCreateStringFromCstr(dotName, ALLOC_DEFAULT);
367         free(dotName);
368     }
369 
370     dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
371 
372 #if 0
373     /* doesn't work -- need "java.lang.String" not "java/lang/String" */
374     {
375         /*
376          * Find the string in the DEX file and use the copy in the intern
377          * table if it already exists (else put one there).  Only works
378          * for strings in the DEX file, e.g. not arrays.
379          *
380          * We have to do the class lookup by name in the DEX file because
381          * we don't have a DexClassDef pointer in the ClassObject, and it's
382          * not worth adding one there just for this.  Should be cheaper
383          * to do this than the string-creation above.
384          */
385         const DexFile* pDexFile = clazz->pDexFile;
386         const DexClassDef* pClassDef;
387         const DexClassId* pClassId;
388 
389         pDexFile = clazz->pDexFile;
390         pClassDef = dvmDexFindClass(pDexFile, clazz->descriptor);
391         pClassId = dvmDexGetClassId(pDexFile, pClassDef->classIdx);
392         nameObj = dvmDexGetResolvedString(pDexFile, pClassId->nameIdx);
393         if (nameObj == NULL) {
394             nameObj = dvmResolveString(clazz, pClassId->nameIdx);
395             if (nameObj == NULL)
396                 LOGW("WARNING: couldn't find string %u for '%s'\n",
397                     pClassId->nameIdx, clazz->name);
398         }
399     }
400 #endif
401 
402     RETURN_PTR(nameObj);
403 }
404 
405 /*
406  * Return the superclass for instances of this class.
407  *
408  * If the class represents a java/lang/Object, an interface, a primitive
409  * type, or void (which *is* a primitive type??), return NULL.
410  *
411  * For an array, return the java/lang/Object ClassObject.
412  */
Dalvik_java_lang_Class_getSuperclass(const u4 * args,JValue * pResult)413 static void Dalvik_java_lang_Class_getSuperclass(const u4* args,
414     JValue* pResult)
415 {
416     ClassObject* clazz = (ClassObject*) args[0];
417 
418     if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz))
419         RETURN_PTR(NULL);
420     else
421         RETURN_PTR(clazz->super);
422 }
423 
424 /*
425  * public boolean isAssignableFrom(Class<?> cls)
426  *
427  * Determine if this class is either the same as, or is a superclass or
428  * superinterface of, the class specified in the "cls" parameter.
429  */
Dalvik_java_lang_Class_isAssignableFrom(const u4 * args,JValue * pResult)430 static void Dalvik_java_lang_Class_isAssignableFrom(const u4* args,
431     JValue* pResult)
432 {
433     ClassObject* thisPtr = (ClassObject*) args[0];
434     ClassObject* testClass = (ClassObject*) args[1];
435 
436     if (testClass == NULL) {
437         dvmThrowException("Ljava/lang/NullPointerException;", NULL);
438         RETURN_INT(false);
439     }
440     RETURN_INT(dvmInstanceof(testClass, thisPtr));
441 }
442 
443 /*
444  * public boolean isInstance(Object o)
445  *
446  * Dynamic equivalent of Java programming language "instanceof".
447  */
Dalvik_java_lang_Class_isInstance(const u4 * args,JValue * pResult)448 static void Dalvik_java_lang_Class_isInstance(const u4* args,
449     JValue* pResult)
450 {
451     ClassObject* thisPtr = (ClassObject*) args[0];
452     Object* testObj = (Object*) args[1];
453 
454     if (testObj == NULL)
455         RETURN_INT(false);
456     RETURN_INT(dvmInstanceof(testObj->clazz, thisPtr));
457 }
458 
459 /*
460  * public boolean isInterface()
461  */
Dalvik_java_lang_Class_isInterface(const u4 * args,JValue * pResult)462 static void Dalvik_java_lang_Class_isInterface(const u4* args,
463     JValue* pResult)
464 {
465     ClassObject* thisPtr = (ClassObject*) args[0];
466 
467     RETURN_INT(dvmIsInterfaceClass(thisPtr));
468 }
469 
470 /*
471  * public boolean isPrimitive()
472  */
Dalvik_java_lang_Class_isPrimitive(const u4 * args,JValue * pResult)473 static void Dalvik_java_lang_Class_isPrimitive(const u4* args,
474     JValue* pResult)
475 {
476     ClassObject* thisPtr = (ClassObject*) args[0];
477 
478     RETURN_INT(dvmIsPrimitiveClass(thisPtr));
479 }
480 
481 /*
482  * public T newInstance() throws InstantiationException, IllegalAccessException
483  *
484  * Create a new instance of this class.
485  */
Dalvik_java_lang_Class_newInstance(const u4 * args,JValue * pResult)486 static void Dalvik_java_lang_Class_newInstance(const u4* args, JValue* pResult)
487 {
488     Thread* self = dvmThreadSelf();
489     ClassObject* clazz = (ClassObject*) args[0];
490     Method* init;
491     Object* newObj;
492 
493     /* can't instantiate these */
494     if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz)
495         || dvmIsArrayClass(clazz) || dvmIsAbstractClass(clazz))
496     {
497         LOGD("newInstance failed: p%d i%d [%d a%d\n",
498             dvmIsPrimitiveClass(clazz), dvmIsInterfaceClass(clazz),
499             dvmIsArrayClass(clazz), dvmIsAbstractClass(clazz));
500         dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;",
501             clazz->descriptor);
502         RETURN_VOID();
503     }
504 
505     /* initialize the class if it hasn't been already */
506     if (!dvmIsClassInitialized(clazz)) {
507         if (!dvmInitClass(clazz)) {
508             LOGW("Class init failed in newInstance call (%s)\n",
509                 clazz->descriptor);
510             assert(dvmCheckException(self));
511             RETURN_VOID();
512         }
513     }
514 
515     /* find the "nullary" constructor */
516     init = dvmFindDirectMethodByDescriptor(clazz, "<init>", "()V");
517     if (init == NULL) {
518         /* common cause: secret "this" arg on non-static inner class ctor */
519         LOGD("newInstance failed: no <init>()\n");
520         dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;",
521             clazz->descriptor);
522         RETURN_VOID();
523     }
524 
525     /*
526      * Verify access from the call site.
527      *
528      * First, make sure the method invoking Class.newInstance() has permission
529      * to access the class.
530      *
531      * Second, make sure it has permission to invoke the constructor.  The
532      * constructor must be public or, if the caller is in the same package,
533      * have package scope.
534      */
535     ClassObject* callerClass = dvmGetCaller2Class(self->curFrame);
536 
537     if (!dvmCheckClassAccess(callerClass, clazz)) {
538         LOGD("newInstance failed: %s not accessible to %s\n",
539             clazz->descriptor, callerClass->descriptor);
540         dvmThrowException("Ljava/lang/IllegalAccessException;",
541             "access to class not allowed");
542         RETURN_VOID();
543     }
544     if (!dvmCheckMethodAccess(callerClass, init)) {
545         LOGD("newInstance failed: %s.<init>() not accessible to %s\n",
546             clazz->descriptor, callerClass->descriptor);
547         dvmThrowException("Ljava/lang/IllegalAccessException;",
548             "access to constructor not allowed");
549         RETURN_VOID();
550     }
551 
552     newObj = dvmAllocObject(clazz, ALLOC_DEFAULT);
553     JValue unused;
554 
555     /* invoke constructor; unlike reflection calls, we don't wrap exceptions */
556     dvmCallMethod(self, init, newObj, &unused);
557     dvmReleaseTrackedAlloc(newObj, NULL);
558 
559     RETURN_PTR(newObj);
560 }
561 
562 /*
563  * private Object[] getSignatureAnnotation()
564  *
565  * Returns the signature annotation array.
566  */
Dalvik_java_lang_Class_getSignatureAnnotation(const u4 * args,JValue * pResult)567 static void Dalvik_java_lang_Class_getSignatureAnnotation(const u4* args,
568     JValue* pResult)
569 {
570     ClassObject* clazz = (ClassObject*) args[0];
571     ArrayObject* arr = dvmGetClassSignatureAnnotation(clazz);
572 
573     dvmReleaseTrackedAlloc((Object*) arr, NULL);
574     RETURN_PTR(arr);
575 }
576 
577 /*
578  * public Class getDeclaringClass()
579  *
580  * Get the class that encloses this class (if any).
581  */
Dalvik_java_lang_Class_getDeclaringClass(const u4 * args,JValue * pResult)582 static void Dalvik_java_lang_Class_getDeclaringClass(const u4* args,
583     JValue* pResult)
584 {
585     ClassObject* clazz = (ClassObject*) args[0];
586 
587     ClassObject* enclosing = dvmGetDeclaringClass(clazz);
588     dvmReleaseTrackedAlloc((Object*) enclosing, NULL);
589     RETURN_PTR(enclosing);
590 }
591 
592 /*
593  * public Class getEnclosingClass()
594  *
595  * Get the class that encloses this class (if any).
596  */
Dalvik_java_lang_Class_getEnclosingClass(const u4 * args,JValue * pResult)597 static void Dalvik_java_lang_Class_getEnclosingClass(const u4* args,
598     JValue* pResult)
599 {
600     ClassObject* clazz = (ClassObject*) args[0];
601 
602     ClassObject* enclosing = dvmGetEnclosingClass(clazz);
603     dvmReleaseTrackedAlloc((Object*) enclosing, NULL);
604     RETURN_PTR(enclosing);
605 }
606 
607 /*
608  * public Constructor getEnclosingConstructor()
609  *
610  * Get the constructor that encloses this class (if any).
611  */
Dalvik_java_lang_Class_getEnclosingConstructor(const u4 * args,JValue * pResult)612 static void Dalvik_java_lang_Class_getEnclosingConstructor(const u4* args,
613     JValue* pResult)
614 {
615     ClassObject* clazz = (ClassObject*) args[0];
616 
617     Object* enclosing = dvmGetEnclosingMethod(clazz);
618     if (enclosing != NULL) {
619         dvmReleaseTrackedAlloc(enclosing, NULL);
620         if (enclosing->clazz == gDvm.classJavaLangReflectConstructor) {
621             RETURN_PTR(enclosing);
622         }
623         assert(enclosing->clazz == gDvm.classJavaLangReflectMethod);
624     }
625     RETURN_PTR(NULL);
626 }
627 
628 /*
629  * public Method getEnclosingMethod()
630  *
631  * Get the method that encloses this class (if any).
632  */
Dalvik_java_lang_Class_getEnclosingMethod(const u4 * args,JValue * pResult)633 static void Dalvik_java_lang_Class_getEnclosingMethod(const u4* args,
634     JValue* pResult)
635 {
636     ClassObject* clazz = (ClassObject*) args[0];
637 
638     Object* enclosing = dvmGetEnclosingMethod(clazz);
639     if (enclosing != NULL) {
640         dvmReleaseTrackedAlloc(enclosing, NULL);
641         if (enclosing->clazz == gDvm.classJavaLangReflectMethod) {
642             RETURN_PTR(enclosing);
643         }
644         assert(enclosing->clazz == gDvm.classJavaLangReflectConstructor);
645     }
646     RETURN_PTR(NULL);
647 }
648 
649 #if 0
650 static void Dalvik_java_lang_Class_getGenericInterfaces(const u4* args,
651     JValue* pResult)
652 {
653     dvmThrowException("Ljava/lang/UnsupportedOperationException;",
654         "native method not implemented");
655 
656     RETURN_PTR(NULL);
657 }
658 
659 static void Dalvik_java_lang_Class_getGenericSuperclass(const u4* args,
660     JValue* pResult)
661 {
662     dvmThrowException("Ljava/lang/UnsupportedOperationException;",
663         "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     dvmThrowException("Ljava/lang/UnsupportedOperationException;",
672         "native method not implemented");
673 
674     RETURN_PTR(NULL);
675 }
676 #endif
677 
678 /*
679  * public boolean isAnonymousClass()
680  *
681  * Returns true if this is an "anonymous" class.
682  */
Dalvik_java_lang_Class_isAnonymousClass(const u4 * args,JValue * pResult)683 static void Dalvik_java_lang_Class_isAnonymousClass(const u4* args,
684     JValue* pResult)
685 {
686     ClassObject* clazz = (ClassObject*) args[0];
687     StringObject* className = NULL;
688     int accessFlags;
689 
690     /*
691      * If this has an InnerClass annotation, pull it out.  Lack of the
692      * annotation, or an annotation with a NULL class name, indicates
693      * that this is an anonymous inner class.
694      */
695     if (!dvmGetInnerClass(clazz, &className, &accessFlags))
696         RETURN_BOOLEAN(false);
697 
698     dvmReleaseTrackedAlloc((Object*) className, NULL);
699     RETURN_BOOLEAN(className == NULL);
700 }
701 
702 /*
703  * private Annotation[] getDeclaredAnnotations()
704  *
705  * Return the annotations declared on this class.
706  */
Dalvik_java_lang_Class_getDeclaredAnnotations(const u4 * args,JValue * pResult)707 static void Dalvik_java_lang_Class_getDeclaredAnnotations(const u4* args,
708     JValue* pResult)
709 {
710     ClassObject* clazz = (ClassObject*) args[0];
711 
712     ArrayObject* annos = dvmGetClassAnnotations(clazz);
713     dvmReleaseTrackedAlloc((Object*) annos, NULL);
714     RETURN_PTR(annos);
715 }
716 
717 /*
718  * public String getInnerClassName()
719  *
720  * Returns the simple name of a member class or local class, or null otherwise.
721  */
Dalvik_java_lang_Class_getInnerClassName(const u4 * args,JValue * pResult)722 static void Dalvik_java_lang_Class_getInnerClassName(const u4* args,
723     JValue* pResult)
724 {
725     ClassObject* clazz = (ClassObject*) args[0];
726     StringObject* nameObj;
727     int flags;
728 
729     if (dvmGetInnerClass(clazz, &nameObj, &flags)) {
730         dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
731         RETURN_PTR(nameObj);
732     } else {
733         RETURN_PTR(NULL);
734     }
735 }
736 
737 /*
738  * static native void setAccessibleNoCheck(AccessibleObject ao, boolean flag);
739  */
Dalvik_java_lang_Class_setAccessibleNoCheck(const u4 * args,JValue * pResult)740 static void Dalvik_java_lang_Class_setAccessibleNoCheck(const u4* args,
741     JValue* pResult)
742 {
743     Object* target = (Object*) args[0];
744     u4 flag = (u4) args[1];
745 
746     dvmSetFieldBoolean(target, gDvm.offJavaLangReflectAccessibleObject_flag,
747             flag);
748 }
749 
750 const DalvikNativeMethod dvm_java_lang_Class[] = {
751     { "desiredAssertionStatus", "()Z",
752         Dalvik_java_lang_Class_desiredAssertionStatus },
753     { "classForName",           "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;",
754         Dalvik_java_lang_Class_classForName },
755     { "getClassLoader",         "(Ljava/lang/Class;)Ljava/lang/ClassLoader;",
756         Dalvik_java_lang_Class_getClassLoader },
757     { "getComponentType",       "()Ljava/lang/Class;",
758         Dalvik_java_lang_Class_getComponentType },
759     { "getSignatureAnnotation",  "()[Ljava/lang/Object;",
760         Dalvik_java_lang_Class_getSignatureAnnotation },
761     { "getDeclaredClasses",     "(Ljava/lang/Class;Z)[Ljava/lang/Class;",
762         Dalvik_java_lang_Class_getDeclaredClasses },
763     { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;",
764         Dalvik_java_lang_Class_getDeclaredConstructors },
765     { "getDeclaredFields",      "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;",
766         Dalvik_java_lang_Class_getDeclaredFields },
767     { "getDeclaredMethods",     "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;",
768         Dalvik_java_lang_Class_getDeclaredMethods },
769     { "getInterfaces",          "()[Ljava/lang/Class;",
770         Dalvik_java_lang_Class_getInterfaces },
771     { "getModifiers",           "(Ljava/lang/Class;Z)I",
772         Dalvik_java_lang_Class_getModifiers },
773     { "getName",                "()Ljava/lang/String;",
774         Dalvik_java_lang_Class_getName },
775     { "getSuperclass",          "()Ljava/lang/Class;",
776         Dalvik_java_lang_Class_getSuperclass },
777     { "isAssignableFrom",       "(Ljava/lang/Class;)Z",
778         Dalvik_java_lang_Class_isAssignableFrom },
779     { "isInstance",             "(Ljava/lang/Object;)Z",
780         Dalvik_java_lang_Class_isInstance },
781     { "isInterface",            "()Z",
782         Dalvik_java_lang_Class_isInterface },
783     { "isPrimitive",            "()Z",
784         Dalvik_java_lang_Class_isPrimitive },
785     { "newInstanceImpl",        "()Ljava/lang/Object;",
786         Dalvik_java_lang_Class_newInstance },
787     { "getDeclaringClass",      "()Ljava/lang/Class;",
788         Dalvik_java_lang_Class_getDeclaringClass },
789     { "getEnclosingClass",      "()Ljava/lang/Class;",
790         Dalvik_java_lang_Class_getEnclosingClass },
791     { "getEnclosingConstructor", "()Ljava/lang/reflect/Constructor;",
792         Dalvik_java_lang_Class_getEnclosingConstructor },
793     { "getEnclosingMethod",     "()Ljava/lang/reflect/Method;",
794         Dalvik_java_lang_Class_getEnclosingMethod },
795 #if 0
796     { "getGenericInterfaces",   "()[Ljava/lang/reflect/Type;",
797         Dalvik_java_lang_Class_getGenericInterfaces },
798     { "getGenericSuperclass",   "()Ljava/lang/reflect/Type;",
799         Dalvik_java_lang_Class_getGenericSuperclass },
800     { "getTypeParameters",      "()Ljava/lang/reflect/TypeVariable;",
801         Dalvik_java_lang_Class_getTypeParameters },
802 #endif
803     { "isAnonymousClass",       "()Z",
804         Dalvik_java_lang_Class_isAnonymousClass },
805     { "getDeclaredAnnotations", "()[Ljava/lang/annotation/Annotation;",
806         Dalvik_java_lang_Class_getDeclaredAnnotations },
807     { "getInnerClassName",       "()Ljava/lang/String;",
808         Dalvik_java_lang_Class_getInnerClassName },
809     { "setAccessibleNoCheck",   "(Ljava/lang/reflect/AccessibleObject;Z)V",
810         Dalvik_java_lang_Class_setAccessibleNoCheck },
811     { NULL, NULL, NULL },
812 };
813 
814