Home | History | Annotate | Download | only in jdi
      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 
     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 
     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      */
     78     public boolean equals(Object obj) {
     79         return this == obj;
     80     }
     81 
     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 
    101         EventRequestImpl() {
    102             super(EventRequestManagerImpl.this.vm);
    103         }
    104 
    105 
    106         /*
    107          * Override superclass back to default equality
    108          */
    109         public boolean equals(Object obj) {
    110             return this == obj;
    111         }
    112 
    113         public int hashCode() {
    114             return System.identityHashCode(this);
    115         }
    116 
    117         abstract int eventCmd();
    118 
    119         InvalidRequestStateException invalidState() {
    120             return new InvalidRequestStateException(toString());
    121         }
    122 
    123         String state() {
    124             return deleted? " (deleted)" :
    125                 (isEnabled()? " (enabled)" : " (disabled)");
    126         }
    127 
    128         /**
    129          * @return all the event request of this kind
    130          */
    131         List requestList() {
    132             return EventRequestManagerImpl.this.requestList(eventCmd());
    133         }
    134 
    135         /**
    136          * delete the event request
    137          */
    138         void delete() {
    139             if (!deleted) {
    140                 requestList().remove(this);
    141                 disable(); /* must do BEFORE delete */
    142                 deleted = true;
    143             }
    144         }
    145 
    146         public boolean isEnabled() {
    147             return isEnabled;
    148         }
    149 
    150         public void enable() {
    151             setEnabled(true);
    152         }
    153 
    154         public void disable() {
    155             setEnabled(false);
    156         }
    157 
    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 
    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 
    182         public void setSuspendPolicy(int policy) {
    183             if (isEnabled() || deleted) {
    184                 throw invalidState();
    185             }
    186             suspendPolicy = JDItoJDWPSuspendPolicy(policy);
    187         }
    188 
    189         public int suspendPolicy() {
    190             return JDWPtoJDISuspendPolicy(suspendPolicy);
    191         }
    192 
    193         /**
    194          * set (enable) the event request
    195          */
    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 
    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          */
    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          */
    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          */
    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 {
    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 {
    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 
    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 
    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 
    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 
    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 
    329         public Location location() {
    330             return location;
    331         }
    332 
    333         int eventCmd() {
    334             return JDWP.EventKind.BREAKPOINT;
    335         }
    336 
    337         public String toString() {
    338             return "breakpoint request " + location() + state();
    339         }
    340     }
    341 
    342     class ClassPrepareRequestImpl extends ClassVisibleEventRequestImpl
    343                                      implements ClassPrepareRequest {
    344         ClassPrepareRequestImpl() {
    345             requestList().add(this);
    346         }
    347 
    348         int eventCmd() {
    349             return JDWP.EventKind.CLASS_PREPARE;
    350         }
    351 
    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 
    368         public String toString() {
    369             return "class prepare request " + state();
    370         }
    371     }
    372 
    373     class ClassUnloadRequestImpl extends ClassVisibleEventRequestImpl
    374                                      implements ClassUnloadRequest {
    375         ClassUnloadRequestImpl() {
    376             requestList().add(this);
    377         }
    378 
    379         int eventCmd() {
    380             return JDWP.EventKind.CLASS_UNLOAD;
    381         }
    382 
    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 
    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 
    412         public ReferenceType exception() {
    413             return exception;
    414         }
    415 
    416         public boolean notifyCaught() {
    417             return caught;
    418         }
    419 
    420         public boolean notifyUncaught() {
    421             return uncaught;
    422         }
    423 
    424         int eventCmd() {
    425             return JDWP.EventKind.EXCEPTION;
    426         }
    427 
    428         public String toString() {
    429             return "exception request " + exception() + state();
    430         }
    431     }
    432 
    433     class MethodEntryRequestImpl extends ClassVisibleEventRequestImpl
    434                                       implements MethodEntryRequest {
    435         MethodEntryRequestImpl() {
    436             requestList().add(this);
    437         }
    438 
    439         int eventCmd() {
    440             return JDWP.EventKind.METHOD_ENTRY;
    441         }
    442 
    443         public String toString() {
    444             return "method entry request " + state();
    445         }
    446     }
    447 
    448     class MethodExitRequestImpl extends ClassVisibleEventRequestImpl
    449                                       implements MethodExitRequest {
    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 
    471         int eventCmd() {
    472             return EventRequestManagerImpl.methodExitEventCmd;
    473         }
    474 
    475         public String toString() {
    476             return "method exit request " + state();
    477         }
    478     }
    479 
    480     class MonitorContendedEnterRequestImpl extends ClassVisibleEventRequestImpl
    481                                       implements MonitorContendedEnterRequest {
    482         MonitorContendedEnterRequestImpl() {
    483             requestList().add(this);
    484         }
    485 
    486         int eventCmd() {
    487             return JDWP.EventKind.MONITOR_CONTENDED_ENTER;
    488         }
    489 
    490         public String toString() {
    491             return "monitor contended enter request " + state();
    492         }
    493     }
    494 
    495     class MonitorContendedEnteredRequestImpl extends ClassVisibleEventRequestImpl
    496                                       implements MonitorContendedEnteredRequest {
    497         MonitorContendedEnteredRequestImpl() {
    498             requestList().add(this);
    499         }
    500 
    501         int eventCmd() {
    502             return JDWP.EventKind.MONITOR_CONTENDED_ENTERED;
    503         }
    504 
    505         public String toString() {
    506             return "monitor contended entered request " + state();
    507         }
    508     }
    509 
    510     class MonitorWaitRequestImpl extends ClassVisibleEventRequestImpl
    511                                  implements MonitorWaitRequest {
    512         MonitorWaitRequestImpl() {
    513             requestList().add(this);
    514         }
    515 
    516         int eventCmd() {
    517             return JDWP.EventKind.MONITOR_WAIT;
    518         }
    519 
    520         public String toString() {
    521             return "monitor wait request " + state();
    522         }
    523     }
    524 
    525     class MonitorWaitedRequestImpl extends ClassVisibleEventRequestImpl
    526                                  implements MonitorWaitedRequest {
    527         MonitorWaitedRequestImpl() {
    528             requestList().add(this);
    529         }
    530 
    531         int eventCmd() {
    532             return JDWP.EventKind.MONITOR_WAITED;
    533         }
    534 
    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 
    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         }
    601         public int depth() {
    602             return depth;
    603         }
    604 
    605         public int size() {
    606             return size;
    607         }
    608 
    609         public ThreadReference thread() {
    610             return thread;
    611         }
    612 
    613         int eventCmd() {
    614             return JDWP.EventKind.SINGLE_STEP;
    615         }
    616 
    617         public String toString() {
    618             return "step request " + thread() + state();
    619         }
    620     }
    621 
    622     class ThreadDeathRequestImpl extends ThreadVisibleEventRequestImpl
    623                                       implements ThreadDeathRequest {
    624         ThreadDeathRequestImpl() {
    625             requestList().add(this);
    626         }
    627 
    628         int eventCmd() {
    629             return JDWP.EventKind.THREAD_DEATH;
    630         }
    631 
    632         public String toString() {
    633             return "thread death request " + state();
    634         }
    635     }
    636 
    637     class ThreadStartRequestImpl extends ThreadVisibleEventRequestImpl
    638                                       implements ThreadStartRequest {
    639         ThreadStartRequestImpl() {
    640             requestList().add(this);
    641         }
    642 
    643         int eventCmd() {
    644             return JDWP.EventKind.THREAD_START;
    645         }
    646 
    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 
    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 
    664         public Field field() {
    665             return field;
    666         }
    667     }
    668 
    669     class AccessWatchpointRequestImpl extends WatchpointRequestImpl
    670                                   implements AccessWatchpointRequest {
    671         AccessWatchpointRequestImpl(Field field) {
    672             super(field);
    673             requestList().add(this);
    674         }
    675 
    676         int eventCmd() {
    677             return JDWP.EventKind.FIELD_ACCESS;
    678         }
    679 
    680         public String toString() {
    681             return "access watchpoint request " + field + state();
    682         }
    683     }
    684 
    685     class ModificationWatchpointRequestImpl extends WatchpointRequestImpl
    686                                   implements ModificationWatchpointRequest {
    687         ModificationWatchpointRequestImpl(Field field) {
    688             super(field);
    689             requestList().add(this);
    690         }
    691 
    692         int eventCmd() {
    693             return JDWP.EventKind.FIELD_MODIFICATION;
    694         }
    695 
    696         public String toString() {
    697             return "modification watchpoint request " + field + state();
    698         }
    699     }
    700 
    701     class VMDeathRequestImpl extends EventRequestImpl
    702                                         implements VMDeathRequest {
    703         VMDeathRequestImpl() {
    704             requestList().add(this);
    705         }
    706 
    707         int eventCmd() {
    708             return JDWP.EventKind.VM_DEATH;
    709         }
    710 
    711         public String toString() {
    712             return "VM death request " + state();
    713         }
    714     }
    715 
    716     /**
    717      * Constructor.
    718      */
    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 
    741     public ClassPrepareRequest createClassPrepareRequest() {
    742         return new ClassPrepareRequestImpl();
    743     }
    744 
    745     public ClassUnloadRequest createClassUnloadRequest() {
    746         return new ClassUnloadRequestImpl();
    747     }
    748 
    749     public ExceptionRequest createExceptionRequest(ReferenceType refType,
    750                                                    boolean notifyCaught,
    751                                                    boolean notifyUncaught) {
    752         validateMirrorOrNull(refType);
    753         return new ExceptionRequestImpl(refType, notifyCaught, notifyUncaught);
    754     }
    755 
    756     public StepRequest createStepRequest(ThreadReference thread,
    757                                          int size, int depth) {
    758         validateMirror(thread);
    759         return new StepRequestImpl(thread, size, depth);
    760     }
    761 
    762     public ThreadDeathRequest createThreadDeathRequest() {
    763         return new ThreadDeathRequestImpl();
    764     }
    765 
    766     public ThreadStartRequest createThreadStartRequest() {
    767         return new ThreadStartRequestImpl();
    768     }
    769 
    770     public MethodEntryRequest createMethodEntryRequest() {
    771         return new MethodEntryRequestImpl();
    772     }
    773 
    774     public MethodExitRequest createMethodExitRequest() {
    775         return new MethodExitRequestImpl();
    776     }
    777 
    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 
    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 
    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 
    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 
    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
    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
    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 
    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 
    846     public void deleteEventRequest(EventRequest eventRequest) {
    847         validateMirror(eventRequest);
    848         ((EventRequestImpl)eventRequest).delete();
    849     }
    850 
    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 
    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 
    870     public List<StepRequest> stepRequests() {
    871         return (List<StepRequest>)unmodifiableRequestList(JDWP.EventKind.SINGLE_STEP);
    872     }
    873 
    874     public List<ClassPrepareRequest> classPrepareRequests() {
    875         return (List<ClassPrepareRequest>)unmodifiableRequestList(JDWP.EventKind.CLASS_PREPARE);
    876     }
    877 
    878     public List<ClassUnloadRequest> classUnloadRequests() {
    879         return (List<ClassUnloadRequest>)unmodifiableRequestList(JDWP.EventKind.CLASS_UNLOAD);
    880     }
    881 
    882     public List<ThreadStartRequest> threadStartRequests() {
    883         return (List<ThreadStartRequest>)unmodifiableRequestList(JDWP.EventKind.THREAD_START);
    884     }
    885 
    886     public List<ThreadDeathRequest> threadDeathRequests() {
    887         return (List<ThreadDeathRequest>)unmodifiableRequestList(JDWP.EventKind.THREAD_DEATH);
    888     }
    889 
    890     public List<ExceptionRequest> exceptionRequests() {
    891         return (List<ExceptionRequest>)unmodifiableRequestList(JDWP.EventKind.EXCEPTION);
    892     }
    893 
    894     public List<BreakpointRequest> breakpointRequests() {
    895         return (List<BreakpointRequest>)unmodifiableRequestList(JDWP.EventKind.BREAKPOINT);
    896     }
    897 
    898     public List<AccessWatchpointRequest> accessWatchpointRequests() {
    899         return (List<AccessWatchpointRequest>)unmodifiableRequestList(JDWP.EventKind.FIELD_ACCESS);
    900     }
    901 
    902     public List<ModificationWatchpointRequest> modificationWatchpointRequests() {
    903         return (List<ModificationWatchpointRequest>)unmodifiableRequestList(JDWP.EventKind.FIELD_MODIFICATION);
    904     }
    905 
    906     public List<MethodEntryRequest> methodEntryRequests() {
    907         return (List<MethodEntryRequest>)unmodifiableRequestList(JDWP.EventKind.METHOD_ENTRY);
    908     }
    909 
    910     public List<MethodExitRequest> methodExitRequests() {
    911         return (List<MethodExitRequest>)unmodifiableRequestList(
    912                                EventRequestManagerImpl.methodExitEventCmd);
    913     }
    914 
    915     public List<MonitorContendedEnterRequest> monitorContendedEnterRequests() {
    916         return (List<MonitorContendedEnterRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_CONTENDED_ENTER);
    917     }
    918 
    919     public List<MonitorContendedEnteredRequest> monitorContendedEnteredRequests() {
    920         return (List<MonitorContendedEnteredRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_CONTENDED_ENTERED);
    921     }
    922 
    923     public List<MonitorWaitRequest> monitorWaitRequests() {
    924         return (List<MonitorWaitRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_WAIT);
    925     }
    926 
    927     public List<MonitorWaitedRequest> monitorWaitedRequests() {
    928         return (List<MonitorWaitedRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_WAITED);
    929     }
    930 
    931     public List<VMDeathRequest> vmDeathRequests() {
    932         return (List<VMDeathRequest>)unmodifiableRequestList(JDWP.EventKind.VM_DEATH);
    933     }
    934 
    935     List<? extends EventRequest> unmodifiableRequestList(int eventCmd) {
    936         return Collections.unmodifiableList(requestList(eventCmd));
    937     }
    938 
    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 
    950     List<? extends EventRequest>  requestList(int eventCmd) {
    951         return requestLists[eventCmd];
    952     }
    953 
    954 }
    955