1 /* 2 * Copyright (c) 1998, 2020, 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 package com.sun.tools.jdi; 27 28 import java.util.ArrayList; 29 import java.util.Collection; 30 import java.util.Iterator; 31 import java.util.NoSuchElementException; 32 import java.util.Spliterator; 33 import java.util.Spliterators; 34 35 import com.sun.jdi.Field; 36 import com.sun.jdi.InternalException; 37 import com.sun.jdi.Locatable; 38 import com.sun.jdi.Location; 39 import com.sun.jdi.Method; 40 import com.sun.jdi.ObjectReference; 41 import com.sun.jdi.ReferenceType; 42 import com.sun.jdi.ThreadReference; 43 import com.sun.jdi.VMDisconnectedException; 44 import com.sun.jdi.Value; 45 import com.sun.jdi.VirtualMachine; 46 import com.sun.jdi.event.AccessWatchpointEvent; 47 import com.sun.jdi.event.BreakpointEvent; 48 import com.sun.jdi.event.ClassPrepareEvent; 49 import com.sun.jdi.event.ClassUnloadEvent; 50 import com.sun.jdi.event.Event; 51 import com.sun.jdi.event.EventIterator; 52 import com.sun.jdi.event.EventSet; 53 import com.sun.jdi.event.ExceptionEvent; 54 import com.sun.jdi.event.MethodEntryEvent; 55 import com.sun.jdi.event.MethodExitEvent; 56 import com.sun.jdi.event.ModificationWatchpointEvent; 57 import com.sun.jdi.event.MonitorContendedEnterEvent; 58 import com.sun.jdi.event.MonitorContendedEnteredEvent; 59 import com.sun.jdi.event.MonitorWaitEvent; 60 import com.sun.jdi.event.MonitorWaitedEvent; 61 import com.sun.jdi.event.StepEvent; 62 import com.sun.jdi.event.ThreadDeathEvent; 63 import com.sun.jdi.event.ThreadStartEvent; 64 import com.sun.jdi.event.VMDeathEvent; 65 import com.sun.jdi.event.VMDisconnectEvent; 66 import com.sun.jdi.event.VMStartEvent; 67 import com.sun.jdi.event.WatchpointEvent; 68 import com.sun.jdi.request.EventRequest; 69 70 enum EventDestination {UNKNOWN_EVENT, INTERNAL_EVENT, CLIENT_EVENT}; 71 72 /* 73 * An EventSet is normally created by the transport reader thread when 74 * it reads a JDWP Composite command. The constructor doesn't unpack 75 * the events contained in the Composite command and create EventImpls 76 * for them because that process might involve calling back into the back-end 77 * which should not be done by the transport reader thread. Instead, 78 * the raw bytes of the packet are read and stored in the EventSet. 79 * The EventSet is then added to each EventQueue. When an EventSet is 80 * removed from an EventQueue, the EventSetImpl.build() method is called. 81 * This method reads the packet bytes and creates the actual EventImpl objects. 82 * build() also filters out events for our internal handler and puts them in 83 * their own EventSet. This means that the EventImpls that are in the EventSet 84 * that is on the queues are all for client requests. 85 */ 86 public class EventSetImpl extends ArrayList<Event> implements EventSet { 87 private static final long serialVersionUID = -4857338819787924570L; 88 private VirtualMachineImpl vm; // we implement Mirror 89 private Packet pkt; 90 private byte suspendPolicy; 91 private EventSetImpl internalEventSet; 92 93 public String toString() { 94 String string = "event set, policy:" + suspendPolicy + 95 ", count:" + this.size() + " = {"; 96 boolean first = true; 97 for (Event event : this) { 98 if (!first) { 99 string += ", "; 100 } 101 string += event.toString(); 102 first = false; 103 } 104 string += "}"; 105 return string; 106 } 107 108 abstract class EventImpl extends MirrorImpl implements Event { 109 110 private final byte eventCmd; 111 private final int requestID; 112 // This is set only for client requests, not internal requests. 113 private final EventRequest request; 114 115 /** 116 * Constructor for events. 117 */ 118 protected EventImpl(JDWP.Event.Composite.Events.EventsCommon evt, 119 int requestID) { 120 super(EventSetImpl.this.vm); 121 this.eventCmd = evt.eventKind(); 122 this.requestID = requestID; 123 EventRequestManagerImpl ermi = EventSetImpl.this. 124 vm.eventRequestManagerImpl(); 125 this.request = ermi.request(eventCmd, requestID); 126 } 127 128 /* 129 * Override superclass back to default equality 130 */ 131 public boolean equals(Object obj) { 132 return this == obj; 133 } 134 135 public int hashCode() { 136 return System.identityHashCode(this); 137 } 138 139 /** 140 * Constructor for VM disconnected events. 141 */ 142 protected EventImpl(byte eventCmd) { 143 super(EventSetImpl.this.vm); 144 this.eventCmd = eventCmd; 145 this.requestID = 0; 146 this.request = null; 147 } 148 149 public EventRequest request() { 150 return request; 151 } 152 153 int requestID() { 154 return requestID; 155 } 156 157 EventDestination destination() { 158 /* 159 * We need to decide if this event is for 160 * 1. an internal request 161 * 2. a client request that is no longer available, ie 162 * it has been deleted, or disabled and re-enabled 163 * which gives it a new ID. 164 * 3. a current client request that is disabled 165 * 4. a current enabled client request. 166 * 167 * We will filter this set into a set 168 * that contains only 1s for our internal queue 169 * and a set that contains only 4s for our client queue. 170 * If we get an EventSet that contains only 2 and 3 171 * then we have to resume it if it is not SUSPEND_NONE 172 * because no one else will. 173 */ 174 if (requestID == 0) { 175 /* An unsolicited event. These have traditionally 176 * been treated as client events. 177 */ 178 return EventDestination.CLIENT_EVENT; 179 } 180 181 // Is this an event for a current client request? 182 if (request == null) { 183 // Nope. Is it an event for an internal request? 184 EventRequestManagerImpl ermi = this.vm.getInternalEventRequestManager(); 185 if (ermi.request(eventCmd, requestID) != null) { 186 // Yep 187 return EventDestination.INTERNAL_EVENT; 188 } 189 return EventDestination.UNKNOWN_EVENT; 190 } 191 192 // We found a client request 193 if (request.isEnabled()) { 194 return EventDestination.CLIENT_EVENT; 195 } 196 return EventDestination.UNKNOWN_EVENT; 197 } 198 199 abstract String eventName(); 200 201 public String toString() { 202 return eventName(); 203 } 204 205 } 206 207 abstract class ThreadedEventImpl extends EventImpl { 208 private ThreadReference thread; 209 210 ThreadedEventImpl(JDWP.Event.Composite.Events.EventsCommon evt, 211 int requestID, ThreadReference thread) { 212 super(evt, requestID); 213 this.thread = thread; 214 } 215 216 public ThreadReference thread() { 217 return thread; 218 } 219 220 public String toString() { 221 return eventName() + " in thread " + thread.name(); 222 } 223 } 224 225 abstract class LocatableEventImpl extends ThreadedEventImpl 226 implements Locatable { 227 private Location location; 228 229 LocatableEventImpl(JDWP.Event.Composite.Events.EventsCommon evt, 230 int requestID, 231 ThreadReference thread, Location location) { 232 super(evt, requestID, thread); 233 this.location = location; 234 } 235 236 public Location location() { 237 return location; 238 } 239 240 /** 241 * For MethodEntry and MethodExit 242 */ 243 public Method method() { 244 return location.method(); 245 } 246 247 public String toString() { 248 return eventName() + "@" + 249 ((location() == null) ? " null" : location().toString()) + 250 " in thread " + thread().name(); 251 } 252 } 253 254 class BreakpointEventImpl extends LocatableEventImpl 255 implements BreakpointEvent { 256 BreakpointEventImpl(JDWP.Event.Composite.Events.Breakpoint evt) { 257 super(evt, evt.requestID, evt.thread, evt.location); 258 } 259 260 String eventName() { 261 return "BreakpointEvent"; 262 } 263 } 264 265 class StepEventImpl extends LocatableEventImpl implements StepEvent { 266 StepEventImpl(JDWP.Event.Composite.Events.SingleStep evt) { 267 super(evt, evt.requestID, evt.thread, evt.location); 268 } 269 270 String eventName() { 271 return "StepEvent"; 272 } 273 } 274 275 class MethodEntryEventImpl extends LocatableEventImpl 276 implements MethodEntryEvent { 277 MethodEntryEventImpl(JDWP.Event.Composite.Events.MethodEntry evt) { 278 super(evt, evt.requestID, evt.thread, evt.location); 279 } 280 281 String eventName() { 282 return "MethodEntryEvent"; 283 } 284 } 285 286 class MethodExitEventImpl extends LocatableEventImpl 287 implements MethodExitEvent { 288 private Value returnVal = null; 289 290 MethodExitEventImpl(JDWP.Event.Composite.Events.MethodExit evt) { 291 super(evt, evt.requestID, evt.thread, evt.location); 292 } 293 294 MethodExitEventImpl(JDWP.Event.Composite.Events.MethodExitWithReturnValue evt) { 295 super(evt, evt.requestID, evt.thread, evt.location); 296 returnVal = evt.value; 297 } 298 299 String eventName() { 300 return "MethodExitEvent"; 301 } 302 303 public Value returnValue() { 304 if (!this.vm.canGetMethodReturnValues()) { 305 throw new UnsupportedOperationException( 306 "target does not support return values in MethodExit events"); 307 } 308 return returnVal; 309 } 310 311 } 312 313 class MonitorContendedEnterEventImpl extends LocatableEventImpl 314 implements MonitorContendedEnterEvent { 315 private ObjectReference monitor = null; 316 317 MonitorContendedEnterEventImpl(JDWP.Event.Composite.Events.MonitorContendedEnter evt) { 318 super(evt, evt.requestID, evt.thread, evt.location); 319 this.monitor = evt.object; 320 } 321 322 String eventName() { 323 return "MonitorContendedEnter"; 324 } 325 326 public ObjectReference monitor() { 327 return monitor; 328 }; 329 330 } 331 332 class MonitorContendedEnteredEventImpl extends LocatableEventImpl 333 implements MonitorContendedEnteredEvent { 334 private ObjectReference monitor = null; 335 336 MonitorContendedEnteredEventImpl(JDWP.Event.Composite.Events.MonitorContendedEntered evt) { 337 super(evt, evt.requestID, evt.thread, evt.location); 338 this.monitor = evt.object; 339 } 340 341 String eventName() { 342 return "MonitorContendedEntered"; 343 } 344 345 public ObjectReference monitor() { 346 return monitor; 347 }; 348 349 } 350 351 class MonitorWaitEventImpl extends LocatableEventImpl 352 implements MonitorWaitEvent { 353 private ObjectReference monitor = null; 354 private long timeout; 355 356 MonitorWaitEventImpl(JDWP.Event.Composite.Events.MonitorWait evt) { 357 super(evt, evt.requestID, evt.thread, evt.location); 358 this.monitor = evt.object; 359 this.timeout = evt.timeout; 360 } 361 362 String eventName() { 363 return "MonitorWait"; 364 } 365 366 public ObjectReference monitor() { 367 return monitor; 368 }; 369 370 public long timeout() { 371 return timeout; 372 } 373 } 374 375 class MonitorWaitedEventImpl extends LocatableEventImpl 376 implements MonitorWaitedEvent { 377 private ObjectReference monitor = null; 378 private boolean timed_out; 379 380 MonitorWaitedEventImpl(JDWP.Event.Composite.Events.MonitorWaited evt) { 381 super(evt, evt.requestID, evt.thread, evt.location); 382 this.monitor = evt.object; 383 this.timed_out = evt.timed_out; 384 } 385 386 String eventName() { 387 return "MonitorWaited"; 388 } 389 390 public ObjectReference monitor() { 391 return monitor; 392 }; 393 394 public boolean timedout() { 395 return timed_out; 396 } 397 } 398 399 class ClassPrepareEventImpl extends ThreadedEventImpl 400 implements ClassPrepareEvent { 401 private ReferenceType referenceType; 402 403 ClassPrepareEventImpl(JDWP.Event.Composite.Events.ClassPrepare evt) { 404 super(evt, evt.requestID, evt.thread); 405 referenceType = this.vm.referenceType(evt.typeID, evt.refTypeTag, 406 evt.signature); 407 ((ReferenceTypeImpl)referenceType).setStatus(evt.status); 408 } 409 410 public ReferenceType referenceType() { 411 return referenceType; 412 } 413 414 String eventName() { 415 return "ClassPrepareEvent"; 416 } 417 } 418 419 class ClassUnloadEventImpl extends EventImpl implements ClassUnloadEvent { 420 private String classSignature; 421 422 ClassUnloadEventImpl(JDWP.Event.Composite.Events.ClassUnload evt) { 423 super(evt, evt.requestID); 424 this.classSignature = evt.signature; 425 } 426 427 public String className() { 428 String name = classSignature; 429 int index = name.indexOf("."); // check if it's a hidden class 430 if (index < 0) { 431 name = name.replace('/', '.'); 432 } else { 433 // the class name of a hidden class is <binary-name> + "/" + <suffix> 434 name = name.substring(0, index).replace('/', '.') + "/" + 435 name.substring(index + 1, name.length()); 436 } 437 return name; 438 } 439 440 public String classSignature() { 441 return classSignature; 442 } 443 444 String eventName() { 445 return "ClassUnloadEvent"; 446 } 447 } 448 449 class ExceptionEventImpl extends LocatableEventImpl 450 implements ExceptionEvent { 451 private ObjectReference exception; 452 private Location catchLocation; 453 454 ExceptionEventImpl(JDWP.Event.Composite.Events.Exception evt) { 455 super(evt, evt.requestID, evt.thread, evt.location); 456 this.exception = evt.exception; 457 this.catchLocation = evt.catchLocation; 458 } 459 460 public ObjectReference exception() { 461 return exception; 462 } 463 464 public Location catchLocation() { 465 return catchLocation; 466 } 467 468 String eventName() { 469 return "ExceptionEvent"; 470 } 471 } 472 473 class ThreadDeathEventImpl extends ThreadedEventImpl 474 implements ThreadDeathEvent { 475 ThreadDeathEventImpl(JDWP.Event.Composite.Events.ThreadDeath evt) { 476 super(evt, evt.requestID, evt.thread); 477 } 478 479 String eventName() { 480 return "ThreadDeathEvent"; 481 } 482 } 483 484 class ThreadStartEventImpl extends ThreadedEventImpl 485 implements ThreadStartEvent { 486 ThreadStartEventImpl(JDWP.Event.Composite.Events.ThreadStart evt) { 487 super(evt, evt.requestID, evt.thread); 488 } 489 490 String eventName() { 491 return "ThreadStartEvent"; 492 } 493 } 494 495 class VMStartEventImpl extends ThreadedEventImpl 496 implements VMStartEvent { 497 VMStartEventImpl(JDWP.Event.Composite.Events.VMStart evt) { 498 super(evt, evt.requestID, evt.thread); 499 } 500 501 String eventName() { 502 return "VMStartEvent"; 503 } 504 } 505 506 class VMDeathEventImpl extends EventImpl implements VMDeathEvent { 507 508 VMDeathEventImpl(JDWP.Event.Composite.Events.VMDeath evt) { 509 super(evt, evt.requestID); 510 } 511 512 String eventName() { 513 return "VMDeathEvent"; 514 } 515 } 516 517 class VMDisconnectEventImpl extends EventImpl 518 implements VMDisconnectEvent { 519 520 VMDisconnectEventImpl() { 521 super((byte)JDWP.EventKind.VM_DISCONNECTED); 522 } 523 524 String eventName() { 525 return "VMDisconnectEvent"; 526 } 527 } 528 529 abstract class WatchpointEventImpl extends LocatableEventImpl 530 implements WatchpointEvent { 531 private final ReferenceTypeImpl refType; 532 private final long fieldID; 533 private final ObjectReference object; 534 private Field field = null; 535 536 WatchpointEventImpl(JDWP.Event.Composite.Events.EventsCommon evt, 537 int requestID, 538 ThreadReference thread, Location location, 539 byte refTypeTag, long typeID, long fieldID, 540 ObjectReference object) { 541 super(evt, requestID, thread, location); 542 this.refType = this.vm.referenceType(typeID, refTypeTag); 543 this.fieldID = fieldID; 544 this.object = object; 545 } 546 547 public Field field() { 548 if (field == null) { 549 field = refType.getFieldMirror(fieldID); 550 } 551 return field; 552 } 553 554 public ObjectReference object() { 555 return object; 556 } 557 558 public Value valueCurrent() { 559 if (object == null) { 560 return refType.getValue(field()); 561 } else { 562 return object.getValue(field()); 563 } 564 } 565 } 566 567 class AccessWatchpointEventImpl extends WatchpointEventImpl 568 implements AccessWatchpointEvent { 569 570 AccessWatchpointEventImpl(JDWP.Event.Composite.Events.FieldAccess evt) { 571 super(evt, evt.requestID, evt.thread, evt.location, 572 evt.refTypeTag, evt.typeID, evt.fieldID, evt.object); 573 } 574 575 String eventName() { 576 return "AccessWatchpoint"; 577 } 578 } 579 580 class ModificationWatchpointEventImpl extends WatchpointEventImpl 581 implements ModificationWatchpointEvent { 582 Value newValue; 583 584 ModificationWatchpointEventImpl( 585 JDWP.Event.Composite.Events.FieldModification evt) { 586 super(evt, evt.requestID, evt.thread, evt.location, 587 evt.refTypeTag, evt.typeID, evt.fieldID, evt.object); 588 this.newValue = evt.valueToBe; 589 } 590 591 public Value valueToBe() { 592 return newValue; 593 } 594 595 String eventName() { 596 return "ModificationWatchpoint"; 597 } 598 } 599 600 /** 601 * Events are constructed on the thread which reads all data from the 602 * transport. This means that the packet cannot be converted to real 603 * JDI objects as that may involve further communications with the 604 * back end which would deadlock. 605 * 606 * Hence the {@link #build()} method below called by EventQueue. 607 */ 608 EventSetImpl(VirtualMachine aVm, Packet pkt) { 609 super(); 610 611 // From "MirrorImpl": 612 // Yes, its a bit of a hack. But by doing it this 613 // way, this is the only place we have to change 614 // typing to substitute a new impl. 615 vm = (VirtualMachineImpl)aVm; 616 617 this.pkt = pkt; 618 } 619 620 /** 621 * Constructor for special events like VM disconnected 622 */ 623 EventSetImpl(VirtualMachine aVm, byte eventCmd) { 624 this(aVm, null); 625 suspendPolicy = JDWP.SuspendPolicy.NONE; 626 switch (eventCmd) { 627 case JDWP.EventKind.VM_DISCONNECTED: 628 addEvent(new VMDisconnectEventImpl()); 629 break; 630 631 default: 632 throw new InternalException("Bad singleton event code"); 633 } 634 } 635 636 private void addEvent(EventImpl evt) { 637 // Note that this class has a public add method that throws 638 // an exception so that clients can't modify the EventSet 639 super.add(evt); 640 } 641 642 /* 643 * Complete the construction of an EventSet. This is called from 644 * an event handler thread. It upacks the JDWP events inside 645 * the packet and creates EventImpls for them. The EventSet is already 646 * on EventQueues when this is called, so it has to be synch. 647 */ 648 synchronized void build() { 649 if (pkt == null) { 650 return; 651 } 652 PacketStream ps = new PacketStream(vm, pkt); 653 JDWP.Event.Composite compEvt = new JDWP.Event.Composite(vm, ps); 654 suspendPolicy = compEvt.suspendPolicy; 655 if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) { 656 switch(suspendPolicy) { 657 case JDWP.SuspendPolicy.ALL: 658 vm.printTrace("EventSet: SUSPEND_ALL"); 659 break; 660 661 case JDWP.SuspendPolicy.EVENT_THREAD: 662 vm.printTrace("EventSet: SUSPEND_EVENT_THREAD"); 663 break; 664 665 case JDWP.SuspendPolicy.NONE: 666 vm.printTrace("EventSet: SUSPEND_NONE"); 667 break; 668 } 669 } 670 671 ThreadReference fix6485605 = null; 672 for (int i = 0; i < compEvt.events.length; i++) { 673 EventImpl evt = createEvent(compEvt.events[i]); 674 if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) { 675 try { 676 vm.printTrace("Event: " + evt); 677 } catch (VMDisconnectedException ee) { 678 // ignore - see bug 6502716 679 } 680 } 681 682 switch (evt.destination()) { 683 case UNKNOWN_EVENT: 684 // Ignore disabled, deleted, unknown events, but 685 // save the thread if there is one since we might 686 // have to resume it. Note that events for different 687 // threads can't be in the same event set. 688 if (evt instanceof ThreadedEventImpl && 689 suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) { 690 fix6485605 = ((ThreadedEventImpl)evt).thread(); 691 } 692 continue; 693 case CLIENT_EVENT: 694 addEvent(evt); 695 break; 696 case INTERNAL_EVENT: 697 if (internalEventSet == null) { 698 internalEventSet = new EventSetImpl(this.vm, null); 699 } 700 internalEventSet.addEvent(evt); 701 break; 702 default: 703 throw new InternalException("Invalid event destination"); 704 } 705 } 706 pkt = null; // No longer needed - free it up 707 708 // Avoid hangs described in 6296125, 6293795 709 if (super.size() == 0) { 710 // This set has no client events. If we don't do 711 // needed resumes, no one else is going to. 712 if (suspendPolicy == JDWP.SuspendPolicy.ALL) { 713 vm.resume(); 714 } else if (suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) { 715 // See bug 6485605. 716 if (fix6485605 != null) { 717 fix6485605.resume(); 718 } else { 719 // apparently, there is nothing to resume. 720 } 721 } 722 suspendPolicy = JDWP.SuspendPolicy.NONE; 723 724 } 725 726 } 727 728 /** 729 * Filter out internal events 730 */ 731 EventSet userFilter() { 732 return this; 733 } 734 735 /** 736 * Filter out user events. 737 */ 738 EventSet internalFilter() { 739 return this.internalEventSet; 740 } 741 742 EventImpl createEvent(JDWP.Event.Composite.Events evt) { 743 JDWP.Event.Composite.Events.EventsCommon comm = evt.aEventsCommon; 744 switch (evt.eventKind) { 745 case JDWP.EventKind.THREAD_START: 746 return new ThreadStartEventImpl( 747 (JDWP.Event.Composite.Events.ThreadStart)comm); 748 749 case JDWP.EventKind.THREAD_END: 750 return new ThreadDeathEventImpl( 751 (JDWP.Event.Composite.Events.ThreadDeath)comm); 752 753 case JDWP.EventKind.EXCEPTION: 754 return new ExceptionEventImpl( 755 (JDWP.Event.Composite.Events.Exception)comm); 756 757 case JDWP.EventKind.BREAKPOINT: 758 return new BreakpointEventImpl( 759 (JDWP.Event.Composite.Events.Breakpoint)comm); 760 761 case JDWP.EventKind.METHOD_ENTRY: 762 return new MethodEntryEventImpl( 763 (JDWP.Event.Composite.Events.MethodEntry)comm); 764 765 case JDWP.EventKind.METHOD_EXIT: 766 return new MethodExitEventImpl( 767 (JDWP.Event.Composite.Events.MethodExit)comm); 768 769 case JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE: 770 return new MethodExitEventImpl( 771 (JDWP.Event.Composite.Events.MethodExitWithReturnValue)comm); 772 773 case JDWP.EventKind.FIELD_ACCESS: 774 return new AccessWatchpointEventImpl( 775 (JDWP.Event.Composite.Events.FieldAccess)comm); 776 777 case JDWP.EventKind.FIELD_MODIFICATION: 778 return new ModificationWatchpointEventImpl( 779 (JDWP.Event.Composite.Events.FieldModification)comm); 780 781 case JDWP.EventKind.SINGLE_STEP: 782 return new StepEventImpl( 783 (JDWP.Event.Composite.Events.SingleStep)comm); 784 785 case JDWP.EventKind.CLASS_PREPARE: 786 return new ClassPrepareEventImpl( 787 (JDWP.Event.Composite.Events.ClassPrepare)comm); 788 789 case JDWP.EventKind.CLASS_UNLOAD: 790 return new ClassUnloadEventImpl( 791 (JDWP.Event.Composite.Events.ClassUnload)comm); 792 793 case JDWP.EventKind.MONITOR_CONTENDED_ENTER: 794 return new MonitorContendedEnterEventImpl( 795 (JDWP.Event.Composite.Events.MonitorContendedEnter)comm); 796 797 case JDWP.EventKind.MONITOR_CONTENDED_ENTERED: 798 return new MonitorContendedEnteredEventImpl( 799 (JDWP.Event.Composite.Events.MonitorContendedEntered)comm); 800 801 case JDWP.EventKind.MONITOR_WAIT: 802 return new MonitorWaitEventImpl( 803 (JDWP.Event.Composite.Events.MonitorWait)comm); 804 805 case JDWP.EventKind.MONITOR_WAITED: 806 return new MonitorWaitedEventImpl( 807 (JDWP.Event.Composite.Events.MonitorWaited)comm); 808 809 case JDWP.EventKind.VM_START: 810 return new VMStartEventImpl( 811 (JDWP.Event.Composite.Events.VMStart)comm); 812 813 case JDWP.EventKind.VM_DEATH: 814 return new VMDeathEventImpl( 815 (JDWP.Event.Composite.Events.VMDeath)comm); 816 817 default: 818 // Ignore unknown event types 819 System.err.println("Ignoring event cmd " + 820 evt.eventKind + " from the VM"); 821 return null; 822 } 823 } 824 825 public VirtualMachine virtualMachine() { 826 return vm; 827 } 828 829 public int suspendPolicy() { 830 return EventRequestManagerImpl.JDWPtoJDISuspendPolicy(suspendPolicy); 831 } 832 833 private ThreadReference eventThread() { 834 for (Event event : this) { 835 if (event instanceof ThreadedEventImpl) { 836 return ((ThreadedEventImpl)event).thread(); 837 } 838 } 839 return null; 840 } 841 842 public void resume() { 843 switch (suspendPolicy()) { 844 case EventRequest.SUSPEND_ALL: 845 vm.resume(); 846 break; 847 case EventRequest.SUSPEND_EVENT_THREAD: 848 ThreadReference thread = eventThread(); 849 if (thread == null) { 850 throw new InternalException("Inconsistent suspend policy"); 851 } 852 thread.resume(); 853 break; 854 case EventRequest.SUSPEND_NONE: 855 // Do nothing 856 break; 857 default: 858 throw new InternalException("Invalid suspend policy"); 859 } 860 } 861 862 public Iterator<Event> iterator() { 863 return new Itr(); 864 } 865 866 public EventIterator eventIterator() { 867 return new Itr(); 868 } 869 870 public class Itr implements EventIterator { 871 /** 872 * Index of element to be returned by subsequent call to next. 873 */ 874 int cursor = 0; 875 876 public boolean hasNext() { 877 return cursor != size(); 878 } 879 880 public Event next() { 881 try { 882 Event nxt = get(cursor); 883 ++cursor; 884 return nxt; 885 } catch(IndexOutOfBoundsException e) { 886 throw new NoSuchElementException(); 887 } 888 } 889 890 public Event nextEvent() { 891 return next(); 892 } 893 894 public void remove() { 895 throw new UnsupportedOperationException(); 896 } 897 } 898 899 @Override 900 public Spliterator<Event> spliterator() { 901 return Spliterators.spliterator(this, Spliterator.DISTINCT); 902 } 903 904 /* below make this unmodifiable */ 905 906 public boolean add(Event o){ 907 throw new UnsupportedOperationException(); 908 } 909 public boolean remove(Object o) { 910 throw new UnsupportedOperationException(); 911 } 912 public boolean addAll(Collection<? extends Event> coll) { 913 throw new UnsupportedOperationException(); 914 } 915 public boolean removeAll(Collection<?> coll) { 916 throw new UnsupportedOperationException(); 917 } 918 public boolean retainAll(Collection<?> coll) { 919 throw new UnsupportedOperationException(); 920 } 921 public void clear() { 922 throw new UnsupportedOperationException(); 923 } 924 }