History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/tools/example/debug/bdi/ExecutionManager.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/tools/example/debug/bdi/ExecutionManager.java+815−0
@@ -0,0 +1,815 @@
1/*
2 * Copyright (c) 1998, 2008, 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
26package com.sun.tools.example.debug.bdi;
27
28import com.sun.jdi.*;
29import com.sun.jdi.request.*;
30import com.sun.jdi.connect.*;
31import com.sun.tools.example.debug.expr.ExpressionParser;
32import com.sun.tools.example.debug.expr.ParseException;
33
34import java.io.*;
35import java.util.*;
36
37import com.sun.tools.example.debug.event.*;
38
39import javax.swing.SwingUtilities;
40
41/**
42 * Move this towards being only state and functionality
43 * that spans across Sessions (and thus VMs).
44 */
45public class ExecutionManager {
46
47 private Session session;
48
49 /**
50 * Get/set JDI trace mode.
51 */
52 int traceMode = VirtualMachine.TRACE_NONE;
53
54 ////////////////// Listener registration //////////////////
55
56 // Session Listeners
57
58 ArrayList<SessionListener> sessionListeners = new ArrayList<SessionListener>();
59
60 public void addSessionListener(SessionListener listener) {
61 sessionListeners.add(listener);
62 }
63
64 public void removeSessionListener(SessionListener listener) {
65 sessionListeners.remove(listener);
66 }
67
68 // Spec Listeners
69
70 ArrayList<SpecListener> specListeners = new ArrayList<SpecListener>();
71
72 public void addSpecListener(SpecListener cl) {
73 specListeners.add(cl);
74 }
75
76 public void removeSpecListener(SpecListener cl) {
77 specListeners.remove(cl);
78 }
79
80 // JDI Listeners
81
82 ArrayList<JDIListener> jdiListeners = new ArrayList<JDIListener>();
83
84 /**
85 * Adds a JDIListener
86 */
87 public void addJDIListener(JDIListener jl) {
88 jdiListeners.add(jl);
89 }
90
91 /**
92 * Adds a JDIListener - at the specified position
93 */
94 public void addJDIListener(int index, JDIListener jl) {
95 jdiListeners.add(index, jl);
96 }
97
98 /**
99 * Removes a JDIListener
100 */
101 public void removeJDIListener(JDIListener jl) {
102 jdiListeners.remove(jl);
103 }
104
105 // App Echo Listeners
106
107 private ArrayList<OutputListener> appEchoListeners = new ArrayList<OutputListener>();
108
109 public void addApplicationEchoListener(OutputListener l) {
110 appEchoListeners.add(l);
111 }
112
113 public void removeApplicationEchoListener(OutputListener l) {
114 appEchoListeners.remove(l);
115 }
116
117 // App Output Listeners
118
119 private ArrayList<OutputListener> appOutputListeners = new ArrayList<OutputListener>();
120
121 public void addApplicationOutputListener(OutputListener l) {
122 appOutputListeners.add(l);
123 }
124
125 public void removeApplicationOutputListener(OutputListener l) {
126 appOutputListeners.remove(l);
127 }
128
129 // App Error Listeners
130
131 private ArrayList<OutputListener> appErrorListeners = new ArrayList<OutputListener>();
132
133 public void addApplicationErrorListener(OutputListener l) {
134 appErrorListeners.add(l);
135 }
136
137 public void removeApplicationErrorListener(OutputListener l) {
138 appErrorListeners.remove(l);
139 }
140
141 // Diagnostic Listeners
142
143 private ArrayList<OutputListener> diagnosticsListeners = new ArrayList<OutputListener>();
144
145 public void addDiagnosticsListener(OutputListener l) {
146 diagnosticsListeners.add(l);
147 }
148
149 public void removeDiagnosticsListener(OutputListener l) {
150 diagnosticsListeners.remove(l);
151 }
152
153 /////////// End Listener Registration //////////////
154
155 //### We probably don't want this public
156 public VirtualMachine vm() {
157 return session == null ? null : session.vm;
158 }
159
160 void ensureActiveSession() throws NoSessionException {
161 if (session == null) {
162 throw new NoSessionException();
163 }
164 }
165
166 public EventRequestManager eventRequestManager() {
167 return vm() == null ? null : vm().eventRequestManager();
168 }
169
170 /**
171 * Get JDI trace mode.
172 */
173 public int getTraceMode(int mode) {
174 return traceMode;
175 }
176
177 /**
178 * Set JDI trace mode.
179 */
180 public void setTraceMode(int mode) {
181 traceMode = mode;
182 if (session != null) {
183 session.setTraceMode(mode);
184 }
185 }
186
187 /**
188 * Determine if VM is interrupted, i.e, present and not running.
189 */
190 public boolean isInterrupted() /* should: throws NoSessionException */ {
191// ensureActiveSession();
192 return session.interrupted;
193 }
194
195 /**
196 * Return a list of ReferenceType objects for all
197 * currently loaded classes and interfaces.
198 * Array types are not returned.
199 */
200 public List<ReferenceType> allClasses() throws NoSessionException {
201 ensureActiveSession();
202 return vm().allClasses();
203 }
204
205 /**
206 * Return a ReferenceType object for the currently
207 * loaded class or interface whose fully-qualified
208 * class name is specified, else return null if there
209 * is none.
210 *
211 * In general, we must return a list of types, because
212 * multiple class loaders could have loaded a class
213 * with the same fully-qualified name.
214 */
215 public List<ReferenceType> findClassesByName(String name) throws NoSessionException {
216 ensureActiveSession();
217 return vm().classesByName(name);
218 }
219
220 /**
221 * Return a list of ReferenceType objects for all
222 * currently loaded classes and interfaces whose name
223 * matches the given pattern. The pattern syntax is
224 * open to some future revision, but currently consists
225 * of a fully-qualified class name in which the first
226 * component may optionally be a "*" character, designating
227 * an arbitrary prefix.
228 */
229 public List<ReferenceType> findClassesMatchingPattern(String pattern)
230 throws NoSessionException {
231 ensureActiveSession();
232 List<ReferenceType> result = new ArrayList<ReferenceType>(); //### Is default size OK?
233 if (pattern.startsWith("*.")) {
234 // Wildcard matches any leading package name.
235 pattern = pattern.substring(1);
236 for (ReferenceType type : vm().allClasses()) {
237 if (type.name().endsWith(pattern)) {
238 result.add(type);
239 }
240 }
241 return result;
242 } else {
243 // It's a class name.
244 return vm().classesByName(pattern);
245 }
246 }
247
248 /*
249 * Return a list of ThreadReference objects corresponding
250 * to the threads that are currently active in the VM.
251 * A thread is removed from the list just before the
252 * thread terminates.
253 */
254
255 public List<ThreadReference> allThreads() throws NoSessionException {
256 ensureActiveSession();
257 return vm().allThreads();
258 }
259
260 /*
261 * Return a list of ThreadGroupReference objects corresponding
262 * to the top-level threadgroups that are currently active in the VM.
263 * Note that a thread group may be empty, or contain no threads as
264 * descendents.
265 */
266
267 public List<ThreadGroupReference> topLevelThreadGroups() throws NoSessionException {
268 ensureActiveSession();
269 return vm().topLevelThreadGroups();
270 }
271
272 /*
273 * Return the system threadgroup.
274 */
275
276 public ThreadGroupReference systemThreadGroup()
277 throws NoSessionException {
278 ensureActiveSession();
279 return vm().topLevelThreadGroups().get(0);
280 }
281
282 /*
283 * Evaluate an expression.
284 */
285
286 public Value evaluate(final StackFrame f, String expr)
287 throws ParseException,
288 InvocationException,
289 InvalidTypeException,
290 ClassNotLoadedException,
291 NoSessionException,
292 IncompatibleThreadStateException {
293 ExpressionParser.GetFrame frameGetter = null;
294 ensureActiveSession();
295 if (f != null) {
296 frameGetter = new ExpressionParser.GetFrame() {
297 @Override
298 public StackFrame get() /* throws IncompatibleThreadStateException */ {
299 return f;
300 }
301 };
302 }
303 return ExpressionParser.evaluate(expr, vm(), frameGetter);
304 }
305
306
307 /*
308 * Start a new VM.
309 */
310
311 public void run(boolean suspended,
312 String vmArgs,
313 String className,
314 String args) throws VMLaunchFailureException {
315
316 endSession();
317
318 //### Set a breakpoint on 'main' method.
319 //### Would be cleaner if we could just bring up VM already suspended.
320 if (suspended) {
321 //### Set breakpoint at 'main(java.lang.String[])'.
322 List<String> argList = new ArrayList<String>(1);
323 argList.add("java.lang.String[]");
324 createMethodBreakpoint(className, "main", argList);
325 }
326
327 String cmdLine = className + " " + args;
328
329 startSession(new ChildSession(this, vmArgs, cmdLine,
330 appInput, appOutput, appError,
331 diagnostics));
332 }
333
334 /*
335 * Attach to an existing VM.
336 */
337 public void attach(String portName) throws VMLaunchFailureException {
338 endSession();
339
340 //### Changes made here for connectors have broken the
341 //### the 'Session' abstraction. The 'Session.attach()'
342 //### method is intended to encapsulate all of the various
343 //### ways in which session start-up can fail. (maddox 12/18/98)
344
345 /*
346 * Now that attaches and launches both go through Connectors,
347 * it may be worth creating a new subclass of Session for
348 * attach sessions.
349 */
350 VirtualMachineManager mgr = Bootstrap.virtualMachineManager();
351 AttachingConnector connector = mgr.attachingConnectors().get(0);
352 Map<String, Connector.Argument> arguments = connector.defaultArguments();
353 arguments.get("port").setValue(portName);
354
355 Session newSession = internalAttach(connector, arguments);
356 if (newSession != null) {
357 startSession(newSession);
358 }
359 }
360
361 private Session internalAttach(AttachingConnector connector,
362 Map<String, Connector.Argument> arguments) {
363 try {
364 VirtualMachine vm = connector.attach(arguments);
365 return new Session(vm, this, diagnostics);
366 } catch (IOException ioe) {
367 diagnostics.putString("\n Unable to attach to target VM: " +
368 ioe.getMessage());
369 } catch (IllegalConnectorArgumentsException icae) {
370 diagnostics.putString("\n Invalid connector arguments: " +
371 icae.getMessage());
372 }
373 return null;
374 }
375
376 private Session internalListen(ListeningConnector connector,
377 Map<String, Connector.Argument> arguments) {
378 try {
379 VirtualMachine vm = connector.accept(arguments);
380 return new Session(vm, this, diagnostics);
381 } catch (IOException ioe) {
382 diagnostics.putString(
383 "\n Unable to accept connection to target VM: " +
384 ioe.getMessage());
385 } catch (IllegalConnectorArgumentsException icae) {
386 diagnostics.putString("\n Invalid connector arguments: " +
387 icae.getMessage());
388 }
389 return null;
390 }
391
392 /*
393 * Connect via user specified arguments
394 * @return true on success
395 */
396 public boolean explictStart(Connector connector, Map<String, Connector.Argument> arguments)
397 throws VMLaunchFailureException {
398 Session newSession = null;
399
400 endSession();
401
402 if (connector instanceof LaunchingConnector) {
403 // we were launched, use ChildSession
404 newSession = new ChildSession(this, (LaunchingConnector)connector,
405 arguments,
406 appInput, appOutput, appError,
407 diagnostics);
408 } else if (connector instanceof AttachingConnector) {
409 newSession = internalAttach((AttachingConnector)connector,
410 arguments);
411 } else if (connector instanceof ListeningConnector) {
412 newSession = internalListen((ListeningConnector)connector,
413 arguments);
414 } else {
415 diagnostics.putString("\n Unknown connector: " + connector);
416 }
417 if (newSession != null) {
418 startSession(newSession);
419 }
420 return newSession != null;
421 }
422
423 /*
424 * Detach from VM. If VM was started by debugger, terminate it.
425 */
426 public void detach() throws NoSessionException {
427 ensureActiveSession();
428 endSession();
429 }
430
431 private void startSession(Session s) throws VMLaunchFailureException {
432 if (!s.attach()) {
433 throw new VMLaunchFailureException();
434 }
435 session = s;
436 EventRequestManager em = vm().eventRequestManager();
437 ClassPrepareRequest classPrepareRequest = em.createClassPrepareRequest();
438 //### We must allow the deferred breakpoints to be resolved before
439 //### we continue executing the class. We could optimize if there
440 //### were no deferred breakpoints outstanding for a particular class.
441 //### Can we do this with JDI?
442 classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
443 classPrepareRequest.enable();
444 ClassUnloadRequest classUnloadRequest = em.createClassUnloadRequest();
445 classUnloadRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
446 classUnloadRequest.enable();
447 ThreadStartRequest threadStartRequest = em.createThreadStartRequest();
448 threadStartRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
449 threadStartRequest.enable();
450 ThreadDeathRequest threadDeathRequest = em.createThreadDeathRequest();
451 threadDeathRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
452 threadDeathRequest.enable();
453 ExceptionRequest exceptionRequest =
454 em.createExceptionRequest(null, false, true);
455 exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
456 exceptionRequest.enable();
457 validateThreadInfo();
458 session.interrupted = true;
459 notifySessionStart();
460 }
461
462 void endSession() {
463 if (session != null) {
464 session.detach();
465 session = null;
466 invalidateThreadInfo();
467 notifySessionDeath();
468 }
469 }
470
471 /*
472 * Suspend all VM activity.
473 */
474
475 public void interrupt() throws NoSessionException {
476 ensureActiveSession();
477 vm().suspend();
478 //### Is it guaranteed that the interrupt has happened?
479 validateThreadInfo();
480 session.interrupted = true;
481 notifyInterrupted();
482 }
483
484 /*
485 * Resume interrupted VM.
486 */
487
488 public void go() throws NoSessionException, VMNotInterruptedException {
489 ensureActiveSession();
490 invalidateThreadInfo();
491 session.interrupted = false;
492 notifyContinued();
493 vm().resume();
494 }
495
496 /*
497 * Stepping.
498 */
499 void clearPreviousStep(ThreadReference thread) {
500 /*
501 * A previous step may not have completed on this thread;
502 * if so, it gets removed here.
503 */
504 EventRequestManager mgr = vm().eventRequestManager();
505 for (StepRequest request : mgr.stepRequests()) {
506 if (request.thread().equals(thread)) {
507 mgr.deleteEventRequest(request);
508 break;
509 }
510 }
511 }
512
513 private void generalStep(ThreadReference thread, int size, int depth)
514 throws NoSessionException {
515 ensureActiveSession();
516 invalidateThreadInfo();
517 session.interrupted = false;
518 notifyContinued();
519
520 clearPreviousStep(thread);
521 EventRequestManager reqMgr = vm().eventRequestManager();
522 StepRequest request = reqMgr.createStepRequest(thread,
523 size, depth);
524 // We want just the next step event and no others
525 request.addCountFilter(1);
526 request.enable();
527 vm().resume();
528 }
529
530 public void stepIntoInstruction(ThreadReference thread)
531 throws NoSessionException {
532 generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO);
533 }
534
535 public void stepOverInstruction(ThreadReference thread)
536 throws NoSessionException {
537 generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OVER);
538 }
539
540 public void stepIntoLine(ThreadReference thread)
541 throws NoSessionException,
542 AbsentInformationException {
543 generalStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO);
544 }
545
546 public void stepOverLine(ThreadReference thread)
547 throws NoSessionException,
548 AbsentInformationException {
549 generalStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER);
550 }
551
552 public void stepOut(ThreadReference thread)
553 throws NoSessionException {
554 generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OUT);
555 }
556
557 /*
558 * Thread control.
559 */
560
561 public void suspendThread(ThreadReference thread) throws NoSessionException {
562 ensureActiveSession();
563 thread.suspend();
564 }
565
566 public void resumeThread(ThreadReference thread) throws NoSessionException {
567 ensureActiveSession();
568 thread.resume();
569 }
570
571 public void stopThread(ThreadReference thread) throws NoSessionException {
572 ensureActiveSession();
573 //### Need an exception now. Which one to use?
574 //thread.stop();
575 }
576
577 /*
578 * ThreadInfo objects -- Allow query of thread status and stack.
579 */
580
581 private List<ThreadInfo> threadInfoList = new LinkedList<ThreadInfo>();
582 //### Should be weak! (in the value, not the key)
583 private HashMap<ThreadReference, ThreadInfo> threadInfoMap = new HashMap<ThreadReference, ThreadInfo>();
584
585 public ThreadInfo threadInfo(ThreadReference thread) {
586 if (session == null || thread == null) {
587 return null;
588 }
589 ThreadInfo info = threadInfoMap.get(thread);
590 if (info == null) {
591 //### Should not hardcode initial frame count and prefetch here!
592 //info = new ThreadInfo(thread, 10, 10);
593 info = new ThreadInfo(thread);
594 if (session.interrupted) {
595 info.validate();
596 }
597 threadInfoList.add(info);
598 threadInfoMap.put(thread, info);
599 }
600 return info;
601 }
602
603 void validateThreadInfo() {
604 session.interrupted = true;
605 for (ThreadInfo threadInfo : threadInfoList) {
606 threadInfo.validate();
607 }
608 }
609
610 private void invalidateThreadInfo() {
611 if (session != null) {
612 session.interrupted = false;
613 for (ThreadInfo threadInfo : threadInfoList) {
614 threadInfo.invalidate();
615 }
616 }
617 }
618
619 void removeThreadInfo(ThreadReference thread) {
620 ThreadInfo info = threadInfoMap.get(thread);
621 if (info != null) {
622 info.invalidate();
623 threadInfoMap.remove(thread);
624 threadInfoList.remove(info);
625 }
626 }
627
628 /*
629 * Listen for Session control events.
630 */
631
632 private void notifyInterrupted() {
633 ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
634 EventObject evt = new EventObject(this);
635 for (int i = 0; i < l.size(); i++) {
636 l.get(i).sessionInterrupt(evt);
637 }
638 }
639
640 private void notifyContinued() {
641 ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
642 EventObject evt = new EventObject(this);
643 for (int i = 0; i < l.size(); i++) {
644 l.get(i).sessionContinue(evt);
645 }
646 }
647
648 private void notifySessionStart() {
649 ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
650 EventObject evt = new EventObject(this);
651 for (int i = 0; i < l.size(); i++) {
652 l.get(i).sessionStart(evt);
653 }
654 }
655
656 private void notifySessionDeath() {
657/*** noop for now
658 ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
659 EventObject evt = new EventObject(this);
660 for (int i = 0; i < l.size(); i++) {
661 ((SessionListener)l.get(i)).sessionDeath(evt);
662 }
663****/
664 }
665
666 /*
667 * Listen for input and output requests from the application
668 * being debugged. These are generated only when the debuggee
669 * is spawned as a child of the debugger.
670 */
671
672 private Object inputLock = new Object();
673 private LinkedList<String> inputBuffer = new LinkedList<String>();
674
675 private void resetInputBuffer() {
676 synchronized (inputLock) {
677 inputBuffer = new LinkedList<String>();
678 }
679 }
680
681 public void sendLineToApplication(String line) {
682 synchronized (inputLock) {
683 inputBuffer.addFirst(line);
684 inputLock.notifyAll();
685 }
686 }
687
688 private InputListener appInput = new InputListener() {
689 @Override
690 public String getLine() {
691 // Don't allow reader to be interrupted -- catch and retry.
692 String line = null;
693 while (line == null) {
694 synchronized (inputLock) {
695 try {
696 while (inputBuffer.size() < 1) {
697 inputLock.wait();
698 }
699 line = inputBuffer.removeLast();
700 } catch (InterruptedException e) {}
701 }
702 }
703 // We must not be holding inputLock here, as the listener
704 // that we call to echo a line might call us re-entrantly
705 // to provide another line of input.
706 // Run in Swing event dispatcher thread.
707 final String input = line;
708 SwingUtilities.invokeLater(new Runnable() {
709 @Override
710 public void run() {
711 echoInputLine(input);
712 }
713 });
714 return line;
715 }
716 };
717
718 private static String newline = System.getProperty("line.separator");
719
720 private void echoInputLine(String line) {
721 ArrayList<OutputListener> l = new ArrayList<OutputListener>(appEchoListeners);
722 for (int i = 0; i < l.size(); i++) {
723 OutputListener ol = l.get(i);
724 ol.putString(line);
725 ol.putString(newline);
726 }
727 }
728
729 private OutputListener appOutput = new OutputListener() {
730 @Override
731 public void putString(String string) {
732 ArrayList<OutputListener> l = new ArrayList<OutputListener>(appEchoListeners);
733 for (int i = 0; i < l.size(); i++) {
734 l.get(i).putString(string);
735 }
736 }
737 };
738
739 private OutputListener appError = new OutputListener() {
740 @Override
741 public void putString(String string) {
742 ArrayList<OutputListener> l = new ArrayList<OutputListener>(appEchoListeners);
743 for (int i = 0; i < l.size(); i++) {
744 l.get(i).putString(string);
745 }
746 }
747 };
748
749 private OutputListener diagnostics = new OutputListener() {
750 @Override
751 public void putString(String string) {
752 ArrayList<OutputListener> l = new ArrayList<OutputListener>(diagnosticsListeners);
753 for (int i = 0; i < l.size(); i++) {
754 l.get(i).putString(string);
755 }
756 }
757 };
758
759 ///////////// Spec Request Creation/Deletion/Query ///////////
760
761 private EventRequestSpecList specList = new EventRequestSpecList(this);
762
763 public BreakpointSpec
764 createSourceLineBreakpoint(String sourceName, int line) {
765 return specList.createSourceLineBreakpoint(sourceName, line);
766 }
767
768 public BreakpointSpec
769 createClassLineBreakpoint(String classPattern, int line) {
770 return specList.createClassLineBreakpoint(classPattern, line);
771 }
772
773 public BreakpointSpec
774 createMethodBreakpoint(String classPattern,
775 String methodId, List<String> methodArgs) {
776 return specList.createMethodBreakpoint(classPattern,
777 methodId, methodArgs);
778 }
779
780 public ExceptionSpec
781 createExceptionIntercept(String classPattern,
782 boolean notifyCaught,
783 boolean notifyUncaught) {
784 return specList.createExceptionIntercept(classPattern,
785 notifyCaught,
786 notifyUncaught);
787 }
788
789 public AccessWatchpointSpec
790 createAccessWatchpoint(String classPattern, String fieldId) {
791 return specList.createAccessWatchpoint(classPattern, fieldId);
792 }
793
794 public ModificationWatchpointSpec
795 createModificationWatchpoint(String classPattern, String fieldId) {
796 return specList.createModificationWatchpoint(classPattern,
797 fieldId);
798 }
799
800 public void delete(EventRequestSpec spec) {
801 specList.delete(spec);
802 }
803
804 void resolve(ReferenceType refType) {
805 specList.resolve(refType);
806 }
807
808 public void install(EventRequestSpec spec) {
809 specList.install(spec, vm());
810 }
811
812 public List<EventRequestSpec> eventRequestSpecs() {
813 return specList.eventRequestSpecs();
814 }
815}