Home | History | Annotate | Download | only in native
      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  */
     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  */
     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