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 */
Dalvik_java_lang_reflect_Array_createObjectArray(const u4 * args,JValue * pResult)30 static 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 */
Dalvik_java_lang_reflect_Array_createMultiArray(const u4 * args,JValue * pResult)66 static 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
141 const 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