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