1 /*
2 * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "ArrayTypeImpl.h"
27 #include "util.h"
28 #include "inStream.h"
29 #include "outStream.h"
30
31 /*
32 * Determine the component class by looking thru all classes for
33 * one that has the signature of the component and the same class loadeer
34 * as the array. See JVM spec 5.3.3:
35 * If the component type is a reference type, C is marked as having
36 * been defined by the defining class loader of the component type.
37 */
38 static jdwpError
getComponentClass(JNIEnv * env,jclass arrayClass,char * componentSignature,jclass * componentClassPtr)39 getComponentClass(JNIEnv *env, jclass arrayClass, char *componentSignature,
40 jclass *componentClassPtr)
41 {
42 jobject arrayClassLoader;
43 jclass *classes;
44 jint count;
45 jclass componentClass = NULL;
46 jdwpError serror;
47 jvmtiError error;
48
49 serror = JDWP_ERROR(NONE);
50
51 error = classLoader(arrayClass, &arrayClassLoader);
52 if (error != JVMTI_ERROR_NONE) {
53 return map2jdwpError(error);
54 }
55
56 error = allLoadedClasses(&classes, &count);
57 if (error != JVMTI_ERROR_NONE) {
58 serror = map2jdwpError(error);
59 } else {
60 int i;
61 for (i = 0; (i < count) && (componentClass == NULL); i++) {
62 char *signature = NULL;
63 jclass clazz = classes[i];
64 jboolean match;
65 jvmtiError error;
66
67 /* signature must match */
68 error = classSignature(clazz, &signature, NULL);
69 if (error != JVMTI_ERROR_NONE) {
70 serror = map2jdwpError(error);
71 break;
72 }
73 match = strcmp(signature, componentSignature) == 0;
74 jvmtiDeallocate(signature);
75
76 /* if signature matches, get class loader to check if
77 * it matches
78 */
79 if (match) {
80 jobject loader;
81 error = classLoader(clazz, &loader);
82 if (error != JVMTI_ERROR_NONE) {
83 return map2jdwpError(error);
84 }
85 match = isSameObject(env, loader, arrayClassLoader);
86 }
87
88 if (match) {
89 componentClass = clazz;
90 }
91 }
92 jvmtiDeallocate(classes);
93
94 *componentClassPtr = componentClass;
95 }
96
97 if (serror == JDWP_ERROR(NONE) && componentClass == NULL) {
98 /* per JVM spec, component class is always loaded
99 * before array class, so this should never occur.
100 */
101 serror = JDWP_ERROR(NOT_FOUND);
102 }
103
104 return serror;
105 }
106
107 static void
writeNewObjectArray(JNIEnv * env,PacketOutputStream * out,jclass arrayClass,jint size,char * componentSignature)108 writeNewObjectArray(JNIEnv *env, PacketOutputStream *out,
109 jclass arrayClass, jint size, char *componentSignature)
110 {
111
112 WITH_LOCAL_REFS(env, 1) {
113
114 jarray array;
115 jclass componentClass;
116 jdwpError serror;
117
118 serror = getComponentClass(env, arrayClass,
119 componentSignature, &componentClass);
120 if (serror != JDWP_ERROR(NONE)) {
121 outStream_setError(out, serror);
122 } else {
123
124 array = JNI_FUNC_PTR(env,NewObjectArray)(env, size, componentClass, 0);
125 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
126 JNI_FUNC_PTR(env,ExceptionClear)(env);
127 array = NULL;
128 }
129
130 if (array == NULL) {
131 outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
132 } else {
133 (void)outStream_writeByte(out, specificTypeKey(env, array));
134 (void)outStream_writeObjectRef(env, out, array);
135 }
136
137 }
138
139 } END_WITH_LOCAL_REFS(env);
140 }
141
142 static void
writeNewPrimitiveArray(JNIEnv * env,PacketOutputStream * out,jclass arrayClass,jint size,char * componentSignature)143 writeNewPrimitiveArray(JNIEnv *env, PacketOutputStream *out,
144 jclass arrayClass, jint size, char *componentSignature)
145 {
146
147 WITH_LOCAL_REFS(env, 1) {
148
149 jarray array = NULL;
150
151 switch (componentSignature[0]) {
152 case JDWP_TAG(BYTE):
153 array = JNI_FUNC_PTR(env,NewByteArray)(env, size);
154 break;
155
156 case JDWP_TAG(CHAR):
157 array = JNI_FUNC_PTR(env,NewCharArray)(env, size);
158 break;
159
160 case JDWP_TAG(FLOAT):
161 array = JNI_FUNC_PTR(env,NewFloatArray)(env, size);
162 break;
163
164 case JDWP_TAG(DOUBLE):
165 array = JNI_FUNC_PTR(env,NewDoubleArray)(env, size);
166 break;
167
168 case JDWP_TAG(INT):
169 array = JNI_FUNC_PTR(env,NewIntArray)(env, size);
170 break;
171
172 case JDWP_TAG(LONG):
173 array = JNI_FUNC_PTR(env,NewLongArray)(env, size);
174 break;
175
176 case JDWP_TAG(SHORT):
177 array = JNI_FUNC_PTR(env,NewShortArray)(env, size);
178 break;
179
180 case JDWP_TAG(BOOLEAN):
181 array = JNI_FUNC_PTR(env,NewBooleanArray)(env, size);
182 break;
183
184 default:
185 outStream_setError(out, JDWP_ERROR(TYPE_MISMATCH));
186 break;
187 }
188
189 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
190 JNI_FUNC_PTR(env,ExceptionClear)(env);
191 array = NULL;
192 }
193
194 if (array == NULL) {
195 outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
196 } else {
197 (void)outStream_writeByte(out, specificTypeKey(env, array));
198 (void)outStream_writeObjectRef(env, out, array);
199 }
200
201 } END_WITH_LOCAL_REFS(env);
202 }
203
204 static jboolean
newInstance(PacketInputStream * in,PacketOutputStream * out)205 newInstance(PacketInputStream *in, PacketOutputStream *out)
206 {
207 JNIEnv *env;
208 char *signature = NULL;
209 char *componentSignature;
210 jclass arrayClass;
211 jint size;
212 jvmtiError error;
213
214 env = getEnv();
215
216 arrayClass = inStream_readClassRef(env, in);
217 if (inStream_error(in)) {
218 return JNI_TRUE;
219 }
220 size = inStream_readInt(in);
221 if (inStream_error(in)) {
222 return JNI_TRUE;
223 }
224
225 error = classSignature(arrayClass, &signature, NULL);
226 if ( error != JVMTI_ERROR_NONE ) {
227 outStream_setError(out, map2jdwpError(error));
228 return JNI_FALSE;
229 }
230 componentSignature = &signature[1];
231
232 if ((componentSignature[0] == JDWP_TAG(OBJECT)) ||
233 (componentSignature[0] == JDWP_TAG(ARRAY))) {
234 writeNewObjectArray(env, out, arrayClass, size, componentSignature);
235 } else {
236 writeNewPrimitiveArray(env, out, arrayClass, size, componentSignature);
237 }
238
239 jvmtiDeallocate(signature);
240 return JNI_TRUE;
241 }
242
243 void *ArrayType_Cmds[] = { (void *)0x1
244 ,(void *)newInstance};
245