2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include "native/InternalNativePriv.h"
25 * native public boolean desiredAssertionStatus()
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.
31 static void Dalvik_java_lang_Class_desiredAssertionStatus(const u4* args,
34 ClassObject* thisPtr = (ClassObject*) args[0];
35 char* className = dvmDescriptorToName(thisPtr->descriptor);
40 * Run through the list of arguments specified on the command line. The
41 * last matching argument takes precedence.
43 for (i = 0; i < gDvm.assertionCtrlCount; i++) {
44 const AssertionControl* pCtrl = &gDvm.assertionCtrl[i];
46 if (pCtrl->isPackage) {
48 * Given "dalvik/system/Debug" or "MyStuff", compute the
49 * length of the package portion of the class name string.
51 * Unlike most package operations, we allow matching on
52 * "sub-packages", so "dalvik..." will match "dalvik.Foo"
53 * and "dalvik.system.Foo".
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.
59 const char* lastSlash;
62 lastSlash = strrchr(className, '/');
63 if (lastSlash == NULL) {
66 pkgLen = lastSlash - className +1;
69 if (pCtrl->pkgOrClassLen > pkgLen ||
70 memcmp(pCtrl->pkgOrClass, className, pCtrl->pkgOrClassLen) != 0)
72 LOGV("ASRT: pkg no match: '%s'(%d) vs '%s'\n",
73 className, pkgLen, pCtrl->pkgOrClass);
75 LOGV("ASRT: pkg match: '%s'(%d) vs '%s' --> %d\n",
76 className, pkgLen, pCtrl->pkgOrClass, pCtrl->enable);
77 enable = pCtrl->enable;
81 * "pkgOrClass" holds a fully-qualified class name, converted from
82 * dot-form to slash-form. An empty string means all classes.
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);
89 LOGV("ASRT: sys match: '%s' --> %d\n",
90 className, pCtrl->enable);
91 enable = pCtrl->enable;
93 } else if (*pCtrl->pkgOrClass == '\0') {
94 LOGV("ASRT: class all: '%s' --> %d\n",
95 className, pCtrl->enable);
96 enable = pCtrl->enable;
98 if (strcmp(pCtrl->pkgOrClass, className) != 0) {
99 LOGV("ASRT: cls no match: '%s' vs '%s'\n",
100 className, pCtrl->pkgOrClass);
102 LOGV("ASRT: cls match: '%s' vs '%s' --> %d\n",
103 className, pCtrl->pkgOrClass, pCtrl->enable);
104 enable = pCtrl->enable;
115 * static public Class<?> classForName(String name, boolean initialize,
116 * ClassLoader loader)
118 * Return the Class object associated with the class or interface with
119 * the specified name.
121 * "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
123 static void Dalvik_java_lang_Class_classForName(const u4* args, JValue* pResult)
125 StringObject* nameObj = (StringObject*) args[0];
126 bool initialize = (args[1] != 0);
127 Object* loader = (Object*) args[2];
129 RETURN_PTR(dvmFindClassByName(nameObj, loader, initialize));
133 * static private ClassLoader getClassLoader(Class clazz)
135 * Return the class' defining class loader.
137 static void Dalvik_java_lang_Class_getClassLoader(const u4* args,
140 ClassObject* clazz = (ClassObject*) args[0];
142 RETURN_PTR(clazz->classLoader);
146 * public Class<?> getComponentType()
148 * If this is an array type, return the class of the elements; otherwise
151 static void Dalvik_java_lang_Class_getComponentType(const u4* args,
154 ClassObject* thisPtr = (ClassObject*) args[0];
156 if (!dvmIsArrayClass(thisPtr))
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.
164 if (thisPtr->descriptor[1] == '[')
165 RETURN_PTR(dvmFindArrayClass(&thisPtr->descriptor[1],
166 thisPtr->classLoader));
168 RETURN_PTR(thisPtr->elementClass);
172 * private static Class<?>[] getDeclaredClasses(Class<?> clazz,
173 * boolean publicOnly)
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"
179 static void Dalvik_java_lang_Class_getDeclaredClasses(const u4* args,
182 ClassObject* clazz = (ClassObject*) args[0];
183 bool publicOnly = (args[1] != 0);
184 ArrayObject* classes;
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,
193 } else if (publicOnly) {
194 u4 count, newIdx, publicCount = 0;
195 ClassObject** pSource = (ClassObject**) classes->contents;
196 u4 length = classes->length;
198 /* count up public classes */
199 for (count = 0; count < length; count++) {
200 if (dvmIsPublicClass(pSource[count]))
204 /* create a new array to hold them */
205 ArrayObject* newClasses;
206 newClasses = dvmAllocArrayByClass(gDvm.classJavaLangClassArray,
207 publicCount, ALLOC_DEFAULT);
210 for (count = newIdx = 0; count < length; count++) {
211 if (dvmIsPublicClass(pSource[count])) {
212 dvmSetObjectArrayElement(newClasses, newIdx,
213 (Object *)pSource[count]);
217 assert(newIdx == publicCount);
218 dvmReleaseTrackedAlloc((Object*) classes, NULL);
219 classes = newClasses;
222 dvmReleaseTrackedAlloc((Object*) classes, NULL);
227 * static Constructor[] getDeclaredConstructors(Class clazz, boolean publicOnly)
228 * throws SecurityException
230 static void Dalvik_java_lang_Class_getDeclaredConstructors(const u4* args,
233 ClassObject* clazz = (ClassObject*) args[0];
234 bool publicOnly = (args[1] != 0);
235 ArrayObject* constructors;
237 constructors = dvmGetDeclaredConstructors(clazz, publicOnly);
238 dvmReleaseTrackedAlloc((Object*) constructors, NULL);
240 RETURN_PTR(constructors);
244 * static Field[] getDeclaredFields(Class klass, boolean publicOnly)
245 * throws SecurityException
247 static void Dalvik_java_lang_Class_getDeclaredFields(const u4* args,
250 ClassObject* clazz = (ClassObject*) args[0];
251 bool publicOnly = (args[1] != 0);
254 fields = dvmGetDeclaredFields(clazz, publicOnly);
255 dvmReleaseTrackedAlloc((Object*) fields, NULL);
261 * static Method[] getDeclaredMethods(Class clazz, boolean publicOnly)
262 * throws SecurityException
264 static void Dalvik_java_lang_Class_getDeclaredMethods(const u4* args,
267 ClassObject* clazz = (ClassObject*) args[0];
268 bool publicOnly = (args[1] != 0);
269 ArrayObject* methods;
271 methods = dvmGetDeclaredMethods(clazz, publicOnly);
272 dvmReleaseTrackedAlloc((Object*) methods, NULL);
278 * Class[] getInterfaces()
280 static void Dalvik_java_lang_Class_getInterfaces(const u4* args,
283 ClassObject* clazz = (ClassObject*) args[0];
284 ArrayObject* interfaces;
286 interfaces = dvmGetInterfaces(clazz);
287 dvmReleaseTrackedAlloc((Object*) interfaces, NULL);
289 RETURN_PTR(interfaces);
293 * private static int getModifiers(Class klass, boolean
294 * ignoreInnerClassesAttrib)
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
300 static void Dalvik_java_lang_Class_getModifiers(const u4* args, JValue* pResult)
302 ClassObject* clazz = (ClassObject*) args[0];
303 bool ignoreInner = args[1];
306 accessFlags = clazz->accessFlags & JAVA_FLAGS_MASK;
309 /* see if we have an InnerClass annotation with flags in it */
310 StringObject* className = NULL;
313 if (dvmGetInnerClass(clazz, &className, &innerFlags))
314 accessFlags = innerFlags & JAVA_FLAGS_MASK;
316 dvmReleaseTrackedAlloc((Object*) className, NULL);
319 RETURN_INT(accessFlags);
323 * private native String getNameNative()
325 * Return the class' name. The exact format is bizarre, but it's the specified
326 * behavior: keywords for primitive types, regular "[I" form for primitive
327 * arrays (so "int" but "[I"), and arrays of reference types written
328 * between "L" and ";" but with dots rather than slashes (so "java.lang.String"
329 * but "[Ljava.lang.String;"). Madness.
331 static void Dalvik_java_lang_Class_getNameNative(const u4* args, JValue* pResult)
333 ClassObject* clazz = (ClassObject*) args[0];
334 const char* descriptor = clazz->descriptor;
335 StringObject* nameObj;
337 if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
339 * The descriptor indicates that this is the class for
340 * a primitive type; special-case the return value.
343 switch (descriptor[0]) {
344 case 'Z': name = "boolean"; break;
345 case 'B': name = "byte"; break;
346 case 'C': name = "char"; break;
347 case 'S': name = "short"; break;
348 case 'I': name = "int"; break;
349 case 'J': name = "long"; break;
350 case 'F': name = "float"; break;
351 case 'D': name = "double"; break;
352 case 'V': name = "void"; break;
354 LOGE("Unknown primitive type '%c'\n", descriptor[0]);
360 nameObj = dvmCreateStringFromCstr(name);
363 * Convert the UTF-8 name to a java.lang.String. The
364 * name must use '.' to separate package components.
366 * TODO: this could be more efficient. Consider a custom
367 * conversion function here that walks the string once and
368 * avoids the allocation for the common case (name less than,
371 char* dotName = dvmDescriptorToDot(clazz->descriptor);
372 nameObj = dvmCreateStringFromCstr(dotName);
376 dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
381 * Return the superclass for instances of this class.
383 * If the class represents a java/lang/Object, an interface, a primitive
384 * type, or void (which *is* a primitive type??), return NULL.
386 * For an array, return the java/lang/Object ClassObject.
388 static void Dalvik_java_lang_Class_getSuperclass(const u4* args,
391 ClassObject* clazz = (ClassObject*) args[0];
393 if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz))
396 RETURN_PTR(clazz->super);
400 * public boolean isAssignableFrom(Class<?> cls)
402 * Determine if this class is either the same as, or is a superclass or
403 * superinterface of, the class specified in the "cls" parameter.
405 static void Dalvik_java_lang_Class_isAssignableFrom(const u4* args,
408 ClassObject* thisPtr = (ClassObject*) args[0];
409 ClassObject* testClass = (ClassObject*) args[1];
411 if (testClass == NULL) {
412 dvmThrowException("Ljava/lang/NullPointerException;", NULL);
415 RETURN_INT(dvmInstanceof(testClass, thisPtr));
419 * public boolean isInstance(Object o)
421 * Dynamic equivalent of Java programming language "instanceof".
423 static void Dalvik_java_lang_Class_isInstance(const u4* args,
426 ClassObject* thisPtr = (ClassObject*) args[0];
427 Object* testObj = (Object*) args[1];
431 RETURN_INT(dvmInstanceof(testObj->clazz, thisPtr));
435 * public boolean isInterface()
437 static void Dalvik_java_lang_Class_isInterface(const u4* args,
440 ClassObject* thisPtr = (ClassObject*) args[0];
442 RETURN_INT(dvmIsInterfaceClass(thisPtr));
446 * public boolean isPrimitive()
448 static void Dalvik_java_lang_Class_isPrimitive(const u4* args,
451 ClassObject* thisPtr = (ClassObject*) args[0];
453 RETURN_INT(dvmIsPrimitiveClass(thisPtr));
457 * public T newInstance() throws InstantiationException, IllegalAccessException
459 * Create a new instance of this class.
461 static void Dalvik_java_lang_Class_newInstance(const u4* args, JValue* pResult)
463 Thread* self = dvmThreadSelf();
464 ClassObject* clazz = (ClassObject*) args[0];
468 /* can't instantiate these */
469 if (dvmIsPrimitiveClass(clazz) || dvmIsInterfaceClass(clazz)
470 || dvmIsArrayClass(clazz) || dvmIsAbstractClass(clazz))
472 LOGD("newInstance failed: p%d i%d [%d a%d\n",
473 dvmIsPrimitiveClass(clazz), dvmIsInterfaceClass(clazz),
474 dvmIsArrayClass(clazz), dvmIsAbstractClass(clazz));
475 dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;",
480 /* initialize the class if it hasn't been already */
481 if (!dvmIsClassInitialized(clazz)) {
482 if (!dvmInitClass(clazz)) {
483 LOGW("Class init failed in newInstance call (%s)\n",
485 assert(dvmCheckException(self));
490 /* find the "nullary" constructor */
491 init = dvmFindDirectMethodByDescriptor(clazz, "<init>", "()V");
493 /* common cause: secret "this" arg on non-static inner class ctor */
494 LOGD("newInstance failed: no <init>()\n");
495 dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationException;",
501 * Verify access from the call site.
503 * First, make sure the method invoking Class.newInstance() has permission
504 * to access the class.
506 * Second, make sure it has permission to invoke the constructor. The
507 * constructor must be public or, if the caller is in the same package,
508 * have package scope.
510 ClassObject* callerClass = dvmGetCaller2Class(self->curFrame);
512 if (!dvmCheckClassAccess(callerClass, clazz)) {
513 LOGD("newInstance failed: %s not accessible to %s\n",
514 clazz->descriptor, callerClass->descriptor);
515 dvmThrowException("Ljava/lang/IllegalAccessException;",
516 "access to class not allowed");
519 if (!dvmCheckMethodAccess(callerClass, init)) {
520 LOGD("newInstance failed: %s.<init>() not accessible to %s\n",
521 clazz->descriptor, callerClass->descriptor);
522 dvmThrowException("Ljava/lang/IllegalAccessException;",
523 "access to constructor not allowed");
527 newObj = dvmAllocObject(clazz, ALLOC_DEFAULT);
530 /* invoke constructor; unlike reflection calls, we don't wrap exceptions */
531 dvmCallMethod(self, init, newObj, &unused);
532 dvmReleaseTrackedAlloc(newObj, NULL);
538 * private Object[] getSignatureAnnotation()
540 * Returns the signature annotation array.
542 static void Dalvik_java_lang_Class_getSignatureAnnotation(const u4* args,
545 ClassObject* clazz = (ClassObject*) args[0];
546 ArrayObject* arr = dvmGetClassSignatureAnnotation(clazz);
548 dvmReleaseTrackedAlloc((Object*) arr, NULL);
553 * public Class getDeclaringClass()
555 * Get the class that encloses this class (if any).
557 static void Dalvik_java_lang_Class_getDeclaringClass(const u4* args,
560 ClassObject* clazz = (ClassObject*) args[0];
562 ClassObject* enclosing = dvmGetDeclaringClass(clazz);
563 dvmReleaseTrackedAlloc((Object*) enclosing, NULL);
564 RETURN_PTR(enclosing);
568 * public Class getEnclosingClass()
570 * Get the class that encloses this class (if any).
572 static void Dalvik_java_lang_Class_getEnclosingClass(const u4* args,
575 ClassObject* clazz = (ClassObject*) args[0];
577 ClassObject* enclosing = dvmGetEnclosingClass(clazz);
578 dvmReleaseTrackedAlloc((Object*) enclosing, NULL);
579 RETURN_PTR(enclosing);
583 * public Constructor getEnclosingConstructor()
585 * Get the constructor that encloses this class (if any).
587 static void Dalvik_java_lang_Class_getEnclosingConstructor(const u4* args,
590 ClassObject* clazz = (ClassObject*) args[0];
592 Object* enclosing = dvmGetEnclosingMethod(clazz);
593 if (enclosing != NULL) {
594 dvmReleaseTrackedAlloc(enclosing, NULL);
595 if (enclosing->clazz == gDvm.classJavaLangReflectConstructor) {
596 RETURN_PTR(enclosing);
598 assert(enclosing->clazz == gDvm.classJavaLangReflectMethod);
604 * public Method getEnclosingMethod()
606 * Get the method that encloses this class (if any).
608 static void Dalvik_java_lang_Class_getEnclosingMethod(const u4* args,
611 ClassObject* clazz = (ClassObject*) args[0];
613 Object* enclosing = dvmGetEnclosingMethod(clazz);
614 if (enclosing != NULL) {
615 dvmReleaseTrackedAlloc(enclosing, NULL);
616 if (enclosing->clazz == gDvm.classJavaLangReflectMethod) {
617 RETURN_PTR(enclosing);
619 assert(enclosing->clazz == gDvm.classJavaLangReflectConstructor);
625 static void Dalvik_java_lang_Class_getGenericInterfaces(const u4* args,
628 dvmThrowException("Ljava/lang/UnsupportedOperationException;",
629 "native method not implemented");
634 static void Dalvik_java_lang_Class_getGenericSuperclass(const u4* args,
637 dvmThrowException("Ljava/lang/UnsupportedOperationException;",
638 "native method not implemented");
643 static void Dalvik_java_lang_Class_getTypeParameters(const u4* args,
646 dvmThrowException("Ljava/lang/UnsupportedOperationException;",
647 "native method not implemented");
654 * public boolean isAnonymousClass()
656 * Returns true if this is an "anonymous" class.
658 static void Dalvik_java_lang_Class_isAnonymousClass(const u4* args,
661 ClassObject* clazz = (ClassObject*) args[0];
662 StringObject* className = NULL;
666 * If this has an InnerClass annotation, pull it out. Lack of the
667 * annotation, or an annotation with a NULL class name, indicates
668 * that this is an anonymous inner class.
670 if (!dvmGetInnerClass(clazz, &className, &accessFlags))
671 RETURN_BOOLEAN(false);
673 dvmReleaseTrackedAlloc((Object*) className, NULL);
674 RETURN_BOOLEAN(className == NULL);
678 * private Annotation[] getDeclaredAnnotations()
680 * Return the annotations declared on this class.
682 static void Dalvik_java_lang_Class_getDeclaredAnnotations(const u4* args,
685 ClassObject* clazz = (ClassObject*) args[0];
687 ArrayObject* annos = dvmGetClassAnnotations(clazz);
688 dvmReleaseTrackedAlloc((Object*) annos, NULL);
693 * public String getInnerClassName()
695 * Returns the simple name of a member class or local class, or null otherwise.
697 static void Dalvik_java_lang_Class_getInnerClassName(const u4* args,
700 ClassObject* clazz = (ClassObject*) args[0];
701 StringObject* nameObj;
704 if (dvmGetInnerClass(clazz, &nameObj, &flags)) {
705 dvmReleaseTrackedAlloc((Object*) nameObj, NULL);
713 * static native void setAccessibleNoCheck(AccessibleObject ao, boolean flag);
715 static void Dalvik_java_lang_Class_setAccessibleNoCheck(const u4* args,
718 Object* target = (Object*) args[0];
719 u4 flag = (u4) args[1];
721 dvmSetFieldBoolean(target, gDvm.offJavaLangReflectAccessibleObject_flag,
725 const DalvikNativeMethod dvm_java_lang_Class[] = {
726 { "desiredAssertionStatus", "()Z",
727 Dalvik_java_lang_Class_desiredAssertionStatus },
728 { "classForName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;",
729 Dalvik_java_lang_Class_classForName },
730 { "getClassLoader", "(Ljava/lang/Class;)Ljava/lang/ClassLoader;",
731 Dalvik_java_lang_Class_getClassLoader },
732 { "getComponentType", "()Ljava/lang/Class;",
733 Dalvik_java_lang_Class_getComponentType },
734 { "getSignatureAnnotation", "()[Ljava/lang/Object;",
735 Dalvik_java_lang_Class_getSignatureAnnotation },
736 { "getDeclaredClasses", "(Ljava/lang/Class;Z)[Ljava/lang/Class;",
737 Dalvik_java_lang_Class_getDeclaredClasses },
738 { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;",
739 Dalvik_java_lang_Class_getDeclaredConstructors },
740 { "getDeclaredFields", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;",
741 Dalvik_java_lang_Class_getDeclaredFields },
742 { "getDeclaredMethods", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;",
743 Dalvik_java_lang_Class_getDeclaredMethods },
744 { "getInterfaces", "()[Ljava/lang/Class;",
745 Dalvik_java_lang_Class_getInterfaces },
746 { "getModifiers", "(Ljava/lang/Class;Z)I",
747 Dalvik_java_lang_Class_getModifiers },
748 { "getNameNative", "()Ljava/lang/String;",
749 Dalvik_java_lang_Class_getNameNative },
750 { "getSuperclass", "()Ljava/lang/Class;",
751 Dalvik_java_lang_Class_getSuperclass },
752 { "isAssignableFrom", "(Ljava/lang/Class;)Z",
753 Dalvik_java_lang_Class_isAssignableFrom },
754 { "isInstance", "(Ljava/lang/Object;)Z",
755 Dalvik_java_lang_Class_isInstance },
756 { "isInterface", "()Z",
757 Dalvik_java_lang_Class_isInterface },
758 { "isPrimitive", "()Z",
759 Dalvik_java_lang_Class_isPrimitive },
760 { "newInstanceImpl", "()Ljava/lang/Object;",
761 Dalvik_java_lang_Class_newInstance },
762 { "getDeclaringClass", "()Ljava/lang/Class;",
763 Dalvik_java_lang_Class_getDeclaringClass },
764 { "getEnclosingClass", "()Ljava/lang/Class;",
765 Dalvik_java_lang_Class_getEnclosingClass },
766 { "getEnclosingConstructor", "()Ljava/lang/reflect/Constructor;",
767 Dalvik_java_lang_Class_getEnclosingConstructor },
768 { "getEnclosingMethod", "()Ljava/lang/reflect/Method;",
769 Dalvik_java_lang_Class_getEnclosingMethod },
771 { "getGenericInterfaces", "()[Ljava/lang/reflect/Type;",
772 Dalvik_java_lang_Class_getGenericInterfaces },
773 { "getGenericSuperclass", "()Ljava/lang/reflect/Type;",
774 Dalvik_java_lang_Class_getGenericSuperclass },
775 { "getTypeParameters", "()Ljava/lang/reflect/TypeVariable;",
776 Dalvik_java_lang_Class_getTypeParameters },
778 { "isAnonymousClass", "()Z",
779 Dalvik_java_lang_Class_isAnonymousClass },
780 { "getDeclaredAnnotations", "()[Ljava/lang/annotation/Annotation;",
781 Dalvik_java_lang_Class_getDeclaredAnnotations },
782 { "getInnerClassName", "()Ljava/lang/String;",
783 Dalvik_java_lang_Class_getInnerClassName },
784 { "setAccessibleNoCheck", "(Ljava/lang/reflect/AccessibleObject;Z)V",
785 Dalvik_java_lang_Class_setAccessibleNoCheck },
786 { NULL, NULL, NULL },