blob: b1ae682c8c0677981668619e54fa9ae6d3da19e5 [file] [log] [blame]
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001/*
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#include "jni_internal.h"
18#include "class_linker.h"
19#include "object.h"
20
21#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
22
23namespace art {
24
25namespace {
26
27
28// Recursively create an array with multiple dimensions. Elements may be
29// Objects or primitive types.
30//
31// The dimension we're creating is in dimensions[0], so when we recurse
32// we advance the pointer.
33Array* CreateMultiArray(Class* array_class, int current_dimension, IntArray* dimensions) {
34 int32_t array_length = dimensions->Get(current_dimension++);
35 Array* new_array = Array::Alloc(array_class, array_length);
36 if (new_array == NULL) {
37 CHECK(Thread::Current()->IsExceptionPending());
38 return NULL;
39 }
40 if (current_dimension == dimensions->GetLength()) {
41 return new_array;
42 }
43
44 if (!array_class->GetComponentType()->IsArrayClass()) {
45 // TODO: throw an exception, not relying on class_linker->FindClass to throw.
46 // old code assumed this but if you recurse from "[Foo" to "Foo" to "oo",
47 // you shouldn't assume there isn't a class "oo".
48 }
49 std::string sub_array_descriptor(array_class->GetDescriptor()->ToModifiedUtf8(), 1);
50 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
51 Class* sub_array_class = class_linker->FindClass(sub_array_descriptor,
52 array_class->GetClassLoader());
53 if (sub_array_class == NULL) {
54 CHECK(Thread::Current()->IsExceptionPending());
55 return NULL;
56 }
57 DCHECK(sub_array_class->IsArrayClass());
58 // Create a new sub-array in every element of the array.
59 ObjectArray<Array>* object_array = new_array->AsObjectArray<Array>();
60 for (int32_t i = 0; i < array_length; i++) {
61 Array* sub_array = CreateMultiArray(sub_array_class, current_dimension, dimensions);
62 if (sub_array == NULL) {
63 CHECK(Thread::Current()->IsExceptionPending());
64 return NULL;
65 }
66 object_array->Set(i, sub_array);
67 }
68 return new_array;
69}
70
71// Create a multi-dimensional array of Objects or primitive types.
72//
73// We have to generate the names for X[], X[][], X[][][], and so on. The
74// easiest way to deal with that is to create the full name once and then
75// subtract pieces off. Besides, we want to start with the outermost
76// piece and work our way in.
77jobject Array_createMultiArray(JNIEnv* env, jclass, jclass javaElementClass, jobject javaDimArray) {
78 DCHECK(javaElementClass != NULL);
79 Class* element_class = Decode<Class*>(env, javaElementClass);
80 DCHECK(element_class->IsClass());
81 DCHECK(javaDimArray != NULL);
82 Object* dimensions_obj = Decode<Class*>(env, javaDimArray);
83 DCHECK(dimensions_obj->IsArrayInstance());
84 DCHECK(dimensions_obj->GetClass()->GetDescriptor()->Equals("[I"));
85 IntArray* dimensions_array = down_cast<IntArray*>(dimensions_obj);
86
87 // Verify dimensions.
88 //
89 // The caller is responsible for verifying that "dimArray" is non-null
90 // and has a length > 0 and <= 255.
91 int num_dimensions = dimensions_array->GetLength();
92 DCHECK_GT(num_dimensions, 0);
93 DCHECK_LE(num_dimensions, 255);
94
95 for (int i = 0; i < num_dimensions; i++) {
96 if (dimensions_array->Get(i) < 0) {
97 UNIMPLEMENTED(FATAL) << "ThrowNegativeArraySizeException(dimensions[i])";
98 return NULL;
99 }
100 }
101
102 // Generate the full name of the array class.
103 std::string descriptor(num_dimensions, '[');
104 descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
105
106 // Find/generate the array class.
107 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
108 Class* array_class = class_linker->FindClass(descriptor, element_class->GetClassLoader());
109 if (array_class == NULL) {
110 CHECK(Thread::Current()->IsExceptionPending());
111 return NULL;
112 }
113 // create the array
114 Array* new_array = CreateMultiArray(array_class, 0, dimensions_array);
115 if (new_array == NULL) {
116 CHECK(Thread::Current()->IsExceptionPending());
117 return NULL;
118 }
119 return AddLocalReference<jobject>(env, new_array);
120}
121
122jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementClass, jint length)
123{
124 DCHECK(javaElementClass != NULL);
125 Class* element_class = Decode<Class*>(env, javaElementClass);
126 if (length < 0) {
127 UNIMPLEMENTED(FATAL) << "ThrowNegativeArraySizeException(length)";
128 return NULL;
129 }
130 std::string descriptor;
131 descriptor += '[';
132 descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
133
134 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
135 Class* array_class = class_linker->FindClass(descriptor, element_class->GetClassLoader());
136 if (array_class == NULL) {
137 CHECK(Thread::Current()->IsExceptionPending());
138 return NULL;
139 }
140 DCHECK(array_class->IsArrayClass());
141 Array* new_array = Array::Alloc(array_class, length);
142 if (new_array == NULL) {
143 CHECK(Thread::Current()->IsExceptionPending());
144 return NULL;
145 }
146 return AddLocalReference<jobject>(env, new_array);
147}
148
149static JNINativeMethod gMethods[] = {
150 NATIVE_METHOD(Array, createMultiArray, "(Ljava/lang/Class;[I)Ljava/lang/Object;"),
151 NATIVE_METHOD(Array, createObjectArray, "(Ljava/lang/Class;I)Ljava/lang/Object;"),
152};
153
154} // namespace
155
156void register_java_lang_reflect_Array(JNIEnv* env) {
157 jniRegisterNativeMethods(env, "java/lang/reflect/Array", gMethods, NELEM(gMethods));
158}
159
160} // namespace art