java_lang_Class.cpp revision 062bf509a77fce9dfcb7e7b2e401cf2a124d83d5
1e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/*
2e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Copyright (C) 2008 The Android Open Source Project
3e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
4e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License");
5e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * you may not use this file except in compliance with the License.
6e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * You may obtain a copy of the License at
7e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
8e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *      http://www.apache.org/licenses/LICENSE-2.0
9e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
10e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Unless required by applicable law or agreed to in writing, software
11e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS,
12e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See the License for the specific language governing permissions and
14e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * limitations under the License.
15e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */
16e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
17e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/*
18e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * java.lang.Class
19bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang */
20bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang#include "Dalvik.h"
21bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang#include "native/InternalNativePriv.h"
22891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang
23bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang
24bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang/*
25e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * native public boolean desiredAssertionStatus()
26bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang *
27e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Determine the class-init-time assertion status of a class.  This is
28e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * called from <clinit> in javac-generated classes that use the Java
29bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang * programming language "assert" keyword.
30bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang */
31bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wangstatic void Dalvik_java_lang_Class_desiredAssertionStatus(const u4* args,
32bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang    JValue* pResult)
33bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang{
34bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang    ClassObject* thisPtr = (ClassObject*) args[0];
35bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang    char* className = dvmDescriptorToName(thisPtr->descriptor);
36bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang    int i;
37bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang    bool enable = false;
38bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang
39bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang    /*
40bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang     * Run through the list of arguments specified on the command line.  The
41bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang     * last matching argument takes precedence.
42bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang     */
43891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang    for (i = 0; i < gDvm.assertionCtrlCount; i++) {
44bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang        const AssertionControl* pCtrl = &gDvm.assertionCtrl[i];
45e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
46bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang        if (pCtrl->isPackage) {
47bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang            /*
48bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang             * Given "dalvik/system/Debug" or "MyStuff", compute the
49bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang             * length of the package portion of the class name string.
50bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang             *
51bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang             * Unlike most package operations, we allow matching on
52891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang             * "sub-packages", so "dalvik..." will match "dalvik.Foo"
53891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang             * and "dalvik.system.Foo".
54bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang             *
55bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang             * The pkgOrClass string looks like "dalvik/system/", i.e. it still
56bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang             * has the terminating slash, so we can be sure we're comparing
57bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang             * against full package component names.
58bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang             */
59bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang            const char* lastSlash;
60bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang            int pkgLen;
61e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
62bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang            lastSlash = strrchr(className, '/');
63891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            if (lastSlash == NULL) {
64891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                pkgLen = 0;
65891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            } else {
66891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                pkgLen = lastSlash - className +1;
67891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            }
68891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang
69891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            if (pCtrl->pkgOrClassLen > pkgLen ||
70891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                memcmp(pCtrl->pkgOrClass, className, pCtrl->pkgOrClassLen) != 0)
71891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            {
72891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                ALOGV("ASRT: pkg no match: '%s'(%d) vs '%s'",
73891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                    className, pkgLen, pCtrl->pkgOrClass);
74891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            } else {
75891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                ALOGV("ASRT: pkg match: '%s'(%d) vs '%s' --> %d",
76891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                    className, pkgLen, pCtrl->pkgOrClass, pCtrl->enable);
77891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                enable = pCtrl->enable;
78891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            }
79891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang        } else {
80891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            /*
81891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang             * "pkgOrClass" holds a fully-qualified class name, converted from
82891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang             * dot-form to slash-form.  An empty string means all classes.
83891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang             */
84891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            if (pCtrl->pkgOrClass == NULL) {
85891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                /* -esa/-dsa; see if class is a "system" class */
86891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                if (strncmp(className, "java/", 5) != 0) {
87891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                    ALOGV("ASRT: sys no match: '%s'", className);
88891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                } else {
89891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                    ALOGV("ASRT: sys match: '%s' --> %d",
90891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                        className, pCtrl->enable);
91891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                    enable = pCtrl->enable;
92891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                }
93891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            } else if (*pCtrl->pkgOrClass == '\0') {
94891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                ALOGV("ASRT: class all: '%s' --> %d",
95891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                    className, pCtrl->enable);
96891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                enable = pCtrl->enable;
97891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            } else {
98891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                if (strcmp(pCtrl->pkgOrClass, className) != 0) {
99891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                    ALOGV("ASRT: cls no match: '%s' vs '%s'",
100891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                        className, pCtrl->pkgOrClass);
101891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                } else {
102891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                    ALOGV("ASRT: cls match: '%s' vs '%s' --> %d",
103891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                        className, pCtrl->pkgOrClass, pCtrl->enable);
104891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                    enable = pCtrl->enable;
105891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang                }
106891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang            }
107891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang        }
108891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang    }
109891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang
110891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang    free(className);
111891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang    RETURN_INT(enable);
112bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang}
113bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang
114bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang/*
115bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang * static public Class<?> classForName(String name, boolean initialize,
116bc0f493f4e6231d12a2c3978c2d8ca1fb5597791Ying Wang *     ClassLoader loader)
117891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang *
118891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang * Return the Class object associated with the class or interface with
119891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang * the specified name.
120891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang *
121891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang * "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
122891e95db9d34c76b1568859865ca4d23f66aa1a2Ying Wang */
123static 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 */
137static 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 */
151static 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 */
179static 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 */
230static 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 */
246static 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 */
262static 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 */
276static 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 */
293static 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 */
311static 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 */
331static 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 */
362static 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                LOGE("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 */
419static 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 */
436static 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 */
454static 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 */
468static 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 */
479static 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 */
492static 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            LOGW("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 */
569static 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 */
584static 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 */
599static 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 */
614static 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 */
635static 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
652static 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
660static 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
668static 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 */
682static 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 */
706static 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 */
719static 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 */
731static 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 */
745static 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
760const DalvikNativeMethod dvm_java_lang_Class[] = {
761    { "desiredAssertionStatus", "()Z",
762        Dalvik_java_lang_Class_desiredAssertionStatus },
763    { "classForName",           "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;",
764        Dalvik_java_lang_Class_classForName },
765    { "getClassLoader",         "(Ljava/lang/Class;)Ljava/lang/ClassLoader;",
766        Dalvik_java_lang_Class_getClassLoader },
767    { "getComponentType",       "()Ljava/lang/Class;",
768        Dalvik_java_lang_Class_getComponentType },
769    { "getSignatureAnnotation",  "()[Ljava/lang/Object;",
770        Dalvik_java_lang_Class_getSignatureAnnotation },
771    { "getDeclaredClasses",     "(Ljava/lang/Class;Z)[Ljava/lang/Class;",
772        Dalvik_java_lang_Class_getDeclaredClasses },
773    { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;",
774        Dalvik_java_lang_Class_getDeclaredConstructors },
775    { "getDeclaredFields",      "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;",
776        Dalvik_java_lang_Class_getDeclaredFields },
777    { "getDeclaredMethods",     "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;",
778        Dalvik_java_lang_Class_getDeclaredMethods },
779    { "getDeclaredField",      "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;",
780        Dalvik_java_lang_Class_getDeclaredField },
781    { "getDeclaredConstructorOrMethod", "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;",
782        Dalvik_java_lang_Class_getDeclaredConstructorOrMethod },
783    { "getInterfaces",          "()[Ljava/lang/Class;",
784        Dalvik_java_lang_Class_getInterfaces },
785    { "getModifiers",           "(Ljava/lang/Class;Z)I",
786        Dalvik_java_lang_Class_getModifiers },
787    { "getNameNative",                "()Ljava/lang/String;",
788        Dalvik_java_lang_Class_getNameNative },
789    { "getSuperclass",          "()Ljava/lang/Class;",
790        Dalvik_java_lang_Class_getSuperclass },
791    { "isAssignableFrom",       "(Ljava/lang/Class;)Z",
792        Dalvik_java_lang_Class_isAssignableFrom },
793    { "isInstance",             "(Ljava/lang/Object;)Z",
794        Dalvik_java_lang_Class_isInstance },
795    { "isInterface",            "()Z",
796        Dalvik_java_lang_Class_isInterface },
797    { "isPrimitive",            "()Z",
798        Dalvik_java_lang_Class_isPrimitive },
799    { "newInstanceImpl",        "()Ljava/lang/Object;",
800        Dalvik_java_lang_Class_newInstance },
801    { "getDeclaringClass",      "()Ljava/lang/Class;",
802        Dalvik_java_lang_Class_getDeclaringClass },
803    { "getEnclosingClass",      "()Ljava/lang/Class;",
804        Dalvik_java_lang_Class_getEnclosingClass },
805    { "getEnclosingConstructor", "()Ljava/lang/reflect/Constructor;",
806        Dalvik_java_lang_Class_getEnclosingConstructor },
807    { "getEnclosingMethod",     "()Ljava/lang/reflect/Method;",
808        Dalvik_java_lang_Class_getEnclosingMethod },
809#if 0
810    { "getGenericInterfaces",   "()[Ljava/lang/reflect/Type;",
811        Dalvik_java_lang_Class_getGenericInterfaces },
812    { "getGenericSuperclass",   "()Ljava/lang/reflect/Type;",
813        Dalvik_java_lang_Class_getGenericSuperclass },
814    { "getTypeParameters",      "()Ljava/lang/reflect/TypeVariable;",
815        Dalvik_java_lang_Class_getTypeParameters },
816#endif
817    { "isAnonymousClass",       "()Z",
818        Dalvik_java_lang_Class_isAnonymousClass },
819    { "getDeclaredAnnotations", "()[Ljava/lang/annotation/Annotation;",
820        Dalvik_java_lang_Class_getDeclaredAnnotations },
821    { "getDeclaredAnnotation", "(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;",
822        Dalvik_java_lang_Class_getDeclaredAnnotation },
823    { "isDeclaredAnnotationPresent", "(Ljava/lang/Class;)Z",
824        Dalvik_java_lang_Class_isDeclaredAnnotationPresent },
825    { "getInnerClassName",       "()Ljava/lang/String;",
826        Dalvik_java_lang_Class_getInnerClassName },
827    { NULL, NULL, NULL },
828};
829