java_lang_reflect_Array.cpp revision e8e1ddccd616e8226b7cc1e4e9fdb327429249e8
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.reflect.Array
19 */
20#include "Dalvik.h"
21#include "native/InternalNativePriv.h"
22
23
24/*
25 * private static Object createObjectArray(Class<?> componentType,
26 *     int length) throws NegativeArraySizeException;
27 *
28 * Create a one-dimensional array of Objects.
29 */
30static void Dalvik_java_lang_reflect_Array_createObjectArray(const u4* args,
31    JValue* pResult)
32{
33    ClassObject* elementClass = (ClassObject*) args[0];
34    int length = args[1];
35
36    assert(elementClass != NULL);       // tested by caller
37    if (length < 0) {
38        dvmThrowNegativeArraySizeException(length);
39        RETURN_VOID();
40    }
41
42    ClassObject* arrayClass =
43        dvmFindArrayClassForElement(elementClass);
44    ArrayObject* newArray =
45        dvmAllocArrayByClass(arrayClass, length, ALLOC_DEFAULT);
46    if (newArray == NULL) {
47        assert(dvmCheckException(dvmThreadSelf()));
48        RETURN_VOID();
49    }
50    dvmReleaseTrackedAlloc((Object*) newArray, NULL);
51
52    RETURN_PTR(newArray);
53}
54
55/*
56 * private static Object createMultiArray(Class<?> componentType,
57 *     int[] dimensions) throws NegativeArraySizeException;
58 *
59 * Create a multi-dimensional array of Objects or primitive types.
60 *
61 * We have to generate the names for X[], X[][], X[][][], and so on.  The
62 * easiest way to deal with that is to create the full name once and then
63 * subtract pieces off.  Besides, we want to start with the outermost
64 * piece and work our way in.
65 */
66static void Dalvik_java_lang_reflect_Array_createMultiArray(const u4* args,
67    JValue* pResult)
68{
69    ClassObject* elementClass = (ClassObject*) args[0];
70    ArrayObject* dimArray = (ArrayObject*) args[1];
71    ClassObject* arrayClass;
72    ArrayObject* newArray;
73    char* acDescriptor;
74    int numDim, i;
75    int* dimensions;
76
77    ALOGV("createMultiArray: '%s' [%d]",
78        elementClass->descriptor, dimArray->length);
79
80    assert(elementClass != NULL);       // verified by caller
81
82    /*
83     * Verify dimensions.
84     *
85     * The caller is responsible for verifying that "dimArray" is non-null
86     * and has a length > 0 and <= 255.
87     */
88    assert(dimArray != NULL);           // verified by caller
89    numDim = dimArray->length;
90    assert(numDim > 0 && numDim <= 255);
91
92    dimensions = (int*)(void*)dimArray->contents;
93    for (i = 0; i < numDim; i++) {
94        if (dimensions[i] < 0) {
95            dvmThrowNegativeArraySizeException(dimensions[i]);
96            RETURN_VOID();
97        }
98        LOGVV("DIM %d: %d", i, dimensions[i]);
99    }
100
101    /*
102     * Generate the full name of the array class.
103     */
104    acDescriptor =
105        (char*) malloc(strlen(elementClass->descriptor) + numDim + 1);
106    memset(acDescriptor, '[', numDim);
107
108    LOGVV("#### element name = '%s'", elementClass->descriptor);
109    if (dvmIsPrimitiveClass(elementClass)) {
110        assert(elementClass->primitiveType != PRIM_NOT);
111        acDescriptor[numDim] = dexGetPrimitiveTypeDescriptorChar(elementClass->primitiveType);
112        acDescriptor[numDim+1] = '\0';
113    } else {
114        strcpy(acDescriptor+numDim, elementClass->descriptor);
115    }
116    LOGVV("#### array name = '%s'", acDescriptor);
117
118    /*
119     * Find/generate the array class.
120     */
121    arrayClass = dvmFindArrayClass(acDescriptor, elementClass->classLoader);
122    if (arrayClass == NULL) {
123        ALOGW("Unable to find or generate array class '%s'", acDescriptor);
124        assert(dvmCheckException(dvmThreadSelf()));
125        free(acDescriptor);
126        RETURN_VOID();
127    }
128    free(acDescriptor);
129
130    /* create the array */
131    newArray = dvmAllocMultiArray(arrayClass, numDim-1, dimensions);
132    if (newArray == NULL) {
133        assert(dvmCheckException(dvmThreadSelf()));
134        RETURN_VOID();
135    }
136
137    dvmReleaseTrackedAlloc((Object*) newArray, NULL);
138    RETURN_PTR(newArray);
139}
140
141const DalvikNativeMethod dvm_java_lang_reflect_Array[] = {
142    { "createObjectArray",  "(Ljava/lang/Class;I)Ljava/lang/Object;",
143        Dalvik_java_lang_reflect_Array_createObjectArray },
144    { "createMultiArray",   "(Ljava/lang/Class;[I)Ljava/lang/Object;",
145        Dalvik_java_lang_reflect_Array_createMultiArray },
146    { NULL, NULL, NULL },
147};
148