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