1 /*
2  * Copyright (c) 1998, 2011, 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 com.sun.jdi.*;
29 import com.sun.jdi.request.*;
30 import com.sun.tools.jdi.JDWP;
31 
32 import java.util.*;
33 
34 /**
35  * This interface is used to create and remove Breakpoints, Watchpoints,
36  * etc.
37  * It include implementations of all the request interfaces..
38  */
39 // Warnings from List filters and List[] requestLists is  hard to fix.
40 // Remove SuppressWarning when we fix the warnings from List filters
41 // and List[] requestLists. The generic array is not supported.
42 @SuppressWarnings("unchecked")
43 class EventRequestManagerImpl extends MirrorImpl
44                                        implements EventRequestManager
45 {
46     List<? extends EventRequest>[] requestLists;
47     private static int methodExitEventCmd = 0;
48 
JDWPtoJDISuspendPolicy(byte jdwpPolicy)49     static int JDWPtoJDISuspendPolicy(byte jdwpPolicy) {
50         switch(jdwpPolicy) {
51             case JDWP.SuspendPolicy.ALL:
52                 return EventRequest.SUSPEND_ALL;
53             case JDWP.SuspendPolicy.EVENT_THREAD:
54                 return EventRequest.SUSPEND_EVENT_THREAD;
55         case JDWP.SuspendPolicy.NONE:
56                 return EventRequest.SUSPEND_NONE;
57             default:
58                 throw new IllegalArgumentException("Illegal policy constant: " + jdwpPolicy);
59         }
60     }
61 
JDItoJDWPSuspendPolicy(int jdiPolicy)62     static byte JDItoJDWPSuspendPolicy(int jdiPolicy) {
63         switch(jdiPolicy) {
64             case EventRequest.SUSPEND_ALL:
65                 return JDWP.SuspendPolicy.ALL;
66             case EventRequest.SUSPEND_EVENT_THREAD:
67                 return JDWP.SuspendPolicy.EVENT_THREAD;
68             case EventRequest.SUSPEND_NONE:
69                 return JDWP.SuspendPolicy.NONE;
70             default:
71                 throw new IllegalArgumentException("Illegal policy constant: " + jdiPolicy);
72         }
73     }
74 
75     /*
76      * Override superclass back to default equality
77      */
equals(Object obj)78     public boolean equals(Object obj) {
79         return this == obj;
80     }
81 
hashCode()82     public int hashCode() {
83         return System.identityHashCode(this);
84     }
85 
86     abstract class EventRequestImpl extends MirrorImpl implements EventRequest {
87         int id;
88 
89         /*
90          * This list is not protected by a synchronized wrapper. All
91          * access/modification should be protected by synchronizing on
92          * the enclosing instance of EventRequestImpl.
93          */
94         List<Object> filters = new ArrayList<>();
95 
96         boolean isEnabled = false;
97         boolean deleted = false;
98         byte suspendPolicy = JDWP.SuspendPolicy.ALL;
99         private Map<Object, Object> clientProperties = null;
100 
EventRequestImpl()101         EventRequestImpl() {
102             super(EventRequestManagerImpl.this.vm);
103         }
104 
105 
106         /*
107          * Override superclass back to default equality
108          */
equals(Object obj)109         public boolean equals(Object obj) {
110             return this == obj;
111         }
112 
hashCode()113         public int hashCode() {
114             return System.identityHashCode(this);
115         }
116 
eventCmd()117         abstract int eventCmd();
118 
invalidState()119         InvalidRequestStateException invalidState() {
120             return new InvalidRequestStateException(toString());
121         }
122 
state()123         String state() {
124             return deleted? " (deleted)" :
125                 (isEnabled()? " (enabled)" : " (disabled)");
126         }
127 
128         /**
129          * @return all the event request of this kind
130          */
requestList()131         List requestList() {
132             return EventRequestManagerImpl.this.requestList(eventCmd());
133         }
134 
135         /**
136          * delete the event request
137          */
delete()138         void delete() {
139             if (!deleted) {
140                 requestList().remove(this);
141                 disable(); /* must do BEFORE delete */
142                 deleted = true;
143             }
144         }
145 
isEnabled()146         public boolean isEnabled() {
147             return isEnabled;
148         }
149 
enable()150         public void enable() {
151             setEnabled(true);
152         }
153 
disable()154         public void disable() {
155             setEnabled(false);
156         }
157 
setEnabled(boolean val)158         public synchronized void setEnabled(boolean val) {
159             if (deleted) {
160                 throw invalidState();
161             } else {
162                 if (val != isEnabled) {
163                     if (isEnabled) {
164                         clear();
165                     } else {
166                         set();
167                     }
168                 }
169             }
170         }
171 
addCountFilter(int count)172         public synchronized void addCountFilter(int count) {
173             if (isEnabled() || deleted) {
174                 throw invalidState();
175             }
176             if (count < 1) {
177                 throw new IllegalArgumentException("count is less than one");
178             }
179             filters.add(JDWP.EventRequest.Set.Modifier.Count.create(count));
180         }
181 
setSuspendPolicy(int policy)182         public void setSuspendPolicy(int policy) {
183             if (isEnabled() || deleted) {
184                 throw invalidState();
185             }
186             suspendPolicy = JDItoJDWPSuspendPolicy(policy);
187         }
188 
suspendPolicy()189         public int suspendPolicy() {
190             return JDWPtoJDISuspendPolicy(suspendPolicy);
191         }
192 
193         /**
194          * set (enable) the event request
195          */
set()196         synchronized void set() {
197             JDWP.EventRequest.Set.Modifier[] mods =
198                 filters.toArray(
199                     new JDWP.EventRequest.Set.Modifier[filters.size()]);
200             try {
201                 id = JDWP.EventRequest.Set.process(vm, (byte)eventCmd(),
202                                                    suspendPolicy, mods).requestID;
203             } catch (JDWPException exc) {
204                 throw exc.toJDIException();
205             }
206             isEnabled = true;
207         }
208 
clear()209         synchronized void clear() {
210             try {
211                 JDWP.EventRequest.Clear.process(vm, (byte)eventCmd(), id);
212             } catch (JDWPException exc) {
213                 throw exc.toJDIException();
214             }
215             isEnabled = false;
216         }
217 
218         /**
219          * @return a small Map
220          * @see #putProperty
221          * @see #getProperty
222          */
getProperties()223         private Map<Object, Object> getProperties() {
224             if (clientProperties == null) {
225                 clientProperties = new HashMap<Object, Object>(2);
226             }
227             return clientProperties;
228         }
229 
230         /**
231          * Returns the value of the property with the specified key.  Only
232          * properties added with <code>putProperty</code> will return
233          * a non-null value.
234          *
235          * @return the value of this property or null
236          * @see #putProperty
237          */
getProperty(Object key)238         public final Object getProperty(Object key) {
239             if (clientProperties == null) {
240                 return null;
241             } else {
242                 return getProperties().get(key);
243             }
244         }
245 
246         /**
247          * Add an arbitrary key/value "property" to this component.
248          *
249          * @see #getProperty
250          */
putProperty(Object key, Object value)251         public final void putProperty(Object key, Object value) {
252             if (value != null) {
253                 getProperties().put(key, value);
254             } else {
255                 getProperties().remove(key);
256             }
257         }
258     }
259 
260     abstract class ThreadVisibleEventRequestImpl extends EventRequestImpl {
addThreadFilter(ThreadReference thread)261         public synchronized void addThreadFilter(ThreadReference thread) {
262             validateMirror(thread);
263             if (isEnabled() || deleted) {
264                 throw invalidState();
265             }
266             filters.add(JDWP.EventRequest.Set.Modifier.ThreadOnly
267                                       .create((ThreadReferenceImpl)thread));
268         }
269     }
270 
271     abstract class ClassVisibleEventRequestImpl
272                                   extends ThreadVisibleEventRequestImpl {
addClassFilter(ReferenceType clazz)273         public synchronized void addClassFilter(ReferenceType clazz) {
274             validateMirror(clazz);
275             if (isEnabled() || deleted) {
276                 throw invalidState();
277             }
278             filters.add(JDWP.EventRequest.Set.Modifier.ClassOnly
279                                       .create((ReferenceTypeImpl)clazz));
280         }
281 
addClassFilter(String classPattern)282         public synchronized void addClassFilter(String classPattern) {
283             if (isEnabled() || deleted) {
284                 throw invalidState();
285             }
286             if (classPattern == null) {
287                 throw new NullPointerException();
288             }
289             filters.add(JDWP.EventRequest.Set.Modifier.ClassMatch
290                                       .create(classPattern));
291         }
292 
addClassExclusionFilter(String classPattern)293         public synchronized void addClassExclusionFilter(String classPattern) {
294             if (isEnabled() || deleted) {
295                 throw invalidState();
296             }
297             if (classPattern == null) {
298                 throw new NullPointerException();
299             }
300             filters.add(JDWP.EventRequest.Set.Modifier.ClassExclude
301                                       .create(classPattern));
302         }
303 
addInstanceFilter(ObjectReference instance)304         public synchronized void addInstanceFilter(ObjectReference instance) {
305             validateMirror(instance);
306             if (isEnabled() || deleted) {
307                 throw invalidState();
308             }
309             if (!vm.canUseInstanceFilters()) {
310                 throw new UnsupportedOperationException(
311                      "target does not support instance filters");
312             }
313             filters.add(JDWP.EventRequest.Set.Modifier.InstanceOnly
314                                       .create((ObjectReferenceImpl)instance));
315         }
316     }
317 
318     class BreakpointRequestImpl extends ClassVisibleEventRequestImpl
319                                      implements BreakpointRequest {
320         private final Location location;
321 
BreakpointRequestImpl(Location location)322         BreakpointRequestImpl(Location location) {
323             this.location = location;
324             filters.add(0,JDWP.EventRequest.Set.Modifier.LocationOnly
325                                                  .create(location));
326             requestList().add(this);
327         }
328 
location()329         public Location location() {
330             return location;
331         }
332 
eventCmd()333         int eventCmd() {
334             return JDWP.EventKind.BREAKPOINT;
335         }
336 
toString()337         public String toString() {
338             return "breakpoint request " + location() + state();
339         }
340     }
341 
342     class ClassPrepareRequestImpl extends ClassVisibleEventRequestImpl
343                                      implements ClassPrepareRequest {
ClassPrepareRequestImpl()344         ClassPrepareRequestImpl() {
345             requestList().add(this);
346         }
347 
eventCmd()348         int eventCmd() {
349             return JDWP.EventKind.CLASS_PREPARE;
350         }
351 
addSourceNameFilter(String sourceNamePattern)352         public synchronized void addSourceNameFilter(String sourceNamePattern) {
353             if (isEnabled() || deleted) {
354                 throw invalidState();
355             }
356             if (!vm.canUseSourceNameFilters()) {
357                 throw new UnsupportedOperationException(
358                      "target does not support source name filters");
359             }
360             if (sourceNamePattern == null) {
361                 throw new NullPointerException();
362             }
363 
364             filters.add(JDWP.EventRequest.Set.Modifier.SourceNameMatch
365                                       .create(sourceNamePattern));
366         }
367 
toString()368         public String toString() {
369             return "class prepare request " + state();
370         }
371     }
372 
373     class ClassUnloadRequestImpl extends ClassVisibleEventRequestImpl
374                                      implements ClassUnloadRequest {
ClassUnloadRequestImpl()375         ClassUnloadRequestImpl() {
376             requestList().add(this);
377         }
378 
eventCmd()379         int eventCmd() {
380             return JDWP.EventKind.CLASS_UNLOAD;
381         }
382 
toString()383         public String toString() {
384             return "class unload request " + state();
385         }
386     }
387 
388     class ExceptionRequestImpl extends ClassVisibleEventRequestImpl
389                                       implements ExceptionRequest {
390         ReferenceType exception = null;
391         boolean caught = true;
392         boolean uncaught = true;
393 
ExceptionRequestImpl(ReferenceType refType, boolean notifyCaught, boolean notifyUncaught)394         ExceptionRequestImpl(ReferenceType refType,
395                           boolean notifyCaught, boolean notifyUncaught) {
396             exception = refType;
397             caught = notifyCaught;
398             uncaught = notifyUncaught;
399             {
400                 ReferenceTypeImpl exc;
401                 if (exception == null) {
402                     exc = new ClassTypeImpl(vm, 0);
403                 } else {
404                     exc = (ReferenceTypeImpl)exception;
405                 }
406                 filters.add(JDWP.EventRequest.Set.Modifier.ExceptionOnly.
407                             create(exc, caught, uncaught));
408             }
409             requestList().add(this);
410         }
411 
exception()412         public ReferenceType exception() {
413             return exception;
414         }
415 
notifyCaught()416         public boolean notifyCaught() {
417             return caught;
418         }
419 
notifyUncaught()420         public boolean notifyUncaught() {
421             return uncaught;
422         }
423 
eventCmd()424         int eventCmd() {
425             return JDWP.EventKind.EXCEPTION;
426         }
427 
toString()428         public String toString() {
429             return "exception request " + exception() + state();
430         }
431     }
432 
433     class MethodEntryRequestImpl extends ClassVisibleEventRequestImpl
434                                       implements MethodEntryRequest {
MethodEntryRequestImpl()435         MethodEntryRequestImpl() {
436             requestList().add(this);
437         }
438 
eventCmd()439         int eventCmd() {
440             return JDWP.EventKind.METHOD_ENTRY;
441         }
442 
toString()443         public String toString() {
444             return "method entry request " + state();
445         }
446     }
447 
448     class MethodExitRequestImpl extends ClassVisibleEventRequestImpl
449                                       implements MethodExitRequest {
MethodExitRequestImpl()450         MethodExitRequestImpl() {
451             if (methodExitEventCmd == 0) {
452                 /*
453                  * If we can get return values, then we always get them.
454                  * Thus, for JDI MethodExitRequests, we always use the
455                  * same JDWP EventKind.  Here we decide which to use and
456                  * save it so that it will be used for all future
457                  * MethodExitRequests.
458                  *
459                  * This call to canGetMethodReturnValues can't
460                  * be done in the EventRequestManager ctor because that is too early.
461                  */
462                 if (vm.canGetMethodReturnValues()) {
463                     methodExitEventCmd = JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE;
464                 } else {
465                     methodExitEventCmd = JDWP.EventKind.METHOD_EXIT;
466                 }
467             }
468             requestList().add(this);
469         }
470 
eventCmd()471         int eventCmd() {
472             return EventRequestManagerImpl.methodExitEventCmd;
473         }
474 
toString()475         public String toString() {
476             return "method exit request " + state();
477         }
478     }
479 
480     class MonitorContendedEnterRequestImpl extends ClassVisibleEventRequestImpl
481                                       implements MonitorContendedEnterRequest {
MonitorContendedEnterRequestImpl()482         MonitorContendedEnterRequestImpl() {
483             requestList().add(this);
484         }
485 
eventCmd()486         int eventCmd() {
487             return JDWP.EventKind.MONITOR_CONTENDED_ENTER;
488         }
489 
toString()490         public String toString() {
491             return "monitor contended enter request " + state();
492         }
493     }
494 
495     class MonitorContendedEnteredRequestImpl extends ClassVisibleEventRequestImpl
496                                       implements MonitorContendedEnteredRequest {
MonitorContendedEnteredRequestImpl()497         MonitorContendedEnteredRequestImpl() {
498             requestList().add(this);
499         }
500 
eventCmd()501         int eventCmd() {
502             return JDWP.EventKind.MONITOR_CONTENDED_ENTERED;
503         }
504 
toString()505         public String toString() {
506             return "monitor contended entered request " + state();
507         }
508     }
509 
510     class MonitorWaitRequestImpl extends ClassVisibleEventRequestImpl
511                                  implements MonitorWaitRequest {
MonitorWaitRequestImpl()512         MonitorWaitRequestImpl() {
513             requestList().add(this);
514         }
515 
eventCmd()516         int eventCmd() {
517             return JDWP.EventKind.MONITOR_WAIT;
518         }
519 
toString()520         public String toString() {
521             return "monitor wait request " + state();
522         }
523     }
524 
525     class MonitorWaitedRequestImpl extends ClassVisibleEventRequestImpl
526                                  implements MonitorWaitedRequest {
MonitorWaitedRequestImpl()527         MonitorWaitedRequestImpl() {
528             requestList().add(this);
529         }
530 
eventCmd()531         int eventCmd() {
532             return JDWP.EventKind.MONITOR_WAITED;
533         }
534 
toString()535         public String toString() {
536             return "monitor waited request " + state();
537         }
538     }
539 
540     class StepRequestImpl extends ClassVisibleEventRequestImpl
541                                       implements StepRequest {
542         ThreadReferenceImpl thread;
543         int size;
544         int depth;
545 
StepRequestImpl(ThreadReference thread, int size, int depth)546         StepRequestImpl(ThreadReference thread, int size, int depth) {
547             this.thread = (ThreadReferenceImpl)thread;
548             this.size = size;
549             this.depth = depth;
550 
551             /*
552              * Translate size and depth to corresponding JDWP values.
553              */
554             int jdwpSize;
555             switch (size) {
556                 case STEP_MIN:
557                     jdwpSize = JDWP.StepSize.MIN;
558                     break;
559                 case STEP_LINE:
560                     jdwpSize = JDWP.StepSize.LINE;
561                     break;
562                 default:
563                     throw new IllegalArgumentException("Invalid step size");
564             }
565 
566             int jdwpDepth;
567             switch (depth) {
568                 case STEP_INTO:
569                     jdwpDepth = JDWP.StepDepth.INTO;
570                     break;
571                 case STEP_OVER:
572                     jdwpDepth = JDWP.StepDepth.OVER;
573                     break;
574                 case STEP_OUT:
575                     jdwpDepth = JDWP.StepDepth.OUT;
576                     break;
577                 default:
578                     throw new IllegalArgumentException("Invalid step depth");
579             }
580 
581             /*
582              * Make sure this isn't a duplicate
583              */
584             List<StepRequest> requests = stepRequests();
585             Iterator<StepRequest> iter = requests.iterator();
586             while (iter.hasNext()) {
587                 StepRequest request = iter.next();
588                 if ((request != this) &&
589                         request.isEnabled() &&
590                         request.thread().equals(thread)) {
591                     throw new DuplicateRequestException(
592                         "Only one step request allowed per thread");
593                 }
594             }
595 
596             filters.add(JDWP.EventRequest.Set.Modifier.Step.
597                         create(this.thread, jdwpSize, jdwpDepth));
598             requestList().add(this);
599 
600         }
depth()601         public int depth() {
602             return depth;
603         }
604 
size()605         public int size() {
606             return size;
607         }
608 
thread()609         public ThreadReference thread() {
610             return thread;
611         }
612 
eventCmd()613         int eventCmd() {
614             return JDWP.EventKind.SINGLE_STEP;
615         }
616 
toString()617         public String toString() {
618             return "step request " + thread() + state();
619         }
620     }
621 
622     class ThreadDeathRequestImpl extends ThreadVisibleEventRequestImpl
623                                       implements ThreadDeathRequest {
ThreadDeathRequestImpl()624         ThreadDeathRequestImpl() {
625             requestList().add(this);
626         }
627 
eventCmd()628         int eventCmd() {
629             return JDWP.EventKind.THREAD_DEATH;
630         }
631 
toString()632         public String toString() {
633             return "thread death request " + state();
634         }
635     }
636 
637     class ThreadStartRequestImpl extends ThreadVisibleEventRequestImpl
638                                       implements ThreadStartRequest {
ThreadStartRequestImpl()639         ThreadStartRequestImpl() {
640             requestList().add(this);
641         }
642 
eventCmd()643         int eventCmd() {
644             return JDWP.EventKind.THREAD_START;
645         }
646 
toString()647         public String toString() {
648             return "thread start request " + state();
649         }
650     }
651 
652     abstract class WatchpointRequestImpl extends ClassVisibleEventRequestImpl
653                                       implements WatchpointRequest {
654         final Field field;
655 
WatchpointRequestImpl(Field field)656         WatchpointRequestImpl(Field field) {
657             this.field = field;
658             filters.add(0,
659                    JDWP.EventRequest.Set.Modifier.FieldOnly.create(
660                     (ReferenceTypeImpl)field.declaringType(),
661                     ((FieldImpl)field).ref()));
662         }
663 
field()664         public Field field() {
665             return field;
666         }
667     }
668 
669     class AccessWatchpointRequestImpl extends WatchpointRequestImpl
670                                   implements AccessWatchpointRequest {
AccessWatchpointRequestImpl(Field field)671         AccessWatchpointRequestImpl(Field field) {
672             super(field);
673             requestList().add(this);
674         }
675 
eventCmd()676         int eventCmd() {
677             return JDWP.EventKind.FIELD_ACCESS;
678         }
679 
toString()680         public String toString() {
681             return "access watchpoint request " + field + state();
682         }
683     }
684 
685     class ModificationWatchpointRequestImpl extends WatchpointRequestImpl
686                                   implements ModificationWatchpointRequest {
ModificationWatchpointRequestImpl(Field field)687         ModificationWatchpointRequestImpl(Field field) {
688             super(field);
689             requestList().add(this);
690         }
691 
eventCmd()692         int eventCmd() {
693             return JDWP.EventKind.FIELD_MODIFICATION;
694         }
695 
toString()696         public String toString() {
697             return "modification watchpoint request " + field + state();
698         }
699     }
700 
701     class VMDeathRequestImpl extends EventRequestImpl
702                                         implements VMDeathRequest {
VMDeathRequestImpl()703         VMDeathRequestImpl() {
704             requestList().add(this);
705         }
706 
eventCmd()707         int eventCmd() {
708             return JDWP.EventKind.VM_DEATH;
709         }
710 
toString()711         public String toString() {
712             return "VM death request " + state();
713         }
714     }
715 
716     /**
717      * Constructor.
718      */
EventRequestManagerImpl(VirtualMachine vm)719     EventRequestManagerImpl(VirtualMachine vm) {
720         super(vm);
721         java.lang.reflect.Field[] ekinds =
722             JDWP.EventKind.class.getDeclaredFields();
723         int highest = 0;
724         for (int i = 0; i < ekinds.length; ++i) {
725             int val;
726             try {
727                 val = ekinds[i].getInt(null);
728             } catch (IllegalAccessException exc) {
729                 throw new RuntimeException("Got: " + exc);
730             }
731             if (val > highest) {
732                 highest = val;
733             }
734         }
735         requestLists = new List[highest+1];
736         for (int i=0; i <= highest; i++) {
737             requestLists[i] = new ArrayList<>();
738         }
739     }
740 
createClassPrepareRequest()741     public ClassPrepareRequest createClassPrepareRequest() {
742         return new ClassPrepareRequestImpl();
743     }
744 
createClassUnloadRequest()745     public ClassUnloadRequest createClassUnloadRequest() {
746         return new ClassUnloadRequestImpl();
747     }
748 
createExceptionRequest(ReferenceType refType, boolean notifyCaught, boolean notifyUncaught)749     public ExceptionRequest createExceptionRequest(ReferenceType refType,
750                                                    boolean notifyCaught,
751                                                    boolean notifyUncaught) {
752         validateMirrorOrNull(refType);
753         return new ExceptionRequestImpl(refType, notifyCaught, notifyUncaught);
754     }
755 
createStepRequest(ThreadReference thread, int size, int depth)756     public StepRequest createStepRequest(ThreadReference thread,
757                                          int size, int depth) {
758         validateMirror(thread);
759         return new StepRequestImpl(thread, size, depth);
760     }
761 
createThreadDeathRequest()762     public ThreadDeathRequest createThreadDeathRequest() {
763         return new ThreadDeathRequestImpl();
764     }
765 
createThreadStartRequest()766     public ThreadStartRequest createThreadStartRequest() {
767         return new ThreadStartRequestImpl();
768     }
769 
createMethodEntryRequest()770     public MethodEntryRequest createMethodEntryRequest() {
771         return new MethodEntryRequestImpl();
772     }
773 
createMethodExitRequest()774     public MethodExitRequest createMethodExitRequest() {
775         return new MethodExitRequestImpl();
776     }
777 
createMonitorContendedEnterRequest()778     public MonitorContendedEnterRequest createMonitorContendedEnterRequest() {
779         if (!vm.canRequestMonitorEvents()) {
780             throw new UnsupportedOperationException(
781           "target VM does not support requesting Monitor events");
782         }
783         return new MonitorContendedEnterRequestImpl();
784     }
785 
createMonitorContendedEnteredRequest()786     public MonitorContendedEnteredRequest createMonitorContendedEnteredRequest() {
787         if (!vm.canRequestMonitorEvents()) {
788             throw new UnsupportedOperationException(
789           "target VM does not support requesting Monitor events");
790         }
791         return new MonitorContendedEnteredRequestImpl();
792     }
793 
createMonitorWaitRequest()794     public MonitorWaitRequest createMonitorWaitRequest() {
795         if (!vm.canRequestMonitorEvents()) {
796             throw new UnsupportedOperationException(
797           "target VM does not support requesting Monitor events");
798         }
799         return new MonitorWaitRequestImpl();
800     }
801 
createMonitorWaitedRequest()802     public MonitorWaitedRequest createMonitorWaitedRequest() {
803         if (!vm.canRequestMonitorEvents()) {
804             throw new UnsupportedOperationException(
805           "target VM does not support requesting Monitor events");
806         }
807         return new MonitorWaitedRequestImpl();
808     }
809 
createBreakpointRequest(Location location)810     public BreakpointRequest createBreakpointRequest(Location location) {
811         validateMirror(location);
812         if (location.codeIndex() == -1) {
813             throw new NativeMethodException("Cannot set breakpoints on native methods");
814         }
815         return new BreakpointRequestImpl(location);
816     }
817 
818     public AccessWatchpointRequest
createAccessWatchpointRequest(Field field)819                               createAccessWatchpointRequest(Field field) {
820         validateMirror(field);
821         if (!vm.canWatchFieldAccess()) {
822             throw new UnsupportedOperationException(
823           "target VM does not support access watchpoints");
824         }
825         return new AccessWatchpointRequestImpl(field);
826     }
827 
828     public ModificationWatchpointRequest
createModificationWatchpointRequest(Field field)829                         createModificationWatchpointRequest(Field field) {
830         validateMirror(field);
831         if (!vm.canWatchFieldModification()) {
832             throw new UnsupportedOperationException(
833           "target VM does not support modification watchpoints");
834         }
835         return new ModificationWatchpointRequestImpl(field);
836     }
837 
createVMDeathRequest()838     public VMDeathRequest createVMDeathRequest() {
839         if (!vm.canRequestVMDeathEvent()) {
840             throw new UnsupportedOperationException(
841           "target VM does not support requesting VM death events");
842         }
843         return new VMDeathRequestImpl();
844     }
845 
deleteEventRequest(EventRequest eventRequest)846     public void deleteEventRequest(EventRequest eventRequest) {
847         validateMirror(eventRequest);
848         ((EventRequestImpl)eventRequest).delete();
849     }
850 
deleteEventRequests(List<? extends EventRequest> eventRequests)851     public void deleteEventRequests(List<? extends EventRequest> eventRequests) {
852         validateMirrors(eventRequests);
853         // copy the eventRequests to avoid ConcurrentModificationException
854         Iterator<? extends EventRequest> iter = (new ArrayList<>(eventRequests)).iterator();
855         while (iter.hasNext()) {
856             ((EventRequestImpl)iter.next()).delete();
857         }
858     }
859 
deleteAllBreakpoints()860     public void deleteAllBreakpoints() {
861         requestList(JDWP.EventKind.BREAKPOINT).clear();
862 
863         try {
864             JDWP.EventRequest.ClearAllBreakpoints.process(vm);
865         } catch (JDWPException exc) {
866             throw exc.toJDIException();
867         }
868     }
869 
stepRequests()870     public List<StepRequest> stepRequests() {
871         return (List<StepRequest>)unmodifiableRequestList(JDWP.EventKind.SINGLE_STEP);
872     }
873 
classPrepareRequests()874     public List<ClassPrepareRequest> classPrepareRequests() {
875         return (List<ClassPrepareRequest>)unmodifiableRequestList(JDWP.EventKind.CLASS_PREPARE);
876     }
877 
classUnloadRequests()878     public List<ClassUnloadRequest> classUnloadRequests() {
879         return (List<ClassUnloadRequest>)unmodifiableRequestList(JDWP.EventKind.CLASS_UNLOAD);
880     }
881 
threadStartRequests()882     public List<ThreadStartRequest> threadStartRequests() {
883         return (List<ThreadStartRequest>)unmodifiableRequestList(JDWP.EventKind.THREAD_START);
884     }
885 
threadDeathRequests()886     public List<ThreadDeathRequest> threadDeathRequests() {
887         return (List<ThreadDeathRequest>)unmodifiableRequestList(JDWP.EventKind.THREAD_DEATH);
888     }
889 
exceptionRequests()890     public List<ExceptionRequest> exceptionRequests() {
891         return (List<ExceptionRequest>)unmodifiableRequestList(JDWP.EventKind.EXCEPTION);
892     }
893 
breakpointRequests()894     public List<BreakpointRequest> breakpointRequests() {
895         return (List<BreakpointRequest>)unmodifiableRequestList(JDWP.EventKind.BREAKPOINT);
896     }
897 
accessWatchpointRequests()898     public List<AccessWatchpointRequest> accessWatchpointRequests() {
899         return (List<AccessWatchpointRequest>)unmodifiableRequestList(JDWP.EventKind.FIELD_ACCESS);
900     }
901 
modificationWatchpointRequests()902     public List<ModificationWatchpointRequest> modificationWatchpointRequests() {
903         return (List<ModificationWatchpointRequest>)unmodifiableRequestList(JDWP.EventKind.FIELD_MODIFICATION);
904     }
905 
methodEntryRequests()906     public List<MethodEntryRequest> methodEntryRequests() {
907         return (List<MethodEntryRequest>)unmodifiableRequestList(JDWP.EventKind.METHOD_ENTRY);
908     }
909 
methodExitRequests()910     public List<MethodExitRequest> methodExitRequests() {
911         return (List<MethodExitRequest>)unmodifiableRequestList(
912                                EventRequestManagerImpl.methodExitEventCmd);
913     }
914 
monitorContendedEnterRequests()915     public List<MonitorContendedEnterRequest> monitorContendedEnterRequests() {
916         return (List<MonitorContendedEnterRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_CONTENDED_ENTER);
917     }
918 
monitorContendedEnteredRequests()919     public List<MonitorContendedEnteredRequest> monitorContendedEnteredRequests() {
920         return (List<MonitorContendedEnteredRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_CONTENDED_ENTERED);
921     }
922 
monitorWaitRequests()923     public List<MonitorWaitRequest> monitorWaitRequests() {
924         return (List<MonitorWaitRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_WAIT);
925     }
926 
monitorWaitedRequests()927     public List<MonitorWaitedRequest> monitorWaitedRequests() {
928         return (List<MonitorWaitedRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_WAITED);
929     }
930 
vmDeathRequests()931     public List<VMDeathRequest> vmDeathRequests() {
932         return (List<VMDeathRequest>)unmodifiableRequestList(JDWP.EventKind.VM_DEATH);
933     }
934 
unmodifiableRequestList(int eventCmd)935     List<? extends EventRequest> unmodifiableRequestList(int eventCmd) {
936         return Collections.unmodifiableList(requestList(eventCmd));
937     }
938 
request(int eventCmd, int requestId)939     EventRequest request(int eventCmd, int requestId) {
940         List<? extends EventRequest> rl = requestList(eventCmd);
941         for (int i = rl.size() - 1; i >= 0; i--) {
942             EventRequestImpl er = (EventRequestImpl)rl.get(i);
943             if (er.id == requestId) {
944                 return er;
945             }
946         }
947         return null;
948     }
949 
requestList(int eventCmd)950     List<? extends EventRequest>  requestList(int eventCmd) {
951         return requestLists[eventCmd];
952     }
953 
954 }
955