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 "util.h" 27 #include "ObjectReferenceImpl.h" 28 #include "commonRef.h" 29 #include "inStream.h" 30 #include "outStream.h" 31 32 static jboolean 33 referenceType(PacketInputStream *in, PacketOutputStream *out) 34 { 35 JNIEnv *env; 36 jobject object; 37 38 env = getEnv(); 39 40 object = inStream_readObjectRef(env, in); 41 if (inStream_error(in)) { 42 return JNI_TRUE; 43 } 44 45 WITH_LOCAL_REFS(env, 1) { 46 47 jbyte tag; 48 jclass clazz; 49 50 clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object); 51 tag = referenceTypeTag(clazz); 52 53 (void)outStream_writeByte(out, tag); 54 (void)outStream_writeObjectRef(env, out, clazz); 55 56 } END_WITH_LOCAL_REFS(env); 57 58 return JNI_TRUE; 59 } 60 61 static jboolean 62 getValues(PacketInputStream *in, PacketOutputStream *out) 63 { 64 sharedGetFieldValues(in, out, JNI_FALSE); 65 return JNI_TRUE; 66 } 67 68 69 static jvmtiError 70 readFieldValue(JNIEnv *env, PacketInputStream *in, jclass clazz, 71 jobject object, jfieldID field, char *signature) 72 { 73 jvalue value; 74 jvmtiError error; 75 76 switch (signature[0]) { 77 case JDWP_TAG(ARRAY): 78 case JDWP_TAG(OBJECT): 79 value.l = inStream_readObjectRef(env, in); 80 JNI_FUNC_PTR(env,SetObjectField)(env, object, field, value.l); 81 break; 82 83 case JDWP_TAG(BYTE): 84 value.b = inStream_readByte(in); 85 JNI_FUNC_PTR(env,SetByteField)(env, object, field, value.b); 86 break; 87 88 case JDWP_TAG(CHAR): 89 value.c = inStream_readChar(in); 90 JNI_FUNC_PTR(env,SetCharField)(env, object, field, value.c); 91 break; 92 93 case JDWP_TAG(FLOAT): 94 value.f = inStream_readFloat(in); 95 JNI_FUNC_PTR(env,SetFloatField)(env, object, field, value.f); 96 break; 97 98 case JDWP_TAG(DOUBLE): 99 value.d = inStream_readDouble(in); 100 JNI_FUNC_PTR(env,SetDoubleField)(env, object, field, value.d); 101 break; 102 103 case JDWP_TAG(INT): 104 value.i = inStream_readInt(in); 105 JNI_FUNC_PTR(env,SetIntField)(env, object, field, value.i); 106 break; 107 108 case JDWP_TAG(LONG): 109 value.j = inStream_readLong(in); 110 JNI_FUNC_PTR(env,SetLongField)(env, object, field, value.j); 111 break; 112 113 case JDWP_TAG(SHORT): 114 value.s = inStream_readShort(in); 115 JNI_FUNC_PTR(env,SetShortField)(env, object, field, value.s); 116 break; 117 118 case JDWP_TAG(BOOLEAN): 119 value.z = inStream_readBoolean(in); 120 JNI_FUNC_PTR(env,SetBooleanField)(env, object, field, value.z); 121 break; 122 } 123 124 error = JVMTI_ERROR_NONE; 125 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) { 126 error = AGENT_ERROR_JNI_EXCEPTION; 127 } 128 129 return error; 130 } 131 132 static jboolean 133 setValues(PacketInputStream *in, PacketOutputStream *out) 134 { 135 JNIEnv *env; 136 jint count; 137 jvmtiError error; 138 jobject object; 139 140 env = getEnv(); 141 142 object = inStream_readObjectRef(env, in); 143 if (inStream_error(in)) { 144 return JNI_TRUE; 145 } 146 count = inStream_readInt(in); 147 if (inStream_error(in)) { 148 return JNI_TRUE; 149 } 150 151 error = JVMTI_ERROR_NONE; 152 153 WITH_LOCAL_REFS(env, count + 1) { 154 155 jclass clazz; 156 157 clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object); 158 159 if (clazz != NULL ) { 160 161 int i; 162 163 for (i = 0; (i < count) && !inStream_error(in); i++) { 164 165 jfieldID field; 166 char *signature = NULL; 167 168 field = inStream_readFieldID(in); 169 if (inStream_error(in)) 170 break; 171 172 error = fieldSignature(clazz, field, NULL, &signature, NULL); 173 if (error != JVMTI_ERROR_NONE) { 174 break; 175 } 176 177 error = readFieldValue(env, in, clazz, object, field, signature); 178 jvmtiDeallocate(signature); 179 180 if (error != JVMTI_ERROR_NONE) { 181 break; 182 } 183 } 184 } 185 186 if (error != JVMTI_ERROR_NONE) { 187 outStream_setError(out, map2jdwpError(error)); 188 } 189 190 } END_WITH_LOCAL_REFS(env); 191 192 return JNI_TRUE; 193 } 194 195 static jboolean 196 monitorInfo(PacketInputStream *in, PacketOutputStream *out) 197 { 198 JNIEnv *env; 199 jobject object; 200 201 env = getEnv(); 202 203 object = inStream_readObjectRef(env, in); 204 if (inStream_error(in)) { 205 return JNI_TRUE; 206 } 207 208 WITH_LOCAL_REFS(env, 1) { 209 210 jvmtiError error; 211 jvmtiMonitorUsage info; 212 213 (void)memset(&info, 0, sizeof(info)); 214 error = JVMTI_FUNC_PTR(gdata->jvmti,GetObjectMonitorUsage) 215 (gdata->jvmti, object, &info); 216 if (error != JVMTI_ERROR_NONE) { 217 outStream_setError(out, map2jdwpError(error)); 218 } else { 219 int i; 220 (void)outStream_writeObjectRef(env, out, info.owner); 221 (void)outStream_writeInt(out, info.entry_count); 222 (void)outStream_writeInt(out, info.waiter_count); 223 for (i = 0; i < info.waiter_count; i++) { 224 (void)outStream_writeObjectRef(env, out, info.waiters[i]); 225 } 226 } 227 228 if (info.waiters != NULL ) 229 jvmtiDeallocate(info.waiters); 230 231 } END_WITH_LOCAL_REFS(env); 232 233 return JNI_TRUE; 234 } 235 236 static jboolean 237 invokeInstance(PacketInputStream *in, PacketOutputStream *out) 238 { 239 return sharedInvoke(in, out); 240 } 241 242 static jboolean 243 disableCollection(PacketInputStream *in, PacketOutputStream *out) 244 { 245 jlong id; 246 jvmtiError error; 247 248 id = inStream_readObjectID(in); 249 if (inStream_error(in)) { 250 return JNI_TRUE; 251 } 252 253 error = commonRef_pin(id); 254 if (error != JVMTI_ERROR_NONE) { 255 outStream_setError(out, map2jdwpError(error)); 256 } 257 258 return JNI_TRUE; 259 } 260 261 static jboolean 262 enableCollection(PacketInputStream *in, PacketOutputStream *out) 263 { 264 jvmtiError error; 265 jlong id; 266 267 id = inStream_readObjectID(in); 268 if (inStream_error(in)) { 269 return JNI_TRUE; 270 } 271 272 error = commonRef_unpin(id); 273 if (error != JVMTI_ERROR_NONE) { 274 outStream_setError(out, map2jdwpError(error)); 275 } 276 277 return JNI_TRUE; 278 } 279 280 static jboolean 281 isCollected(PacketInputStream *in, PacketOutputStream *out) 282 { 283 jobject ref; 284 jlong id; 285 JNIEnv *env; 286 287 env = getEnv(); 288 id = inStream_readObjectID(in); 289 if (inStream_error(in)) { 290 return JNI_TRUE; 291 } 292 293 if (id == NULL_OBJECT_ID) { 294 outStream_setError(out, JDWP_ERROR(INVALID_OBJECT)); 295 return JNI_TRUE; 296 } 297 298 ref = commonRef_idToRef(env, id); 299 (void)outStream_writeBoolean(out, (jboolean)(ref == NULL)); 300 301 commonRef_idToRef_delete(env, ref); 302 303 return JNI_TRUE; 304 } 305 306 307 static jboolean 308 referringObjects(PacketInputStream *in, PacketOutputStream *out) 309 { 310 jobject object; 311 jint maxReferrers; 312 JNIEnv *env; 313 314 env = getEnv(); 315 316 if (gdata->vmDead) { 317 outStream_setError(out, JDWP_ERROR(VM_DEAD)); 318 return JNI_TRUE; 319 } 320 321 object = inStream_readObjectRef(env,in); 322 if (inStream_error(in)) { 323 return JNI_TRUE; 324 } 325 326 maxReferrers = inStream_readInt(in); 327 if (inStream_error(in)) { 328 return JNI_TRUE; 329 } 330 331 WITH_LOCAL_REFS(env, 1) { 332 jvmtiError error; 333 ObjectBatch referrerBatch; 334 335 error = objectReferrers(object, &referrerBatch, maxReferrers); 336 if (error != JVMTI_ERROR_NONE) { 337 outStream_setError(out, map2jdwpError(error)); 338 } else { 339 int kk; 340 341 (void)outStream_writeInt(out, referrerBatch.count); 342 for (kk = 0; kk < referrerBatch.count; kk++) { 343 jobject ref; 344 345 ref = referrerBatch.objects[kk]; 346 (void)outStream_writeByte(out, specificTypeKey(env, ref)); 347 (void)outStream_writeObjectRef(env, out, ref); 348 } 349 jvmtiDeallocate(referrerBatch.objects); 350 } 351 } END_WITH_LOCAL_REFS(env); 352 return JNI_TRUE; 353 } 354 355 void *ObjectReference_Cmds[] = { (void *)10 356 ,(void *)referenceType 357 ,(void *)getValues 358 ,(void *)setValues 359 ,(void *)NULL /* no longer used */ 360 ,(void *)monitorInfo 361 ,(void *)invokeInstance 362 ,(void *)disableCollection 363 ,(void *)enableCollection 364 ,(void *)isCollected 365 ,(void *)referringObjects 366 }; 367