Path: blob/master/src/jdk.jdi/share/classes/com/sun/tools/jdi/EventRequestManagerImpl.java
41161 views
/*1* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.jdi;2627import java.util.ArrayList;28import java.util.Collections;29import java.util.HashMap;30import java.util.Iterator;31import java.util.List;32import java.util.Map;3334import com.sun.jdi.Field;35import com.sun.jdi.Location;36import com.sun.jdi.NativeMethodException;37import com.sun.jdi.ObjectReference;38import com.sun.jdi.ReferenceType;39import com.sun.jdi.ThreadReference;40import com.sun.jdi.VirtualMachine;41import com.sun.jdi.request.AccessWatchpointRequest;42import com.sun.jdi.request.BreakpointRequest;43import com.sun.jdi.request.ClassPrepareRequest;44import com.sun.jdi.request.ClassUnloadRequest;45import com.sun.jdi.request.DuplicateRequestException;46import com.sun.jdi.request.EventRequest;47import com.sun.jdi.request.EventRequestManager;48import com.sun.jdi.request.ExceptionRequest;49import com.sun.jdi.request.InvalidRequestStateException;50import com.sun.jdi.request.MethodEntryRequest;51import com.sun.jdi.request.MethodExitRequest;52import com.sun.jdi.request.ModificationWatchpointRequest;53import com.sun.jdi.request.MonitorContendedEnterRequest;54import com.sun.jdi.request.MonitorContendedEnteredRequest;55import com.sun.jdi.request.MonitorWaitRequest;56import com.sun.jdi.request.MonitorWaitedRequest;57import com.sun.jdi.request.StepRequest;58import com.sun.jdi.request.ThreadDeathRequest;59import com.sun.jdi.request.ThreadStartRequest;60import com.sun.jdi.request.VMDeathRequest;61import com.sun.jdi.request.WatchpointRequest;6263/**64* This interface is used to create and remove Breakpoints, Watchpoints,65* etc.66* It include implementations of all the request interfaces..67*/68// Warnings from List filters and List[] requestLists is hard to fix.69// Remove SuppressWarning when we fix the warnings from List filters70// and List[] requestLists. The generic array is not supported.71@SuppressWarnings({"unchecked", "rawtypes"})72class EventRequestManagerImpl extends MirrorImpl73implements EventRequestManager74{75private final List<? extends EventRequest>[] requestLists;76private static int methodExitEventCmd = 0;7778static int JDWPtoJDISuspendPolicy(byte jdwpPolicy) {79switch(jdwpPolicy) {80case JDWP.SuspendPolicy.ALL:81return EventRequest.SUSPEND_ALL;82case JDWP.SuspendPolicy.EVENT_THREAD:83return EventRequest.SUSPEND_EVENT_THREAD;84case JDWP.SuspendPolicy.NONE:85return EventRequest.SUSPEND_NONE;86default:87throw new IllegalArgumentException("Illegal policy constant: " + jdwpPolicy);88}89}9091static byte JDItoJDWPSuspendPolicy(int jdiPolicy) {92switch(jdiPolicy) {93case EventRequest.SUSPEND_ALL:94return JDWP.SuspendPolicy.ALL;95case EventRequest.SUSPEND_EVENT_THREAD:96return JDWP.SuspendPolicy.EVENT_THREAD;97case EventRequest.SUSPEND_NONE:98return JDWP.SuspendPolicy.NONE;99default:100throw new IllegalArgumentException("Illegal policy constant: " + jdiPolicy);101}102}103104/*105* Override superclass back to default equality106*/107public boolean equals(Object obj) {108return this == obj;109}110111public int hashCode() {112return System.identityHashCode(this);113}114115private abstract class EventRequestImpl extends MirrorImpl implements EventRequest {116int id;117118/*119* This list is not protected by a synchronized wrapper. All120* access/modification should be protected by synchronizing on121* the enclosing instance of EventRequestImpl.122*/123List<Object> filters = new ArrayList<>();124125boolean isEnabled = false;126boolean deleted = false;127byte suspendPolicy = JDWP.SuspendPolicy.ALL;128private Map<Object, Object> clientProperties = null;129130EventRequestImpl() {131super(EventRequestManagerImpl.this.vm);132}133134/*135* Override superclass back to default equality136*/137public boolean equals(Object obj) {138return this == obj;139}140141public int hashCode() {142return System.identityHashCode(this);143}144145abstract int eventCmd();146147InvalidRequestStateException invalidState() {148return new InvalidRequestStateException(toString());149}150151String state() {152return deleted? " (deleted)" :153(isEnabled()? " (enabled)" : " (disabled)");154}155156/**157* @return all the event request of this kind158*/159List requestList() {160return EventRequestManagerImpl.this.requestList(eventCmd());161}162163/**164* delete the event request165*/166void delete() {167if (!deleted) {168requestList().remove(this);169disable(); /* must do BEFORE delete */170deleted = true;171}172}173174public boolean isEnabled() {175return isEnabled;176}177178public void enable() {179setEnabled(true);180}181182public void disable() {183setEnabled(false);184}185186public synchronized void setEnabled(boolean val) {187if (deleted) {188throw invalidState();189} else {190if (val != isEnabled) {191if (isEnabled) {192clear();193} else {194set();195}196}197}198}199200public synchronized void addCountFilter(int count) {201if (isEnabled() || deleted) {202throw invalidState();203}204if (count < 1) {205throw new IllegalArgumentException("count is less than one");206}207filters.add(JDWP.EventRequest.Set.Modifier.Count.create(count));208}209210public void setSuspendPolicy(int policy) {211if (isEnabled() || deleted) {212throw invalidState();213}214suspendPolicy = JDItoJDWPSuspendPolicy(policy);215}216217public int suspendPolicy() {218return JDWPtoJDISuspendPolicy(suspendPolicy);219}220221/**222* set (enable) the event request223*/224synchronized void set() {225JDWP.EventRequest.Set.Modifier[] mods =226filters.toArray(227new JDWP.EventRequest.Set.Modifier[filters.size()]);228try {229id = JDWP.EventRequest.Set.process(vm, (byte)eventCmd(),230suspendPolicy, mods).requestID;231} catch (JDWPException exc) {232throw exc.toJDIException();233}234isEnabled = true;235}236237synchronized void clear() {238try {239JDWP.EventRequest.Clear.process(vm, (byte)eventCmd(), id);240} catch (JDWPException exc) {241throw exc.toJDIException();242}243isEnabled = false;244}245246/**247* @return a small Map248* @see #putProperty249* @see #getProperty250*/251private Map<Object, Object> getProperties() {252if (clientProperties == null) {253clientProperties = new HashMap<>(2);254}255return clientProperties;256}257258/**259* Returns the value of the property with the specified key. Only260* properties added with <code>putProperty</code> will return261* a non-null value.262*263* @return the value of this property or null264* @see #putProperty265*/266public final Object getProperty(Object key) {267if (clientProperties == null) {268return null;269} else {270return getProperties().get(key);271}272}273274/**275* Add an arbitrary key/value "property" to this component.276*277* @see #getProperty278*/279public final void putProperty(Object key, Object value) {280if (value != null) {281getProperties().put(key, value);282} else {283getProperties().remove(key);284}285}286}287288abstract class ThreadVisibleEventRequestImpl extends EventRequestImpl {289public synchronized void addThreadFilter(ThreadReference thread) {290validateMirror(thread);291if (isEnabled() || deleted) {292throw invalidState();293}294filters.add(JDWP.EventRequest.Set.Modifier.ThreadOnly295.create((ThreadReferenceImpl)thread));296}297}298299abstract class ClassVisibleEventRequestImpl300extends ThreadVisibleEventRequestImpl {301public synchronized void addClassFilter(ReferenceType clazz) {302validateMirror(clazz);303if (isEnabled() || deleted) {304throw invalidState();305}306filters.add(JDWP.EventRequest.Set.Modifier.ClassOnly307.create((ReferenceTypeImpl)clazz));308}309310public synchronized void addClassFilter(String classPattern) {311if (isEnabled() || deleted) {312throw invalidState();313}314if (classPattern == null) {315throw new NullPointerException();316}317filters.add(JDWP.EventRequest.Set.Modifier.ClassMatch318.create(classPattern));319}320321public synchronized void addClassExclusionFilter(String classPattern) {322if (isEnabled() || deleted) {323throw invalidState();324}325if (classPattern == null) {326throw new NullPointerException();327}328filters.add(JDWP.EventRequest.Set.Modifier.ClassExclude329.create(classPattern));330}331332public synchronized void addInstanceFilter(ObjectReference instance) {333validateMirror(instance);334if (isEnabled() || deleted) {335throw invalidState();336}337if (!vm.canUseInstanceFilters()) {338throw new UnsupportedOperationException(339"target does not support instance filters");340}341filters.add(JDWP.EventRequest.Set.Modifier.InstanceOnly342.create((ObjectReferenceImpl)instance));343}344}345346class BreakpointRequestImpl extends ClassVisibleEventRequestImpl347implements BreakpointRequest {348private final Location location;349350BreakpointRequestImpl(Location location) {351this.location = location;352filters.add(0,JDWP.EventRequest.Set.Modifier.LocationOnly353.create(location));354requestList().add(this);355}356357public Location location() {358return location;359}360361int eventCmd() {362return JDWP.EventKind.BREAKPOINT;363}364365public String toString() {366return "breakpoint request " + location() + state();367}368}369370class ClassPrepareRequestImpl extends ClassVisibleEventRequestImpl371implements ClassPrepareRequest {372ClassPrepareRequestImpl() {373requestList().add(this);374}375376int eventCmd() {377return JDWP.EventKind.CLASS_PREPARE;378}379380public synchronized void addSourceNameFilter(String sourceNamePattern) {381if (isEnabled() || deleted) {382throw invalidState();383}384if (!vm.canUseSourceNameFilters()) {385throw new UnsupportedOperationException(386"target does not support source name filters");387}388if (sourceNamePattern == null) {389throw new NullPointerException();390}391392filters.add(JDWP.EventRequest.Set.Modifier.SourceNameMatch393.create(sourceNamePattern));394}395396public String toString() {397return "class prepare request " + state();398}399}400401class ClassUnloadRequestImpl extends ClassVisibleEventRequestImpl402implements ClassUnloadRequest {403ClassUnloadRequestImpl() {404requestList().add(this);405}406407int eventCmd() {408return JDWP.EventKind.CLASS_UNLOAD;409}410411public String toString() {412return "class unload request " + state();413}414}415416class ExceptionRequestImpl extends ClassVisibleEventRequestImpl417implements ExceptionRequest {418ReferenceType exception = null;419boolean caught = true;420boolean uncaught = true;421422ExceptionRequestImpl(ReferenceType refType,423boolean notifyCaught, boolean notifyUncaught) {424exception = refType;425caught = notifyCaught;426uncaught = notifyUncaught;427{428ReferenceTypeImpl exc;429if (exception == null) {430exc = new ClassTypeImpl(vm, 0);431} else {432exc = (ReferenceTypeImpl)exception;433}434filters.add(JDWP.EventRequest.Set.Modifier.ExceptionOnly.435create(exc, caught, uncaught));436}437requestList().add(this);438}439440public ReferenceType exception() {441return exception;442}443444public boolean notifyCaught() {445return caught;446}447448public boolean notifyUncaught() {449return uncaught;450}451452int eventCmd() {453return JDWP.EventKind.EXCEPTION;454}455456public String toString() {457return "exception request " + exception() + state();458}459}460461class MethodEntryRequestImpl extends ClassVisibleEventRequestImpl462implements MethodEntryRequest {463MethodEntryRequestImpl() {464requestList().add(this);465}466467int eventCmd() {468return JDWP.EventKind.METHOD_ENTRY;469}470471public String toString() {472return "method entry request " + state();473}474}475476class MethodExitRequestImpl extends ClassVisibleEventRequestImpl477implements MethodExitRequest {478MethodExitRequestImpl() {479if (methodExitEventCmd == 0) {480/*481* If we can get return values, then we always get them.482* Thus, for JDI MethodExitRequests, we always use the483* same JDWP EventKind. Here we decide which to use and484* save it so that it will be used for all future485* MethodExitRequests.486*487* This call to canGetMethodReturnValues can't488* be done in the EventRequestManager ctor because that is too early.489*/490if (vm.canGetMethodReturnValues()) {491methodExitEventCmd = JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE;492} else {493methodExitEventCmd = JDWP.EventKind.METHOD_EXIT;494}495}496requestList().add(this);497}498499int eventCmd() {500return EventRequestManagerImpl.methodExitEventCmd;501}502503public String toString() {504return "method exit request " + state();505}506}507508class MonitorContendedEnterRequestImpl extends ClassVisibleEventRequestImpl509implements MonitorContendedEnterRequest {510MonitorContendedEnterRequestImpl() {511requestList().add(this);512}513514int eventCmd() {515return JDWP.EventKind.MONITOR_CONTENDED_ENTER;516}517518public String toString() {519return "monitor contended enter request " + state();520}521}522523class MonitorContendedEnteredRequestImpl extends ClassVisibleEventRequestImpl524implements MonitorContendedEnteredRequest {525MonitorContendedEnteredRequestImpl() {526requestList().add(this);527}528529int eventCmd() {530return JDWP.EventKind.MONITOR_CONTENDED_ENTERED;531}532533public String toString() {534return "monitor contended entered request " + state();535}536}537538class MonitorWaitRequestImpl extends ClassVisibleEventRequestImpl539implements MonitorWaitRequest {540MonitorWaitRequestImpl() {541requestList().add(this);542}543544int eventCmd() {545return JDWP.EventKind.MONITOR_WAIT;546}547548public String toString() {549return "monitor wait request " + state();550}551}552553class MonitorWaitedRequestImpl extends ClassVisibleEventRequestImpl554implements MonitorWaitedRequest {555MonitorWaitedRequestImpl() {556requestList().add(this);557}558559int eventCmd() {560return JDWP.EventKind.MONITOR_WAITED;561}562563public String toString() {564return "monitor waited request " + state();565}566}567568class StepRequestImpl extends ClassVisibleEventRequestImpl569implements StepRequest {570ThreadReferenceImpl thread;571int size;572int depth;573574StepRequestImpl(ThreadReference thread, int size, int depth) {575this.thread = (ThreadReferenceImpl)thread;576this.size = size;577this.depth = depth;578579/*580* Translate size and depth to corresponding JDWP values.581*/582int jdwpSize;583switch (size) {584case STEP_MIN:585jdwpSize = JDWP.StepSize.MIN;586break;587case STEP_LINE:588jdwpSize = JDWP.StepSize.LINE;589break;590default:591throw new IllegalArgumentException("Invalid step size");592}593594int jdwpDepth;595switch (depth) {596case STEP_INTO:597jdwpDepth = JDWP.StepDepth.INTO;598break;599case STEP_OVER:600jdwpDepth = JDWP.StepDepth.OVER;601break;602case STEP_OUT:603jdwpDepth = JDWP.StepDepth.OUT;604break;605default:606throw new IllegalArgumentException("Invalid step depth");607}608609/*610* Make sure this isn't a duplicate611*/612List<StepRequest> requests = stepRequests();613Iterator<StepRequest> iter = requests.iterator();614while (iter.hasNext()) {615StepRequest request = iter.next();616if ((request != this) &&617request.isEnabled() &&618request.thread().equals(thread)) {619throw new DuplicateRequestException(620"Only one step request allowed per thread");621}622}623624filters.add(JDWP.EventRequest.Set.Modifier.Step.625create(this.thread, jdwpSize, jdwpDepth));626requestList().add(this);627628}629public int depth() {630return depth;631}632633public int size() {634return size;635}636637public ThreadReference thread() {638return thread;639}640641int eventCmd() {642return JDWP.EventKind.SINGLE_STEP;643}644645public String toString() {646return "step request " + thread() + state();647}648}649650class ThreadDeathRequestImpl extends ThreadVisibleEventRequestImpl651implements ThreadDeathRequest {652ThreadDeathRequestImpl() {653requestList().add(this);654}655656int eventCmd() {657return JDWP.EventKind.THREAD_DEATH;658}659660public String toString() {661return "thread death request " + state();662}663}664665class ThreadStartRequestImpl extends ThreadVisibleEventRequestImpl666implements ThreadStartRequest {667ThreadStartRequestImpl() {668requestList().add(this);669}670671int eventCmd() {672return JDWP.EventKind.THREAD_START;673}674675public String toString() {676return "thread start request " + state();677}678}679680abstract class WatchpointRequestImpl extends ClassVisibleEventRequestImpl681implements WatchpointRequest {682final Field field;683684WatchpointRequestImpl(Field field) {685this.field = field;686filters.add(0,687JDWP.EventRequest.Set.Modifier.FieldOnly.create(688(ReferenceTypeImpl)field.declaringType(),689((FieldImpl)field).ref()));690}691692public Field field() {693return field;694}695}696697class AccessWatchpointRequestImpl extends WatchpointRequestImpl698implements AccessWatchpointRequest {699AccessWatchpointRequestImpl(Field field) {700super(field);701requestList().add(this);702}703704int eventCmd() {705return JDWP.EventKind.FIELD_ACCESS;706}707708public String toString() {709return "access watchpoint request " + field + state();710}711}712713class ModificationWatchpointRequestImpl extends WatchpointRequestImpl714implements ModificationWatchpointRequest {715ModificationWatchpointRequestImpl(Field field) {716super(field);717requestList().add(this);718}719720int eventCmd() {721return JDWP.EventKind.FIELD_MODIFICATION;722}723724public String toString() {725return "modification watchpoint request " + field + state();726}727}728729class VMDeathRequestImpl extends EventRequestImpl730implements VMDeathRequest {731VMDeathRequestImpl() {732requestList().add(this);733}734735int eventCmd() {736return JDWP.EventKind.VM_DEATH;737}738739public String toString() {740return "VM death request " + state();741}742}743744/**745* Constructor.746*/747EventRequestManagerImpl(VirtualMachine vm) {748super(vm);749java.lang.reflect.Field[] ekinds =750JDWP.EventKind.class.getDeclaredFields();751int highest = 0;752for (int i = 0; i < ekinds.length; ++i) {753int val;754try {755val = ekinds[i].getInt(null);756} catch (IllegalAccessException exc) {757throw new RuntimeException("Got: " + exc);758}759if (val > highest) {760highest = val;761}762}763requestLists = new List[highest+1];764for (int i=0; i <= highest; i++) {765requestLists[i] = Collections.synchronizedList(new ArrayList<>());766}767}768769public ClassPrepareRequest createClassPrepareRequest() {770return new ClassPrepareRequestImpl();771}772773public ClassUnloadRequest createClassUnloadRequest() {774return new ClassUnloadRequestImpl();775}776777public ExceptionRequest createExceptionRequest(ReferenceType refType,778boolean notifyCaught,779boolean notifyUncaught) {780validateMirrorOrNull(refType);781return new ExceptionRequestImpl(refType, notifyCaught, notifyUncaught);782}783784public StepRequest createStepRequest(ThreadReference thread,785int size, int depth) {786validateMirror(thread);787return new StepRequestImpl(thread, size, depth);788}789790public ThreadDeathRequest createThreadDeathRequest() {791return new ThreadDeathRequestImpl();792}793794public ThreadStartRequest createThreadStartRequest() {795return new ThreadStartRequestImpl();796}797798public MethodEntryRequest createMethodEntryRequest() {799return new MethodEntryRequestImpl();800}801802public MethodExitRequest createMethodExitRequest() {803return new MethodExitRequestImpl();804}805806public MonitorContendedEnterRequest createMonitorContendedEnterRequest() {807if (!vm.canRequestMonitorEvents()) {808throw new UnsupportedOperationException(809"target VM does not support requesting Monitor events");810}811return new MonitorContendedEnterRequestImpl();812}813814public MonitorContendedEnteredRequest createMonitorContendedEnteredRequest() {815if (!vm.canRequestMonitorEvents()) {816throw new UnsupportedOperationException(817"target VM does not support requesting Monitor events");818}819return new MonitorContendedEnteredRequestImpl();820}821822public MonitorWaitRequest createMonitorWaitRequest() {823if (!vm.canRequestMonitorEvents()) {824throw new UnsupportedOperationException(825"target VM does not support requesting Monitor events");826}827return new MonitorWaitRequestImpl();828}829830public MonitorWaitedRequest createMonitorWaitedRequest() {831if (!vm.canRequestMonitorEvents()) {832throw new UnsupportedOperationException(833"target VM does not support requesting Monitor events");834}835return new MonitorWaitedRequestImpl();836}837838public BreakpointRequest createBreakpointRequest(Location location) {839validateMirror(location);840if (location.codeIndex() == -1) {841throw new NativeMethodException("Cannot set breakpoints on native methods");842}843return new BreakpointRequestImpl(location);844}845846public AccessWatchpointRequest847createAccessWatchpointRequest(Field field) {848validateMirror(field);849if (!vm.canWatchFieldAccess()) {850throw new UnsupportedOperationException(851"target VM does not support access watchpoints");852}853return new AccessWatchpointRequestImpl(field);854}855856public ModificationWatchpointRequest857createModificationWatchpointRequest(Field field) {858validateMirror(field);859if (!vm.canWatchFieldModification()) {860throw new UnsupportedOperationException(861"target VM does not support modification watchpoints");862}863return new ModificationWatchpointRequestImpl(field);864}865866public VMDeathRequest createVMDeathRequest() {867if (!vm.canRequestVMDeathEvent()) {868throw new UnsupportedOperationException(869"target VM does not support requesting VM death events");870}871return new VMDeathRequestImpl();872}873874public void deleteEventRequest(EventRequest eventRequest) {875validateMirror(eventRequest);876((EventRequestImpl)eventRequest).delete();877}878879public void deleteEventRequests(List<? extends EventRequest> eventRequests) {880validateMirrors(eventRequests);881// copy the eventRequests to avoid ConcurrentModificationException882Iterator<? extends EventRequest> iter = (new ArrayList<>(eventRequests)).iterator();883while (iter.hasNext()) {884((EventRequestImpl)iter.next()).delete();885}886}887888public void deleteAllBreakpoints() {889requestList(JDWP.EventKind.BREAKPOINT).clear();890891try {892JDWP.EventRequest.ClearAllBreakpoints.process(vm);893} catch (JDWPException exc) {894throw exc.toJDIException();895}896}897898public List<StepRequest> stepRequests() {899return (List<StepRequest>)unmodifiableRequestList(JDWP.EventKind.SINGLE_STEP);900}901902public List<ClassPrepareRequest> classPrepareRequests() {903return (List<ClassPrepareRequest>)unmodifiableRequestList(JDWP.EventKind.CLASS_PREPARE);904}905906public List<ClassUnloadRequest> classUnloadRequests() {907return (List<ClassUnloadRequest>)unmodifiableRequestList(JDWP.EventKind.CLASS_UNLOAD);908}909910public List<ThreadStartRequest> threadStartRequests() {911return (List<ThreadStartRequest>)unmodifiableRequestList(JDWP.EventKind.THREAD_START);912}913914public List<ThreadDeathRequest> threadDeathRequests() {915return (List<ThreadDeathRequest>)unmodifiableRequestList(JDWP.EventKind.THREAD_DEATH);916}917918public List<ExceptionRequest> exceptionRequests() {919return (List<ExceptionRequest>)unmodifiableRequestList(JDWP.EventKind.EXCEPTION);920}921922public List<BreakpointRequest> breakpointRequests() {923return (List<BreakpointRequest>)unmodifiableRequestList(JDWP.EventKind.BREAKPOINT);924}925926public List<AccessWatchpointRequest> accessWatchpointRequests() {927return (List<AccessWatchpointRequest>)unmodifiableRequestList(JDWP.EventKind.FIELD_ACCESS);928}929930public List<ModificationWatchpointRequest> modificationWatchpointRequests() {931return (List<ModificationWatchpointRequest>)unmodifiableRequestList(JDWP.EventKind.FIELD_MODIFICATION);932}933934public List<MethodEntryRequest> methodEntryRequests() {935return (List<MethodEntryRequest>)unmodifiableRequestList(JDWP.EventKind.METHOD_ENTRY);936}937938public List<MethodExitRequest> methodExitRequests() {939return (List<MethodExitRequest>)unmodifiableRequestList(EventRequestManagerImpl.methodExitEventCmd);940}941942public List<MonitorContendedEnterRequest> monitorContendedEnterRequests() {943return (List<MonitorContendedEnterRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_CONTENDED_ENTER);944}945946public List<MonitorContendedEnteredRequest> monitorContendedEnteredRequests() {947return (List<MonitorContendedEnteredRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_CONTENDED_ENTERED);948}949950public List<MonitorWaitRequest> monitorWaitRequests() {951return (List<MonitorWaitRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_WAIT);952}953954public List<MonitorWaitedRequest> monitorWaitedRequests() {955return (List<MonitorWaitedRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_WAITED);956}957958public List<VMDeathRequest> vmDeathRequests() {959return (List<VMDeathRequest>)unmodifiableRequestList(JDWP.EventKind.VM_DEATH);960}961962List<? extends EventRequest> unmodifiableRequestList(int eventCmd) {963// No need of explicit synchronization for requestList here.964// It is taken care internally by SynchronizedList class.965return Collections.unmodifiableList(new ArrayList<>(requestList(eventCmd)));966}967968EventRequest request(int eventCmd, int requestId) {969List<? extends EventRequest> rl = requestList(eventCmd);970synchronized(rl) { // Refer Collections.synchronizedList javadoc.971Iterator<? extends EventRequest> itr = rl.iterator();972while (itr.hasNext()){973EventRequestImpl er = (EventRequestImpl)itr.next();974if (er.id == requestId)975return er;976}977}978return null;979}980981private List<? extends EventRequest> requestList(int eventCmd) {982return requestLists[eventCmd];983}984}985986987