• 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.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