Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/tools/jdi/EventSetImpl.java
38920 views
/*1* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.jdi;2627import com.sun.jdi.*;28import com.sun.jdi.event.*;29import com.sun.jdi.request.*;3031import java.util.*;32enum EventDestination {UNKNOWN_EVENT, INTERNAL_EVENT, CLIENT_EVENT};3334/*35* An EventSet is normally created by the transport reader thread when36* it reads a JDWP Composite command. The constructor doesn't unpack37* the events contained in the Composite command and create EventImpls38* for them because that process might involve calling back into the back-end39* which should not be done by the transport reader thread. Instead,40* the raw bytes of the packet are read and stored in the EventSet.41* The EventSet is then added to each EventQueue. When an EventSet is42* removed from an EventQueue, the EventSetImpl.build() method is called.43* This method reads the packet bytes and creates the actual EventImpl objects.44* build() also filters out events for our internal handler and puts them in45* their own EventSet. This means that the EventImpls that are in the EventSet46* that is on the queues are all for client requests.47*/48public class EventSetImpl extends ArrayList<Event> implements EventSet {49private static final long serialVersionUID = -4857338819787924570L;50private VirtualMachineImpl vm; // we implement Mirror51private Packet pkt;52private byte suspendPolicy;53private EventSetImpl internalEventSet;5455public String toString() {56String string = "event set, policy:" + suspendPolicy +57", count:" + this.size() + " = {";58boolean first = true;59for (Event event : this) {60if (!first) {61string += ", ";62}63string += event.toString();64first = false;65}66string += "}";67return string;68}6970abstract class EventImpl extends MirrorImpl implements Event {7172private final byte eventCmd;73private final int requestID;74// This is set only for client requests, not internal requests.75private final EventRequest request;7677/**78* Constructor for events.79*/80protected EventImpl(JDWP.Event.Composite.Events.EventsCommon evt,81int requestID) {82super(EventSetImpl.this.vm);83this.eventCmd = evt.eventKind();84this.requestID = requestID;85EventRequestManagerImpl ermi = EventSetImpl.this.86vm.eventRequestManagerImpl();87this.request = ermi.request(eventCmd, requestID);88}8990/*91* Override superclass back to default equality92*/93public boolean equals(Object obj) {94return this == obj;95}9697public int hashCode() {98return System.identityHashCode(this);99}100101/**102* Constructor for VM disconnected events.103*/104protected EventImpl(byte eventCmd) {105super(EventSetImpl.this.vm);106this.eventCmd = eventCmd;107this.requestID = 0;108this.request = null;109}110111public EventRequest request() {112return request;113}114115int requestID() {116return requestID;117}118119EventDestination destination() {120/*121* We need to decide if this event is for122* 1. an internal request123* 2. a client request that is no longer available, ie124* it has been deleted, or disabled and re-enabled125* which gives it a new ID.126* 3. a current client request that is disabled127* 4. a current enabled client request.128*129* We will filter this set into a set130* that contains only 1s for our internal queue131* and a set that contains only 4s for our client queue.132* If we get an EventSet that contains only 2 and 3133* then we have to resume it if it is not SUSPEND_NONE134* because no one else will.135*/136if (requestID == 0) {137/* An unsolicited event. These have traditionally138* been treated as client events.139*/140return EventDestination.CLIENT_EVENT;141}142143// Is this an event for a current client request?144if (request == null) {145// Nope. Is it an event for an internal request?146EventRequestManagerImpl ermi = this.vm.getInternalEventRequestManager();147if (ermi.request(eventCmd, requestID) != null) {148// Yep149return EventDestination.INTERNAL_EVENT;150}151return EventDestination.UNKNOWN_EVENT;152}153154// We found a client request155if (request.isEnabled()) {156return EventDestination.CLIENT_EVENT;157}158return EventDestination.UNKNOWN_EVENT;159}160161abstract String eventName();162163public String toString() {164return eventName();165}166167}168169abstract class ThreadedEventImpl extends EventImpl {170private ThreadReference thread;171172ThreadedEventImpl(JDWP.Event.Composite.Events.EventsCommon evt,173int requestID, ThreadReference thread) {174super(evt, requestID);175this.thread = thread;176}177178public ThreadReference thread() {179return thread;180}181182public String toString() {183return eventName() + " in thread " + thread.name();184}185}186187abstract class LocatableEventImpl extends ThreadedEventImpl188implements Locatable {189private Location location;190191LocatableEventImpl(JDWP.Event.Composite.Events.EventsCommon evt,192int requestID,193ThreadReference thread, Location location) {194super(evt, requestID, thread);195this.location = location;196}197198public Location location() {199return location;200}201202/**203* For MethodEntry and MethodExit204*/205public Method method() {206return location.method();207}208209public String toString() {210return eventName() + "@" +211((location() == null) ? " null" : location().toString()) +212" in thread " + thread().name();213}214}215216class BreakpointEventImpl extends LocatableEventImpl217implements BreakpointEvent {218BreakpointEventImpl(JDWP.Event.Composite.Events.Breakpoint evt) {219super(evt, evt.requestID, evt.thread, evt.location);220}221222String eventName() {223return "BreakpointEvent";224}225}226227class StepEventImpl extends LocatableEventImpl implements StepEvent {228StepEventImpl(JDWP.Event.Composite.Events.SingleStep evt) {229super(evt, evt.requestID, evt.thread, evt.location);230}231232String eventName() {233return "StepEvent";234}235}236237class MethodEntryEventImpl extends LocatableEventImpl238implements MethodEntryEvent {239MethodEntryEventImpl(JDWP.Event.Composite.Events.MethodEntry evt) {240super(evt, evt.requestID, evt.thread, evt.location);241}242243String eventName() {244return "MethodEntryEvent";245}246}247248class MethodExitEventImpl extends LocatableEventImpl249implements MethodExitEvent {250private Value returnVal = null;251252MethodExitEventImpl(JDWP.Event.Composite.Events.MethodExit evt) {253super(evt, evt.requestID, evt.thread, evt.location);254}255256MethodExitEventImpl(JDWP.Event.Composite.Events.MethodExitWithReturnValue evt) {257super(evt, evt.requestID, evt.thread, evt.location);258returnVal = evt.value;259}260261String eventName() {262return "MethodExitEvent";263}264265public Value returnValue() {266if (!this.vm.canGetMethodReturnValues()) {267throw new UnsupportedOperationException(268"target does not support return values in MethodExit events");269}270return returnVal;271}272273}274275class MonitorContendedEnterEventImpl extends LocatableEventImpl276implements MonitorContendedEnterEvent {277private ObjectReference monitor = null;278279MonitorContendedEnterEventImpl(JDWP.Event.Composite.Events.MonitorContendedEnter evt) {280super(evt, evt.requestID, evt.thread, evt.location);281this.monitor = evt.object;282}283284String eventName() {285return "MonitorContendedEnter";286}287288public ObjectReference monitor() {289return monitor;290};291292}293294class MonitorContendedEnteredEventImpl extends LocatableEventImpl295implements MonitorContendedEnteredEvent {296private ObjectReference monitor = null;297298MonitorContendedEnteredEventImpl(JDWP.Event.Composite.Events.MonitorContendedEntered evt) {299super(evt, evt.requestID, evt.thread, evt.location);300this.monitor = evt.object;301}302303String eventName() {304return "MonitorContendedEntered";305}306307public ObjectReference monitor() {308return monitor;309};310311}312313class MonitorWaitEventImpl extends LocatableEventImpl314implements MonitorWaitEvent {315private ObjectReference monitor = null;316private long timeout;317318MonitorWaitEventImpl(JDWP.Event.Composite.Events.MonitorWait evt) {319super(evt, evt.requestID, evt.thread, evt.location);320this.monitor = evt.object;321this.timeout = evt.timeout;322}323324String eventName() {325return "MonitorWait";326}327328public ObjectReference monitor() {329return monitor;330};331332public long timeout() {333return timeout;334}335}336337class MonitorWaitedEventImpl extends LocatableEventImpl338implements MonitorWaitedEvent {339private ObjectReference monitor = null;340private boolean timed_out;341342MonitorWaitedEventImpl(JDWP.Event.Composite.Events.MonitorWaited evt) {343super(evt, evt.requestID, evt.thread, evt.location);344this.monitor = evt.object;345this.timed_out = evt.timed_out;346}347348String eventName() {349return "MonitorWaited";350}351352public ObjectReference monitor() {353return monitor;354};355356public boolean timedout() {357return timed_out;358}359}360361class ClassPrepareEventImpl extends ThreadedEventImpl362implements ClassPrepareEvent {363private ReferenceType referenceType;364365ClassPrepareEventImpl(JDWP.Event.Composite.Events.ClassPrepare evt) {366super(evt, evt.requestID, evt.thread);367referenceType = this.vm.referenceType(evt.typeID, evt.refTypeTag,368evt.signature);369((ReferenceTypeImpl)referenceType).setStatus(evt.status);370}371372public ReferenceType referenceType() {373return referenceType;374}375376String eventName() {377return "ClassPrepareEvent";378}379}380381class ClassUnloadEventImpl extends EventImpl implements ClassUnloadEvent {382private String classSignature;383384ClassUnloadEventImpl(JDWP.Event.Composite.Events.ClassUnload evt) {385super(evt, evt.requestID);386this.classSignature = evt.signature;387}388389public String className() {390return classSignature.substring(1, classSignature.length()-1)391.replace('/', '.');392}393394public String classSignature() {395return classSignature;396}397398String eventName() {399return "ClassUnloadEvent";400}401}402403class ExceptionEventImpl extends LocatableEventImpl404implements ExceptionEvent {405private ObjectReference exception;406private Location catchLocation;407408ExceptionEventImpl(JDWP.Event.Composite.Events.Exception evt) {409super(evt, evt.requestID, evt.thread, evt.location);410this.exception = evt.exception;411this.catchLocation = evt.catchLocation;412}413414public ObjectReference exception() {415return exception;416}417418public Location catchLocation() {419return catchLocation;420}421422String eventName() {423return "ExceptionEvent";424}425}426427class ThreadDeathEventImpl extends ThreadedEventImpl428implements ThreadDeathEvent {429ThreadDeathEventImpl(JDWP.Event.Composite.Events.ThreadDeath evt) {430super(evt, evt.requestID, evt.thread);431}432433String eventName() {434return "ThreadDeathEvent";435}436}437438class ThreadStartEventImpl extends ThreadedEventImpl439implements ThreadStartEvent {440ThreadStartEventImpl(JDWP.Event.Composite.Events.ThreadStart evt) {441super(evt, evt.requestID, evt.thread);442}443444String eventName() {445return "ThreadStartEvent";446}447}448449class VMStartEventImpl extends ThreadedEventImpl450implements VMStartEvent {451VMStartEventImpl(JDWP.Event.Composite.Events.VMStart evt) {452super(evt, evt.requestID, evt.thread);453}454455String eventName() {456return "VMStartEvent";457}458}459460class VMDeathEventImpl extends EventImpl implements VMDeathEvent {461462VMDeathEventImpl(JDWP.Event.Composite.Events.VMDeath evt) {463super(evt, evt.requestID);464}465466String eventName() {467return "VMDeathEvent";468}469}470471class VMDisconnectEventImpl extends EventImpl472implements VMDisconnectEvent {473474VMDisconnectEventImpl() {475super((byte)JDWP.EventKind.VM_DISCONNECTED);476}477478String eventName() {479return "VMDisconnectEvent";480}481}482483abstract class WatchpointEventImpl extends LocatableEventImpl484implements WatchpointEvent {485private final ReferenceTypeImpl refType;486private final long fieldID;487private final ObjectReference object;488private Field field = null;489490WatchpointEventImpl(JDWP.Event.Composite.Events.EventsCommon evt,491int requestID,492ThreadReference thread, Location location,493byte refTypeTag, long typeID, long fieldID,494ObjectReference object) {495super(evt, requestID, thread, location);496this.refType = this.vm.referenceType(typeID, refTypeTag);497this.fieldID = fieldID;498this.object = object;499}500501public Field field() {502if (field == null) {503field = refType.getFieldMirror(fieldID);504}505return field;506}507508public ObjectReference object() {509return object;510}511512public Value valueCurrent() {513if (object == null) {514return refType.getValue(field());515} else {516return object.getValue(field());517}518}519}520521class AccessWatchpointEventImpl extends WatchpointEventImpl522implements AccessWatchpointEvent {523524AccessWatchpointEventImpl(JDWP.Event.Composite.Events.FieldAccess evt) {525super(evt, evt.requestID, evt.thread, evt.location,526evt.refTypeTag, evt.typeID, evt.fieldID, evt.object);527}528529String eventName() {530return "AccessWatchpoint";531}532}533534class ModificationWatchpointEventImpl extends WatchpointEventImpl535implements ModificationWatchpointEvent {536Value newValue;537538ModificationWatchpointEventImpl(539JDWP.Event.Composite.Events.FieldModification evt) {540super(evt, evt.requestID, evt.thread, evt.location,541evt.refTypeTag, evt.typeID, evt.fieldID, evt.object);542this.newValue = evt.valueToBe;543}544545public Value valueToBe() {546return newValue;547}548549String eventName() {550return "ModificationWatchpoint";551}552}553554/**555* Events are constructed on the thread which reads all data from the556* transport. This means that the packet cannot be converted to real557* JDI objects as that may involve further communications with the558* back end which would deadlock.559*560* Hence the {@link #build()} method below called by EventQueue.561*/562EventSetImpl(VirtualMachine aVm, Packet pkt) {563super();564565// From "MirrorImpl":566// Yes, its a bit of a hack. But by doing it this567// way, this is the only place we have to change568// typing to substitute a new impl.569vm = (VirtualMachineImpl)aVm;570571this.pkt = pkt;572}573574/**575* Constructor for special events like VM disconnected576*/577EventSetImpl(VirtualMachine aVm, byte eventCmd) {578this(aVm, null);579suspendPolicy = JDWP.SuspendPolicy.NONE;580switch (eventCmd) {581case JDWP.EventKind.VM_DISCONNECTED:582addEvent(new VMDisconnectEventImpl());583break;584585default:586throw new InternalException("Bad singleton event code");587}588}589590private void addEvent(EventImpl evt) {591// Note that this class has a public add method that throws592// an exception so that clients can't modify the EventSet593super.add(evt);594}595596/*597* Complete the construction of an EventSet. This is called from598* an event handler thread. It upacks the JDWP events inside599* the packet and creates EventImpls for them. The EventSet is already600* on EventQueues when this is called, so it has to be synch.601*/602synchronized void build() {603if (pkt == null) {604return;605}606PacketStream ps = new PacketStream(vm, pkt);607JDWP.Event.Composite compEvt = new JDWP.Event.Composite(vm, ps);608suspendPolicy = compEvt.suspendPolicy;609if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {610switch(suspendPolicy) {611case JDWP.SuspendPolicy.ALL:612vm.printTrace("EventSet: SUSPEND_ALL");613break;614615case JDWP.SuspendPolicy.EVENT_THREAD:616vm.printTrace("EventSet: SUSPEND_EVENT_THREAD");617break;618619case JDWP.SuspendPolicy.NONE:620vm.printTrace("EventSet: SUSPEND_NONE");621break;622}623}624625ThreadReference fix6485605 = null;626for (int i = 0; i < compEvt.events.length; i++) {627EventImpl evt = createEvent(compEvt.events[i]);628if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {629try {630vm.printTrace("Event: " + evt);631} catch (VMDisconnectedException ee) {632// ignore - see bug 6502716633}634}635636switch (evt.destination()) {637case UNKNOWN_EVENT:638// Ignore disabled, deleted, unknown events, but639// save the thread if there is one since we might640// have to resume it. Note that events for different641// threads can't be in the same event set.642if (evt instanceof ThreadedEventImpl &&643suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) {644fix6485605 = ((ThreadedEventImpl)evt).thread();645}646continue;647case CLIENT_EVENT:648addEvent(evt);649break;650case INTERNAL_EVENT:651if (internalEventSet == null) {652internalEventSet = new EventSetImpl(this.vm, null);653}654internalEventSet.addEvent(evt);655break;656default:657throw new InternalException("Invalid event destination");658}659}660pkt = null; // No longer needed - free it up661662// Avoid hangs described in 6296125, 6293795663if (super.size() == 0) {664// This set has no client events. If we don't do665// needed resumes, no one else is going to.666if (suspendPolicy == JDWP.SuspendPolicy.ALL) {667vm.resume();668} else if (suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) {669// See bug 6485605.670if (fix6485605 != null) {671fix6485605.resume();672} else {673// apparently, there is nothing to resume.674}675}676suspendPolicy = JDWP.SuspendPolicy.NONE;677678}679680}681682/**683* Filter out internal events684*/685EventSet userFilter() {686return this;687}688689/**690* Filter out user events.691*/692EventSet internalFilter() {693return this.internalEventSet;694}695696EventImpl createEvent(JDWP.Event.Composite.Events evt) {697JDWP.Event.Composite.Events.EventsCommon comm = evt.aEventsCommon;698switch (evt.eventKind) {699case JDWP.EventKind.THREAD_START:700return new ThreadStartEventImpl(701(JDWP.Event.Composite.Events.ThreadStart)comm);702703case JDWP.EventKind.THREAD_END:704return new ThreadDeathEventImpl(705(JDWP.Event.Composite.Events.ThreadDeath)comm);706707case JDWP.EventKind.EXCEPTION:708return new ExceptionEventImpl(709(JDWP.Event.Composite.Events.Exception)comm);710711case JDWP.EventKind.BREAKPOINT:712return new BreakpointEventImpl(713(JDWP.Event.Composite.Events.Breakpoint)comm);714715case JDWP.EventKind.METHOD_ENTRY:716return new MethodEntryEventImpl(717(JDWP.Event.Composite.Events.MethodEntry)comm);718719case JDWP.EventKind.METHOD_EXIT:720return new MethodExitEventImpl(721(JDWP.Event.Composite.Events.MethodExit)comm);722723case JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE:724return new MethodExitEventImpl(725(JDWP.Event.Composite.Events.MethodExitWithReturnValue)comm);726727case JDWP.EventKind.FIELD_ACCESS:728return new AccessWatchpointEventImpl(729(JDWP.Event.Composite.Events.FieldAccess)comm);730731case JDWP.EventKind.FIELD_MODIFICATION:732return new ModificationWatchpointEventImpl(733(JDWP.Event.Composite.Events.FieldModification)comm);734735case JDWP.EventKind.SINGLE_STEP:736return new StepEventImpl(737(JDWP.Event.Composite.Events.SingleStep)comm);738739case JDWP.EventKind.CLASS_PREPARE:740return new ClassPrepareEventImpl(741(JDWP.Event.Composite.Events.ClassPrepare)comm);742743case JDWP.EventKind.CLASS_UNLOAD:744return new ClassUnloadEventImpl(745(JDWP.Event.Composite.Events.ClassUnload)comm);746747case JDWP.EventKind.MONITOR_CONTENDED_ENTER:748return new MonitorContendedEnterEventImpl(749(JDWP.Event.Composite.Events.MonitorContendedEnter)comm);750751case JDWP.EventKind.MONITOR_CONTENDED_ENTERED:752return new MonitorContendedEnteredEventImpl(753(JDWP.Event.Composite.Events.MonitorContendedEntered)comm);754755case JDWP.EventKind.MONITOR_WAIT:756return new MonitorWaitEventImpl(757(JDWP.Event.Composite.Events.MonitorWait)comm);758759case JDWP.EventKind.MONITOR_WAITED:760return new MonitorWaitedEventImpl(761(JDWP.Event.Composite.Events.MonitorWaited)comm);762763case JDWP.EventKind.VM_START:764return new VMStartEventImpl(765(JDWP.Event.Composite.Events.VMStart)comm);766767case JDWP.EventKind.VM_DEATH:768return new VMDeathEventImpl(769(JDWP.Event.Composite.Events.VMDeath)comm);770771default:772// Ignore unknown event types773System.err.println("Ignoring event cmd " +774evt.eventKind + " from the VM");775return null;776}777}778779public VirtualMachine virtualMachine() {780return vm;781}782783public int suspendPolicy() {784return EventRequestManagerImpl.JDWPtoJDISuspendPolicy(suspendPolicy);785}786787private ThreadReference eventThread() {788for (Event event : this) {789if (event instanceof ThreadedEventImpl) {790return ((ThreadedEventImpl)event).thread();791}792}793return null;794}795796public void resume() {797switch (suspendPolicy()) {798case EventRequest.SUSPEND_ALL:799vm.resume();800break;801case EventRequest.SUSPEND_EVENT_THREAD:802ThreadReference thread = eventThread();803if (thread == null) {804throw new InternalException("Inconsistent suspend policy");805}806thread.resume();807break;808case EventRequest.SUSPEND_NONE:809// Do nothing810break;811default:812throw new InternalException("Invalid suspend policy");813}814}815816public Iterator<Event> iterator() {817return new Itr();818}819820public EventIterator eventIterator() {821return new Itr();822}823824public class Itr implements EventIterator {825/**826* Index of element to be returned by subsequent call to next.827*/828int cursor = 0;829830public boolean hasNext() {831return cursor != size();832}833834public Event next() {835try {836Event nxt = get(cursor);837++cursor;838return nxt;839} catch(IndexOutOfBoundsException e) {840throw new NoSuchElementException();841}842}843844public Event nextEvent() {845return next();846}847848public void remove() {849throw new UnsupportedOperationException();850}851}852853@Override854public Spliterator<Event> spliterator() {855return Spliterators.spliterator(this, Spliterator.DISTINCT);856}857858/* below make this unmodifiable */859860public boolean add(Event o){861throw new UnsupportedOperationException();862}863public boolean remove(Object o) {864throw new UnsupportedOperationException();865}866public boolean addAll(Collection<? extends Event> coll) {867throw new UnsupportedOperationException();868}869public boolean removeAll(Collection<?> coll) {870throw new UnsupportedOperationException();871}872public boolean retainAll(Collection<?> coll) {873throw new UnsupportedOperationException();874}875public void clear() {876throw new UnsupportedOperationException();877}878}879880881