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