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 }