1 11 package org.eclipse.jdi.internal; 12 13 14 import java.io.ByteArrayOutputStream ; 15 import java.io.DataInputStream ; 16 import java.io.DataOutputStream ; 17 import java.io.IOException ; 18 import java.util.ArrayList ; 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.List ; 22 import java.util.Map ; 23 24 import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket; 25 import org.eclipse.jdi.internal.jdwp.JdwpID; 26 import org.eclipse.jdi.internal.jdwp.JdwpObjectID; 27 import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket; 28 29 import com.sun.jdi.ArrayType; 30 import com.sun.jdi.ClassNotLoadedException; 31 import com.sun.jdi.Field; 32 import com.sun.jdi.IncompatibleThreadStateException; 33 import com.sun.jdi.InternalException; 34 import com.sun.jdi.InvalidTypeException; 35 import com.sun.jdi.InvocationException; 36 import com.sun.jdi.Method; 37 import com.sun.jdi.ObjectCollectedException; 38 import com.sun.jdi.ObjectReference; 39 import com.sun.jdi.ReferenceType; 40 import com.sun.jdi.ThreadReference; 41 import com.sun.jdi.Type; 42 import com.sun.jdi.VMDisconnectedException; 43 import com.sun.jdi.Value; 44 45 51 public class ObjectReferenceImpl extends ValueImpl implements ObjectReference { 52 53 public static final byte tag = JdwpID.OBJECT_TAG; 54 55 56 private JdwpObjectID fObjectID; 57 61 private ReferenceType fReferenceType; 62 63 66 public ObjectReferenceImpl(VirtualMachineImpl vmImpl, JdwpObjectID objectID) { 67 this("ObjectReference", vmImpl, objectID); } 69 70 73 public ObjectReferenceImpl(String description, VirtualMachineImpl vmImpl, JdwpObjectID objectID) { 74 super(description, vmImpl); 75 fObjectID = objectID; 76 } 77 78 81 public byte getTag() { 82 return tag; 83 } 84 85 88 public JdwpObjectID getObjectID() { 89 return fObjectID; 90 } 91 92 95 public void disableCollection() { 96 initJdwpRequest(); 97 try { 98 JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.OR_DISABLE_COLLECTION, this); 99 defaultReplyErrorHandler(replyPacket.errorCode()); 100 } finally { 101 handledJdwpRequest(); 102 } 103 } 104 105 108 public void enableCollection() { 109 initJdwpRequest(); 110 try { 111 JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.OR_ENABLE_COLLECTION, this); 112 defaultReplyErrorHandler(replyPacket.errorCode()); 113 } finally { 114 handledJdwpRequest(); 115 } 116 } 117 118 121 private class MonitorInfo { 122 ThreadReferenceImpl owner; 123 int entryCount; 124 ArrayList waiters; 125 } 126 127 130 private MonitorInfo monitorInfo() throws IncompatibleThreadStateException { 131 if (!virtualMachine().canGetMonitorInfo()) { 132 throw new UnsupportedOperationException (); 133 } 134 initJdwpRequest(); 136 try { 137 JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.OR_MONITOR_INFO, this); 138 switch (replyPacket.errorCode()) { 139 case JdwpReplyPacket.INVALID_THREAD: 140 throw new IncompatibleThreadStateException(); 141 case JdwpReplyPacket.THREAD_NOT_SUSPENDED: 142 throw new IncompatibleThreadStateException(); 143 } 144 145 defaultReplyErrorHandler(replyPacket.errorCode()); 146 147 DataInputStream replyData = replyPacket.dataInStream(); 148 MonitorInfo result = new MonitorInfo(); 149 result.owner = ThreadReferenceImpl.read(this, replyData); 150 result.entryCount = readInt("entry count", replyData); int nrOfWaiters = readInt("nr of waiters", replyData); result.waiters = new ArrayList (nrOfWaiters); 153 for (int i = 0; i < nrOfWaiters; i++) 154 result.waiters.add(ThreadReferenceImpl.read(this, replyData)); 155 return result; 156 } catch (IOException e) { 157 defaultIOExceptionHandler(e); 158 return null; 159 } finally { 160 handledJdwpRequest(); 161 } 162 } 163 164 167 public ThreadReference owningThread() throws IncompatibleThreadStateException { 168 return monitorInfo().owner; 169 } 170 171 174 public int entryCount() throws IncompatibleThreadStateException { 175 return monitorInfo().entryCount; 176 } 177 178 181 public List waitingThreads() throws IncompatibleThreadStateException { 182 return monitorInfo().waiters; 183 } 184 185 188 public Value getValue(Field field) { 189 ArrayList list = new ArrayList (1); 190 list.add(field); 191 return (ValueImpl)getValues(list).get(field); 192 } 193 194 201 public List referringObjects(long maxReferrers) throws UnsupportedOperationException , IllegalArgumentException { 202 try { 203 int max = (int)maxReferrers; 204 if (maxReferrers >= Integer.MAX_VALUE) { 205 max = Integer.MAX_VALUE; 206 } 207 ByteArrayOutputStream outBytes = new ByteArrayOutputStream (); 208 DataOutputStream outData = new DataOutputStream (outBytes); 209 this.getObjectID().write(outData); 210 writeInt(max, "max referrers", outData); 212 JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.OR_REFERRING_OBJECTS, outBytes); 213 switch(replyPacket.errorCode()) { 214 case JdwpReplyPacket.NOT_IMPLEMENTED: 215 throw new UnsupportedOperationException (JDIMessages.ReferenceTypeImpl_27); 216 case JdwpReplyPacket.ILLEGAL_ARGUMENT: 217 throw new IllegalArgumentException (JDIMessages.ReferenceTypeImpl_26); 218 case JdwpReplyPacket.INVALID_OBJECT: 219 throw new ObjectCollectedException(JDIMessages.ObjectReferenceImpl_object_not_known); 220 case JdwpReplyPacket.VM_DEAD: 221 throw new VMDisconnectedException(JDIMessages.vm_dead); 222 } 223 defaultReplyErrorHandler(replyPacket.errorCode()); 224 225 DataInputStream replyData = replyPacket.dataInStream(); 226 int elements = readInt("elements", replyData); if(max > 0 && elements > max) { 228 elements = max; 229 } 230 ArrayList list = new ArrayList (); 231 for(int i = 0; i < elements; i++) { 232 list.add(ValueImpl.readWithTag(this, replyData)); 233 } 234 return list; 235 } 236 catch(IOException e) { 237 defaultIOExceptionHandler(e); 238 return null; 239 } finally { 240 handledJdwpRequest(); 241 } 242 } 243 244 247 public Map getValues(List allFields) { 248 if (allFields.isEmpty()) { 250 return new HashMap (); 251 } 252 initJdwpRequest(); 254 try { 255 ByteArrayOutputStream outBytes = new ByteArrayOutputStream (); 256 DataOutputStream outData = new DataOutputStream (outBytes); 257 258 262 List staticFields = new ArrayList (); 263 List nonStaticFields = new ArrayList (); 264 265 int allFieldsSize = allFields.size(); 267 for (int i = 0; i < allFieldsSize; i++) { 268 FieldImpl field = (FieldImpl)allFields.get(i); 269 checkVM(field); 270 if (field.isStatic()) 271 staticFields.add(field); 272 else 273 nonStaticFields.add(field); 274 } 275 276 Map resultMap; 278 if (staticFields.isEmpty()) { 279 resultMap= new HashMap (); 280 } else { 281 resultMap= referenceType().getValues(staticFields); 282 } 283 284 if (nonStaticFields.isEmpty()) { 286 return resultMap; 287 } 288 int nonStaticFieldsSize = nonStaticFields.size(); 290 write(this, outData); 291 writeInt(nonStaticFieldsSize, "size", outData); for (int i = 0; i < nonStaticFieldsSize; i++) { 293 FieldImpl field = (FieldImpl)nonStaticFields.get(i); 294 field.write(this, outData); 295 } 296 297 JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.OR_GET_VALUES, outBytes); 298 defaultReplyErrorHandler(replyPacket.errorCode()); 299 300 DataInputStream replyData = replyPacket.dataInStream(); 301 int nrOfElements = readInt("elements", replyData); if (nrOfElements != nonStaticFieldsSize) 303 throw new InternalError (JDIMessages.ObjectReferenceImpl_Retrieved_a_different_number_of_values_from_the_VM_than_requested_1); 304 305 for (int i = 0; i < nrOfElements; i++) { 306 resultMap.put(nonStaticFields.get(i), ValueImpl.readWithTag(this, replyData)); 307 } 308 return resultMap; 309 } catch (IOException e) { 310 defaultIOExceptionHandler(e); 311 return null; 312 } finally { 313 handledJdwpRequest(); 314 } 315 } 316 317 320 public int hashCode() { 321 return fObjectID.hashCode(); 322 } 323 324 328 public boolean equals(Object object) { 329 330 return object != null 331 && object.getClass().equals(this.getClass()) 332 && fObjectID.equals(((ObjectReferenceImpl)object).fObjectID) 333 && virtualMachine().equals(((MirrorImpl)object).virtualMachine()); 334 } 335 336 339 private int optionsToJdwpOptions(int options) { 340 int jdwpOptions = 0; 341 if ((options & INVOKE_SINGLE_THREADED) != 0) { 342 jdwpOptions |= MethodImpl.INVOKE_SINGLE_THREADED_JDWP; 343 } 344 if ((options & INVOKE_NONVIRTUAL) != 0) { 345 jdwpOptions |= MethodImpl.INVOKE_NONVIRTUAL_JDWP; 346 } 347 return jdwpOptions; 348 } 349 350 354 public Value invokeMethod(ThreadReference thread, Method method, List arguments, int options) throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException { 355 checkVM(thread); 356 checkVM(method); 357 ThreadReferenceImpl threadImpl = (ThreadReferenceImpl)thread; 358 MethodImpl methodImpl = (MethodImpl)method; 359 360 if (!isAValidMethod(method)) 362 throw new IllegalArgumentException (JDIMessages.ObjectReferenceImpl_Class_does_not_contain_given_method_2); 363 if (method.argumentTypeNames().size() != arguments.size()) 364 throw new IllegalArgumentException (JDIMessages.ObjectReferenceImpl_Number_of_arguments_doesn__t_match_3); 365 if (method.isConstructor() || method.isStaticInitializer()) 366 throw new IllegalArgumentException (JDIMessages.ObjectReferenceImpl_Method_is_constructor_or_intitializer_4); 367 if ((options & INVOKE_NONVIRTUAL) != 0 && method.isAbstract()) 368 throw new IllegalArgumentException (JDIMessages.ObjectReferenceImpl_Method_is_abstract_and_can_therefore_not_be_invoked_nonvirtual_5); 369 370 List checkedArguments= ValueImpl.checkValues(arguments, method.argumentTypes(), virtualMachineImpl()); 372 373 initJdwpRequest(); 374 try { 375 ByteArrayOutputStream outBytes = new ByteArrayOutputStream (); 376 DataOutputStream outData = new DataOutputStream (outBytes); 377 write(this, outData); 378 threadImpl.write(this, outData); 379 ((ReferenceTypeImpl)referenceType()).write(this, outData); 380 methodImpl.write(this, outData); 381 382 writeInt(checkedArguments.size(), "size", outData); Iterator iter = checkedArguments.iterator(); 384 while(iter.hasNext()) { 385 ValueImpl elt = (ValueImpl)iter.next(); 386 if (elt != null) { 387 elt.writeWithTag(this, outData); 388 } else { 389 ValueImpl.writeNullWithTag(this, outData); 390 } 391 } 392 393 writeInt(optionsToJdwpOptions(options),"options", MethodImpl.getInvokeOptions(), outData); 395 JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.OR_INVOKE_METHOD, outBytes); 396 switch (replyPacket.errorCode()) { 397 case JdwpReplyPacket.TYPE_MISMATCH: 398 throw new InvalidTypeException(); 399 case JdwpReplyPacket.INVALID_CLASS: 400 throw new ClassNotLoadedException(JDIMessages.ObjectReferenceImpl_One_of_the_arguments_of_ObjectReference_invokeMethod___6); 401 case JdwpReplyPacket.INVALID_THREAD: 402 throw new IncompatibleThreadStateException(); 403 case JdwpReplyPacket.THREAD_NOT_SUSPENDED: 404 throw new IncompatibleThreadStateException(); 405 case JdwpReplyPacket.INVALID_TYPESTATE: 406 throw new IncompatibleThreadStateException(); 407 } 408 defaultReplyErrorHandler(replyPacket.errorCode()); 409 DataInputStream replyData = replyPacket.dataInStream(); 410 ValueImpl value = ValueImpl.readWithTag(this, replyData); 411 ObjectReferenceImpl exception = ObjectReferenceImpl.readObjectRefWithTag(this, replyData); 412 if (exception != null) 413 throw new InvocationException(exception); 414 return value; 415 } catch (IOException e) { 416 defaultIOExceptionHandler(e); 417 return null; 418 } finally { 419 handledJdwpRequest(); 420 } 421 } 422 423 private boolean isAValidMethod(Method method) { 424 ReferenceType refType= referenceType(); 425 if (refType instanceof ArrayType) { 426 return "java.lang.Object".equals(method.declaringType().name()); } 429 return refType.allMethods().contains(method); 430 } 431 432 435 public boolean isCollected() { 436 initJdwpRequest(); 438 try { 439 JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.OR_IS_COLLECTED, this); 440 switch (replyPacket.errorCode()) { 441 case JdwpReplyPacket.INVALID_OBJECT: 442 return true; 443 case JdwpReplyPacket.NOT_IMPLEMENTED: 444 try { 447 referenceType(); 448 } catch (ObjectCollectedException e) { 449 return true; 450 } 451 return false; 452 default: 453 defaultReplyErrorHandler(replyPacket.errorCode()); 454 break; 455 } 456 DataInputStream replyData = replyPacket.dataInStream(); 457 boolean result = readBoolean("is collected", replyData); return result; 459 } catch (IOException e) { 460 defaultIOExceptionHandler(e); 461 return false; 462 } finally { 463 handledJdwpRequest(); 464 } 465 } 466 467 468 471 public ReferenceType referenceType() { 472 if (fReferenceType != null) { 473 return fReferenceType; 474 } 475 initJdwpRequest(); 476 try { 477 JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.OR_REFERENCE_TYPE, this); 478 defaultReplyErrorHandler(replyPacket.errorCode()); 479 DataInputStream replyData = replyPacket.dataInStream(); 480 fReferenceType= ReferenceTypeImpl.readWithTypeTag(this, replyData); 481 return fReferenceType; 482 } catch (IOException e) { 483 defaultIOExceptionHandler(e); 484 return null; 485 } finally { 486 handledJdwpRequest(); 487 } 488 } 489 490 493 public Type type() { 494 return referenceType(); 495 } 496 497 500 public void setValue(Field field, Value value) throws InvalidTypeException, ClassNotLoadedException { 501 initJdwpRequest(); 503 try { 504 ByteArrayOutputStream outBytes = new ByteArrayOutputStream (); 505 DataOutputStream outData = new DataOutputStream (outBytes); 506 write(this, outData); 507 writeInt(1, "size", outData); checkVM(field); 509 ((FieldImpl)field).write(this, outData); 510 511 ValueImpl checkedValue= ValueImpl.checkValue(value, field.type(), virtualMachineImpl()); 513 514 if (checkedValue != null) { 515 checkedValue.write(this, outData); 516 } else { 517 ValueImpl.writeNull(this, outData); 518 } 519 520 JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.OR_SET_VALUES, outBytes); 521 switch (replyPacket.errorCode()) { 522 case JdwpReplyPacket.TYPE_MISMATCH: 523 throw new InvalidTypeException(); 524 case JdwpReplyPacket.INVALID_CLASS: 525 throw new ClassNotLoadedException(referenceType().name()); 526 } 527 defaultReplyErrorHandler(replyPacket.errorCode()); 528 } catch (IOException e) { 529 defaultIOExceptionHandler(e); 530 } finally { 531 handledJdwpRequest(); 532 } 533 } 534 535 538 public long uniqueID() { 539 return fObjectID.value(); 540 } 541 542 545 public String idString() { 546 return "(id=" + fObjectID + ")"; } 548 549 552 public String toString() { 553 try { 554 return type().toString() + " " + idString(); } catch (ObjectCollectedException e) { 556 return JDIMessages.ObjectReferenceImpl__Garbage_Collected__ObjectReference__8 + idString(); 557 } catch (Exception e) { 558 return fDescription; 559 } 560 } 561 562 565 public static ObjectReferenceImpl readObjectRefWithoutTag(MirrorImpl target, DataInputStream in) throws IOException { 566 VirtualMachineImpl vmImpl = target.virtualMachineImpl(); 567 JdwpObjectID ID = new JdwpObjectID(vmImpl); 568 ID.read(in); 569 if (target.fVerboseWriter != null) 570 target.fVerboseWriter.println("objectReference", ID.value()); 572 if (ID.isNull()) 573 return null; 574 575 ObjectReferenceImpl mirror = new ObjectReferenceImpl(vmImpl, ID); 576 return mirror; 577 } 578 579 582 public static ObjectReferenceImpl readObjectRefWithTag(MirrorImpl target, DataInputStream in) throws IOException { 583 byte objectTag = target.readByte("object tag", JdwpID.tagMap(), in); switch (objectTag) { 585 case 0: 586 return null; 587 case ObjectReferenceImpl.tag: 588 return ObjectReferenceImpl.readObjectRefWithoutTag(target, in); 589 case ArrayReferenceImpl.tag: 590 return ArrayReferenceImpl.read(target, in); 591 case ClassLoaderReferenceImpl.tag: 592 return ClassLoaderReferenceImpl.read(target, in); 593 case ClassObjectReferenceImpl.tag: 594 return ClassObjectReferenceImpl.read(target, in); 595 case StringReferenceImpl.tag: 596 return StringReferenceImpl.read(target, in); 597 case ThreadGroupReferenceImpl.tag: 598 return ThreadGroupReferenceImpl.read(target, in); 599 case ThreadReferenceImpl.tag: 600 return ThreadReferenceImpl.read(target, in); 601 } 602 throw new InternalException(JDIMessages.ObjectReferenceImpl_Invalid_ObjectID_tag_encountered___9 + objectTag); 603 } 604 605 608 public void write(MirrorImpl target, DataOutputStream out) throws IOException { 609 fObjectID.write(out); 610 if (target.fVerboseWriter != null) 611 target.fVerboseWriter.println("objectReference", fObjectID.value()); } 613 } 614 | Popular Tags |