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 // trim leading "L" and trailing ";" 429 String name = classSignature.substring(1, classSignature.length() - 1); 430 int index = name.indexOf("."); // check if it is a hidden class 431 if (index < 0) { 432 return name.replace('/', '.'); 433 } else { 434 // map the type descriptor from: "L" + N + "." + <suffix> + ";" 435 // to class name: N.replace('/', '.') + "/" + <suffix> 436 return name.substring(0, index).replace('/', '.') 437 + "/" + name.substring(index + 1); 438 } 439 } 440 441 public String classSignature() { 442 return classSignature; 443 } 444 445 String eventName() { 446 return "ClassUnloadEvent"; 447 } 448 } 449 450 class ExceptionEventImpl extends LocatableEventImpl 451 implements ExceptionEvent { 452 private ObjectReference exception; 453 private Location catchLocation; 454 455 ExceptionEventImpl(JDWP.Event.Composite.Events.Exception evt) { 456 super(evt, evt.requestID, evt.thread, evt.location); 457 this.exception = evt.exception; 458 this.catchLocation = evt.catchLocation; 459 } 460 461 public ObjectReference exception() { 462 return exception; 463 } 464 465 public Location catchLocation() { 466 return catchLocation; 467 } 468 469 String eventName() { 470 return "ExceptionEvent"; 471 } 472 } 473 474 class ThreadDeathEventImpl extends ThreadedEventImpl 475 implements ThreadDeathEvent { 476 ThreadDeathEventImpl(JDWP.Event.Composite.Events.ThreadDeath evt) { 477 super(evt, evt.requestID, evt.thread); 478 } 479 480 String eventName() { 481 return "ThreadDeathEvent"; 482 } 483 } 484 485 class ThreadStartEventImpl extends ThreadedEventImpl 486 implements ThreadStartEvent { 487 ThreadStartEventImpl(JDWP.Event.Composite.Events.ThreadStart evt) { 488 super(evt, evt.requestID, evt.thread); 489 } 490 491 String eventName() { 492 return "ThreadStartEvent"; 493 } 494 } 495 496 class VMStartEventImpl extends ThreadedEventImpl 497 implements VMStartEvent { 498 VMStartEventImpl(JDWP.Event.Composite.Events.VMStart evt) { 499 super(evt, evt.requestID, evt.thread); 500 } 501 502 String eventName() { 503 return "VMStartEvent"; 504 } 505 } 506 507 class VMDeathEventImpl extends EventImpl implements VMDeathEvent { 508 509 VMDeathEventImpl(JDWP.Event.Composite.Events.VMDeath evt) { 510 super(evt, evt.requestID); 511 } 512 513 String eventName() { 514 return "VMDeathEvent"; 515 } 516 } 517 518 class VMDisconnectEventImpl extends EventImpl 519 implements VMDisconnectEvent { 520 521 VMDisconnectEventImpl() { 522 super((byte)JDWP.EventKind.VM_DISCONNECTED); 523 } 524 525 String eventName() { 526 return "VMDisconnectEvent"; 527 } 528 } 529 530 abstract class WatchpointEventImpl extends LocatableEventImpl 531 implements WatchpointEvent { 532 private final ReferenceTypeImpl refType; 533 private final long fieldID; 534 private final ObjectReference object; 535 private Field field = null; 536 537 WatchpointEventImpl(JDWP.Event.Composite.Events.EventsCommon evt, 538 int requestID, 539 ThreadReference thread, Location location, 540 byte refTypeTag, long typeID, long fieldID, 541 ObjectReference object) { 542 super(evt, requestID, thread, location); 543 this.refType = this.vm.referenceType(typeID, refTypeTag); 544 this.fieldID = fieldID; 545 this.object = object; 546 } 547 548 public Field field() { 549 if (field == null) { 550 field = refType.getFieldMirror(fieldID); 551 } 552 return field; 553 } 554 555 public ObjectReference object() { 556 return object; 557 } 558 559 public Value valueCurrent() { 560 if (object == null) { 561 return refType.getValue(field()); 562 } else { 563 return object.getValue(field()); 564 } 565 } 566 } 567 568 class AccessWatchpointEventImpl extends WatchpointEventImpl 569 implements AccessWatchpointEvent { 570 571 AccessWatchpointEventImpl(JDWP.Event.Composite.Events.FieldAccess evt) { 572 super(evt, evt.requestID, evt.thread, evt.location, 573 evt.refTypeTag, evt.typeID, evt.fieldID, evt.object); 574 } 575 576 String eventName() { 577 return "AccessWatchpoint"; 578 } 579 } 580 581 class ModificationWatchpointEventImpl extends WatchpointEventImpl 582 implements ModificationWatchpointEvent { 583 Value newValue; 584 585 ModificationWatchpointEventImpl( 586 JDWP.Event.Composite.Events.FieldModification evt) { 587 super(evt, evt.requestID, evt.thread, evt.location, 588 evt.refTypeTag, evt.typeID, evt.fieldID, evt.object); 589 this.newValue = evt.valueToBe; 590 } 591 592 public Value valueToBe() { 593 return newValue; 594 } 595 596 String eventName() { 597 return "ModificationWatchpoint"; 598 } 599 } 600 601 /** 602 * Events are constructed on the thread which reads all data from the 603 * transport. This means that the packet cannot be converted to real 604 * JDI objects as that may involve further communications with the 605 * back end which would deadlock. 606 * 607 * Hence the {@link #build()} method below called by EventQueue. 608 */ 609 EventSetImpl(VirtualMachine aVm, Packet pkt) { 610 super(); 611 612 // From "MirrorImpl": 613 // Yes, its a bit of a hack. But by doing it this 614 // way, this is the only place we have to change 615 // typing to substitute a new impl. 616 vm = (VirtualMachineImpl)aVm; 617 618 this.pkt = pkt; 619 } 620 621 /** 622 * Constructor for special events like VM disconnected 623 */ 624 EventSetImpl(VirtualMachine aVm, byte eventCmd) { 625 this(aVm, null); 626 suspendPolicy = JDWP.SuspendPolicy.NONE; 627 switch (eventCmd) { 628 case JDWP.EventKind.VM_DISCONNECTED: 629 addEvent(new VMDisconnectEventImpl()); 630 break; 631 632 default: 633 throw new InternalException("Bad singleton event code"); 634 } 635 } 636 637 private void addEvent(EventImpl evt) { 638 // Note that this class has a public add method that throws 639 // an exception so that clients can't modify the EventSet 640 super.add(evt); 641 } 642 643 /* 644 * Complete the construction of an EventSet. This is called from 645 * an event handler thread. It upacks the JDWP events inside 646 * the packet and creates EventImpls for them. The EventSet is already 647 * on EventQueues when this is called, so it has to be synch. 648 */ 649 synchronized void build() { 650 if (pkt == null) { 651 return; 652 } 653 PacketStream ps = new PacketStream(vm, pkt); 654 JDWP.Event.Composite compEvt = new JDWP.Event.Composite(vm, ps); 655 suspendPolicy = compEvt.suspendPolicy; 656 if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) { 657 switch(suspendPolicy) { 658 case JDWP.SuspendPolicy.ALL: 659 vm.printTrace("EventSet: SUSPEND_ALL"); 660 break; 661 662 case JDWP.SuspendPolicy.EVENT_THREAD: 663 vm.printTrace("EventSet: SUSPEND_EVENT_THREAD"); 664 break; 665 666 case JDWP.SuspendPolicy.NONE: 667 vm.printTrace("EventSet: SUSPEND_NONE"); 668 break; 669 } 670 } 671 672 ThreadReference fix6485605 = null; 673 for (int i = 0; i < compEvt.events.length; i++) { 674 EventImpl evt = createEvent(compEvt.events[i]); 675 if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) { 676 try { 677 vm.printTrace("Event: " + evt); 678 } catch (VMDisconnectedException ee) { 679 // ignore - see bug 6502716 680 } 681 } 682 683 switch (evt.destination()) { 684 case UNKNOWN_EVENT: 685 // Ignore disabled, deleted, unknown events, but 686 // save the thread if there is one since we might 687 // have to resume it. Note that events for different 688 // threads can't be in the same event set. 689 if (evt instanceof ThreadedEventImpl && 690 suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) { 691 fix6485605 = ((ThreadedEventImpl)evt).thread(); 692 } 693 continue; 694 case CLIENT_EVENT: 695 addEvent(evt); 696 break; 697 case INTERNAL_EVENT: 698 if (internalEventSet == null) { 699 internalEventSet = new EventSetImpl(this.vm, null); 700 } 701 internalEventSet.addEvent(evt); 702 break; 703 default: 704 throw new InternalException("Invalid event destination"); 705 } 706 } 707 pkt = null; // No longer needed - free it up 708 709 // Avoid hangs described in 6296125, 6293795 710 if (super.size() == 0) { 711 // This set has no client events. If we don't do 712 // needed resumes, no one else is going to. 713 if (suspendPolicy == JDWP.SuspendPolicy.ALL) { 714 vm.resume(); 715 } else if (suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) { 716 // See bug 6485605. 717 if (fix6485605 != null) { 718 fix6485605.resume(); 719 } else { 720 // apparently, there is nothing to resume. 721 } 722 } 723 suspendPolicy = JDWP.SuspendPolicy.NONE; 724 725 } 726 727 } 728 729 /** 730 * Filter out internal events 731 */ 732 EventSet userFilter() { 733 return this; 734 } 735 736 /** 737 * Filter out user events. 738 */ 739 EventSet internalFilter() { 740 return this.internalEventSet; 741 } 742 743 EventImpl createEvent(JDWP.Event.Composite.Events evt) { 744 JDWP.Event.Composite.Events.EventsCommon comm = evt.aEventsCommon; 745 switch (evt.eventKind) { 746 case JDWP.EventKind.THREAD_START: 747 return new ThreadStartEventImpl( 748 (JDWP.Event.Composite.Events.ThreadStart)comm); 749 750 case JDWP.EventKind.THREAD_END: 751 return new ThreadDeathEventImpl( 752 (JDWP.Event.Composite.Events.ThreadDeath)comm); 753 754 case JDWP.EventKind.EXCEPTION: 755 return new ExceptionEventImpl( 756 (JDWP.Event.Composite.Events.Exception)comm); 757 758 case JDWP.EventKind.BREAKPOINT: 759 return new BreakpointEventImpl( 760 (JDWP.Event.Composite.Events.Breakpoint)comm); 761 762 case JDWP.EventKind.METHOD_ENTRY: 763 return new MethodEntryEventImpl( 764 (JDWP.Event.Composite.Events.MethodEntry)comm); 765 766 case JDWP.EventKind.METHOD_EXIT: 767 return new MethodExitEventImpl( 768 (JDWP.Event.Composite.Events.MethodExit)comm); 769 770 case JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE: 771 return new MethodExitEventImpl( 772 (JDWP.Event.Composite.Events.MethodExitWithReturnValue)comm); 773 774 case JDWP.EventKind.FIELD_ACCESS: 775 return new AccessWatchpointEventImpl( 776 (JDWP.Event.Composite.Events.FieldAccess)comm); 777 778 case JDWP.EventKind.FIELD_MODIFICATION: 779 return new ModificationWatchpointEventImpl( 780 (JDWP.Event.Composite.Events.FieldModification)comm); 781 782 case JDWP.EventKind.SINGLE_STEP: 783 return new StepEventImpl( 784 (JDWP.Event.Composite.Events.SingleStep)comm); 785 786 case JDWP.EventKind.CLASS_PREPARE: 787 return new ClassPrepareEventImpl( 788 (JDWP.Event.Composite.Events.ClassPrepare)comm); 789 790 case JDWP.EventKind.CLASS_UNLOAD: 791 return new ClassUnloadEventImpl( 792 (JDWP.Event.Composite.Events.ClassUnload)comm); 793 794 case JDWP.EventKind.MONITOR_CONTENDED_ENTER: 795 return new MonitorContendedEnterEventImpl( 796 (JDWP.Event.Composite.Events.MonitorContendedEnter)comm); 797 798 case JDWP.EventKind.MONITOR_CONTENDED_ENTERED: 799 return new MonitorContendedEnteredEventImpl( 800 (JDWP.Event.Composite.Events.MonitorContendedEntered)comm); 801 802 case JDWP.EventKind.MONITOR_WAIT: 803 return new MonitorWaitEventImpl( 804 (JDWP.Event.Composite.Events.MonitorWait)comm); 805 806 case JDWP.EventKind.MONITOR_WAITED: 807 return new MonitorWaitedEventImpl( 808 (JDWP.Event.Composite.Events.MonitorWaited)comm); 809 810 case JDWP.EventKind.VM_START: 811 return new VMStartEventImpl( 812 (JDWP.Event.Composite.Events.VMStart)comm); 813 814 case JDWP.EventKind.VM_DEATH: 815 return new VMDeathEventImpl( 816 (JDWP.Event.Composite.Events.VMDeath)comm); 817 818 default: 819 // Ignore unknown event types 820 System.err.println("Ignoring event cmd " + 821 evt.eventKind + " from the VM"); 822 return null; 823 } 824 } 825 826 public VirtualMachine virtualMachine() { 827 return vm; 828 } 829 830 public int suspendPolicy() { 831 return EventRequestManagerImpl.JDWPtoJDISuspendPolicy(suspendPolicy); 832 } 833 834 private ThreadReference eventThread() { 835 for (Event event : this) { 836 if (event instanceof ThreadedEventImpl) { 837 return ((ThreadedEventImpl)event).thread(); 838 } 839 } 840 return null; 841 } 842 843 public void resume() { 844 switch (suspendPolicy()) { 845 case EventRequest.SUSPEND_ALL: 846 vm.resume(); 847 break; 848 case EventRequest.SUSPEND_EVENT_THREAD: 849 ThreadReference thread = eventThread(); 850 if (thread == null) { 851 throw new InternalException("Inconsistent suspend policy"); 852 } 853 thread.resume(); 854 break; 855 case EventRequest.SUSPEND_NONE: 856 // Do nothing 857 break; 858 default: 859 throw new InternalException("Invalid suspend policy"); 860 } 861 } 862 863 public Iterator<Event> iterator() { 864 return new Itr(); 865 } 866 867 public EventIterator eventIterator() { 868 return new Itr(); 869 } 870 871 public class Itr implements EventIterator { 872 /** 873 * Index of element to be returned by subsequent call to next. 874 */ 875 int cursor = 0; 876 877 public boolean hasNext() { 878 return cursor != size(); 879 } 880 881 public Event next() { 882 try { 883 Event nxt = get(cursor); 884 ++cursor; 885 return nxt; 886 } catch(IndexOutOfBoundsException e) { 887 throw new NoSuchElementException(); 888 } 889 } 890 891 public Event nextEvent() { 892 return next(); 893 } 894 895 public void remove() { 896 throw new UnsupportedOperationException(); 897 } 898 } 899 900 @Override 901 public Spliterator<Event> spliterator() { 902 return Spliterators.spliterator(this, Spliterator.DISTINCT); 903 } 904 905 /* below make this unmodifiable */ 906 907 public boolean add(Event o){ 908 throw new UnsupportedOperationException(); 909 } 910 public boolean remove(Object o) { 911 throw new UnsupportedOperationException(); 912 } 913 public boolean addAll(Collection<? extends Event> coll) { 914 throw new UnsupportedOperationException(); 915 } 916 public boolean removeAll(Collection<?> coll) { 917 throw new UnsupportedOperationException(); 918 } 919 public boolean retainAll(Collection<?> coll) { 920 throw new UnsupportedOperationException(); 921 } 922 public void clear() { 923 throw new UnsupportedOperationException(); 924 } 925 }