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 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 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 = NULL; 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 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 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};