KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > JPDAStepImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.debugger.jpda;
21
22 import com.sun.jdi.AbsentInformationException;
23 import com.sun.jdi.IncompatibleThreadStateException;
24 import com.sun.jdi.event.LocatableEvent;
25 import java.beans.PropertyChangeListener JavaDoc;
26 import java.lang.reflect.InvocationTargetException JavaDoc;
27 import java.net.MalformedURLException JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.awt.Dialog JavaDoc;
30 import java.awt.event.ActionEvent JavaDoc;
31 import java.awt.event.ActionListener JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.HashSet JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.Set JavaDoc;
39 import java.util.logging.Level JavaDoc;
40 import java.util.logging.Logger JavaDoc;
41 import org.netbeans.api.debugger.DebuggerManager;
42 import org.netbeans.api.debugger.Session;
43 import org.netbeans.api.debugger.jpda.CallStackFrame;
44 import org.netbeans.api.debugger.jpda.JPDABreakpoint;
45 import org.netbeans.api.debugger.jpda.JPDAStep;
46 import org.netbeans.api.debugger.jpda.JPDAThread;
47 import org.netbeans.api.debugger.jpda.JPDADebugger;
48 import com.sun.jdi.event.Event;
49 import com.sun.jdi.request.BreakpointRequest;
50 import com.sun.jdi.ThreadReference;
51 import com.sun.jdi.request.StepRequest;
52 import com.sun.jdi.request.EventRequest;
53 import com.sun.jdi.request.EventRequestManager;
54 import com.sun.jdi.Location;
55 import com.sun.jdi.Method;
56 import com.sun.jdi.ReferenceType;
57 import com.sun.jdi.StackFrame;
58 import com.sun.jdi.ThreadReference;
59 import com.sun.jdi.VirtualMachine;
60 import org.netbeans.api.debugger.jpda.JPDAThreadGroup;
61 import org.netbeans.api.debugger.jpda.MethodBreakpoint;
62 import org.netbeans.api.debugger.jpda.SmartSteppingFilter;
63 import org.netbeans.api.debugger.jpda.Variable;
64 import org.netbeans.api.debugger.jpda.event.JPDABreakpointEvent;
65 import org.netbeans.api.debugger.jpda.event.JPDABreakpointListener;
66 import org.netbeans.modules.debugger.jpda.JPDAStepImpl.SingleThreadedStepWatch;
67 import org.netbeans.modules.debugger.jpda.actions.SmartSteppingFilterImpl;
68 import org.netbeans.modules.debugger.jpda.breakpoints.MethodBreakpointImpl;
69 import org.netbeans.modules.debugger.jpda.util.Executor;
70 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
71 import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl;
72 import org.netbeans.spi.debugger.jpda.EditorContext;
73 import org.netbeans.spi.debugger.jpda.EditorContext.Operation;
74 import org.openide.DialogDescriptor;
75 import org.openide.DialogDescriptor;
76 import org.openide.ErrorManager;
77 import org.openide.NotifyDescriptor;
78 import org.openide.filesystems.FileObject;
79 import org.openide.filesystems.URLMapper;
80 import org.openide.util.NbBundle;
81 import org.openide.util.RequestProcessor;
82
83
84 public class JPDAStepImpl extends JPDAStep implements Executor {
85     
86     private static Logger JavaDoc logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.step"); // NOI18N
87

88     private static final boolean IS_JDK_16 = !System.getProperty("java.version").startsWith("1.5"); // NOI18N
89

90     /** The source tree with location info of this step */
91     //private ASTL stepASTL;
92
private Operation[] currentOperations;
93     private Operation lastOperation;
94     private MethodExitBreakpointListener lastMethodExitBreakpointListener;
95     private Set JavaDoc<BreakpointRequest> operationBreakpoints;
96     private StepRequest boundaryStepRequest;
97     private SingleThreadedStepWatch stepWatch;
98     
99     private Session session;
100     
101     public JPDAStepImpl(JPDADebugger debugger, Session session, int size, int depth) {
102         super(debugger, size, depth);
103         this.session = session;
104     }
105     
106     public void addStep(JPDAThread tr) {
107         JPDADebuggerImpl debuggerImpl = (JPDADebuggerImpl) debugger;
108         JPDAThreadImpl trImpl = (JPDAThreadImpl) tr;
109         VirtualMachine vm = debuggerImpl.getVirtualMachine();
110         if (vm == null) {
111             return ; // The session has finished
112
}
113         EventRequestManager erm = vm.eventRequestManager();
114         //Remove all step requests -- TODO: Do we want it?
115
List JavaDoc<StepRequest> stepRequests = erm.stepRequests();
116         erm.deleteEventRequests(stepRequests);
117         for (StepRequest stepRequest : stepRequests) {
118             SingleThreadedStepWatch.stepRequestDeleted(stepRequest);
119         }
120         int size = getSize();
121         boolean stepAdded = false;
122         logger.log(Level.FINE, "Step "+((size == JPDAStep.STEP_OPERATION) ? "operation" : "line")
123                    +" "+((getDepth() == JPDAStep.STEP_INTO) ? "into" :
124                        ((getDepth() == JPDAStep.STEP_OVER) ? "over" : "out"))
125                    +" in thread "+tr.getName());
126         if (size == JPDAStep.STEP_OPERATION) {
127             stepAdded = addOperationStep(trImpl, false);
128             if (!stepAdded) {
129                 size = JPDAStep.STEP_LINE;
130                 logger.log(Level.FINE, "Operation step changed to line step");
131             }
132         }
133         if (!stepAdded) {
134             StepRequest stepRequest = vm.eventRequestManager().createStepRequest(
135                 trImpl.getThreadReference(),
136                 size,
137                 getDepth()
138             );
139             stepRequest.addCountFilter(1);
140             debuggerImpl.getOperator().register(stepRequest, this);
141             stepRequest.setSuspendPolicy(debugger.getSuspend());
142
143             try {
144                 stepRequest.enable ();
145             } catch (IllegalThreadStateException JavaDoc itsex) {
146                 // the thread named in the request has died.
147
debuggerImpl.getOperator().unregister(stepRequest);
148                 stepRequest = null;
149             }
150             
151             if (stepRequest != null && stepRequest.suspendPolicy() == StepRequest.SUSPEND_EVENT_THREAD) {
152                 stepWatch = new SingleThreadedStepWatch(debuggerImpl, stepRequest);
153             }
154         }
155     }
156     
157     private boolean addOperationStep(JPDAThreadImpl tr, boolean lineStepExec) {
158         ThreadReference trRef = tr.getThreadReference();
159         StackFrame sf;
160         try {
161             sf = trRef.frame(0);
162         } catch (IncompatibleThreadStateException itsex) {
163             return false;
164         }
165         Location loc = sf.location();
166         Session currentSession = DebuggerManager.getDebuggerManager().getCurrentSession();
167         String JavaDoc language = currentSession == null ? null : currentSession.getCurrentLanguage();
168         SourcePath sourcePath = ((JPDADebuggerImpl) debugger).getEngineContext();
169         String JavaDoc url = sourcePath.getURL(loc, language);
170         ExpressionPool exprPool = ((JPDADebuggerImpl) debugger).getExpressionPool();
171         ExpressionPool.Expression expr = exprPool.getExpressionAt(loc, url);
172         if (expr == null) {
173             return false;
174         }
175         Operation[] ops = expr.getOperations();
176         
177         //Operation operation = null;
178
int opIndex = -1;
179         int codeIndex = (int) loc.codeIndex();
180         if (codeIndex <= ops[0].getBytecodeIndex()) {
181             if (!lineStepExec) {
182                 tr.clearLastOperations();
183             }
184             // We're at the beginning. Just take the first operation
185
if (!ops[0].equals(tr.getCurrentOperation())) {
186                 opIndex = expr.findNextOperationIndex(codeIndex - 1);
187                 if (opIndex >= 0 && ops[opIndex].getBytecodeIndex() == codeIndex) {
188                     tr.setCurrentOperation(ops[opIndex]);
189                     if (lineStepExec) {
190                         return false;
191                     }
192                     if (! getHidden()) {
193                         JPDADebuggerImpl debuggerImpl = (JPDADebuggerImpl)debugger;
194                         debuggerImpl.setStoppedStateNoContinue(tr.getThreadReference());
195                     }
196                     return true;
197                 }
198             }
199         }
200         this.lastOperation = tr.getCurrentOperation();
201         VirtualMachine vm = loc.virtualMachine();
202         if (lastOperation != null) {
203              // Set the method exit breakpoint to get the return value
204
String JavaDoc methodName = lastOperation.getMethodName();
205             if (methodName != null && MethodBreakpointImpl.canGetMethodReturnValues(vm)) {
206                 MethodBreakpoint mb = MethodBreakpoint.create(lastOperation.getMethodClassType(), methodName);
207                 //mb.setMethodName(methodName);
208
mb.setBreakpointType(MethodBreakpoint.TYPE_METHOD_EXIT);
209                 mb.setHidden(true);
210                 mb.setSuspend(JPDABreakpoint.SUSPEND_NONE);
211                 lastMethodExitBreakpointListener = new MethodExitBreakpointListener(mb);
212                 mb.addJPDABreakpointListener(lastMethodExitBreakpointListener);
213                 DebuggerManager.getDebuggerManager().addBreakpoint(mb);
214             }
215         }
216         tr.keepLastOperationsUponResume();
217         ExpressionPool.OperationLocation[] nextOperationLocations;
218         if (opIndex < 0) {
219             nextOperationLocations = expr.findNextOperationLocations(codeIndex);
220         } else {
221             Location[] locations = expr.getLocations();
222             nextOperationLocations = new ExpressionPool.OperationLocation[] {
223                 new ExpressionPool.OperationLocation(ops[opIndex], locations[opIndex], opIndex) };
224         }
225         boolean isNextOperationFromDifferentExpression = false;
226         if (nextOperationLocations != null) {
227             //Location[] locations = expr.getLocations();
228
/*if (opIndex < 0) {
229                 // search for an operation on the next line
230                 expr = exprPool.getExpressionAt(locations[locations.length - 1], url);
231                 if (expr == null) {
232                     logger.log(Level.FINE, "No next operation is available.");
233                     return false;
234                 }
235                 ops = expr.getOperations();
236                 opIndex = 0;
237                 locations = expr.getLocations();
238             }*/

239             this.operationBreakpoints = new HashSet JavaDoc<BreakpointRequest>();
240             // We need to submit breakpoints on the desired operation and all subsequent ones,
241
// because some might be skipped due to conditional execution.
242
for (int ni = 0; ni < nextOperationLocations.length; ni++) {
243                 Location nloc = nextOperationLocations[ni].getLocation();
244                 if (nextOperationLocations[ni].getIndex() < 0) {
245                     isNextOperationFromDifferentExpression = true;
246                     Operation[] newOps = new Operation[ops.length + 1];
247                     System.arraycopy(ops, 0, newOps, 0, ops.length);
248                     newOps[ops.length] = nextOperationLocations[ni].getOperation();
249                     ops = newOps;
250                 }
251                 BreakpointRequest brReq = vm.eventRequestManager().createBreakpointRequest(nloc);
252                 operationBreakpoints.add(brReq);
253                 ((JPDADebuggerImpl) debugger).getOperator().register(brReq, this);
254                 brReq.setSuspendPolicy(debugger.getSuspend());
255                 brReq.addThreadFilter(trRef);
256                 brReq.enable();
257             }
258         } else if (lineStepExec) {
259             return false;
260         }
261         
262         // We need to also submit a step request so that we're sure that we end up at least on the next execution line
263
boundaryStepRequest = vm.eventRequestManager().createStepRequest(
264             tr.getThreadReference(),
265             StepRequest.STEP_LINE,
266             StepRequest.STEP_OVER
267         );
268         if (isNextOperationFromDifferentExpression) {
269             boundaryStepRequest.addCountFilter(2);
270         } else {
271             boundaryStepRequest.addCountFilter(1);
272         }
273         ((JPDADebuggerImpl) debugger).getOperator().register(boundaryStepRequest, this);
274         boundaryStepRequest.setSuspendPolicy(debugger.getSuspend());
275         try {
276             boundaryStepRequest.enable ();
277         } catch (IllegalThreadStateException JavaDoc itsex) {
278             // the thread named in the request has died.
279
((JPDADebuggerImpl) debugger).getOperator().unregister(boundaryStepRequest);
280             boundaryStepRequest = null;
281             return false;
282         }
283         
284         this.currentOperations = ops;
285         return true;
286     }
287     
288     public boolean exec (Event event) {
289         if (stepWatch != null) {
290             stepWatch.done();
291             stepWatch = null;
292         }
293         // TODO: Check the location, follow the smart-stepping logic!
294
JPDADebuggerImpl debuggerImpl = (JPDADebuggerImpl)debugger;
295         JPDAThreadImpl tr = (JPDAThreadImpl)debuggerImpl.getCurrentThread();
296         VirtualMachine vm = debuggerImpl.getVirtualMachine();
297         if (vm == null) {
298             return false; // The session has finished
299
}
300         if (lastMethodExitBreakpointListener != null) {
301             Variable returnValue = lastMethodExitBreakpointListener.getReturnValue();
302             lastMethodExitBreakpointListener.destroy();
303             lastMethodExitBreakpointListener = null;
304             lastOperation.setReturnValue(returnValue);
305         }
306         if (lastOperation != null) {
307             tr.addLastOperation(lastOperation);
308         }
309         Operation currentOperation = null;
310         boolean addExprStep = false;
311         if (currentOperations != null) {
312             if (event.request() instanceof BreakpointRequest) {
313                 long codeIndex = ((BreakpointRequest) event.request()).location().codeIndex();
314                 for (int i = 0; i < currentOperations.length; i++) {
315                     if (currentOperations[i].getBytecodeIndex() == codeIndex) {
316                         currentOperation = currentOperations[i];
317                         break;
318                     }
319                 }
320             } else {
321                 // A line step was finished, the execution of current expression
322
// has finished, we need to check the expression on this line.
323
addExprStep = true;
324             }
325             this.currentOperations = null;
326         }
327         tr.setCurrentOperation(currentOperation);
328         EventRequestManager erm = vm.eventRequestManager();
329         EventRequest eventRequest = event.request();
330         erm.deleteEventRequest(eventRequest);
331         if (eventRequest instanceof StepRequest) {
332             SingleThreadedStepWatch.stepRequestDeleted((StepRequest) eventRequest);
333         }
334         if (operationBreakpoints != null) {
335             for (Iterator JavaDoc<BreakpointRequest> it = operationBreakpoints.iterator(); it.hasNext(); ) {
336                 erm.deleteEventRequest(it.next());
337             }
338             this.operationBreakpoints = null;
339         }
340         if (boundaryStepRequest != null) {
341             erm.deleteEventRequest(boundaryStepRequest);
342             SingleThreadedStepWatch.stepRequestDeleted(boundaryStepRequest);
343         }
344         int suspendPolicy = debugger.getSuspend();
345         if (addExprStep) {
346             if (addOperationStep(tr, true)) {
347                 return true; // Resume
348
}
349         }
350         if ((event.request() instanceof StepRequest) && shouldNotStopHere(event)) {
351             return true; // Resume
352
}
353         firePropertyChange(PROP_STATE_EXEC, null, null);
354         if (! getHidden()) {
355             DebuggerManager.getDebuggerManager().setCurrentSession(session);
356             debuggerImpl.setStoppedState(tr.getThreadReference());
357         }
358         if (getHidden()) {
359             return true; // Resume
360
} else {
361             return false;
362         }
363     }
364     
365     /**
366      * Checks for synthetic methods and smart-stepping...
367      */

368     private boolean shouldNotStopHere(Event ev) {
369         JPDADebuggerImpl debuggerImpl = (JPDADebuggerImpl) debugger;
370         synchronized (debuggerImpl.LOCK) {
371             // 2) init info about current state
372
LocatableEvent event = (LocatableEvent) ev;
373             String JavaDoc className = event.location ().declaringType ().name ();
374             ThreadReference tr = event.thread ();
375             //JPDAThreadImpl ct = (JPDAThreadImpl) debuggerImpl.getCurrentThread();
376

377             // Synthetic method?
378
try {
379                 if (tr.frame(0).location().method().isSynthetic()) {
380                     //S ystem.out.println("In synthetic method -> STEP OVER/OUT again");
381

382                     VirtualMachine vm = debuggerImpl.getVirtualMachine ();
383                     if (vm == null) {
384                         return false; // The session has finished
385
}
386                     StepRequest stepRequest = vm.eventRequestManager ().createStepRequest (
387                         tr,
388                         StepRequest.STEP_LINE,
389                         getDepth()
390                     );
391                     stepRequest.addCountFilter(1);
392                     debuggerImpl.getOperator ().register (stepRequest, this);
393                     stepRequest.setSuspendPolicy (debugger.getSuspend ());
394                     try {
395                         stepRequest.enable ();
396                     } catch (IllegalThreadStateException JavaDoc itsex) {
397                         // the thread named in the request has died.
398
debuggerImpl.getOperator ().unregister (stepRequest);
399                     }
400                     return true;
401                 }
402             } catch (IncompatibleThreadStateException e) {
403                 ErrorManager.getDefault().notify(e);
404             }
405             
406             // Not synthetic
407
JPDAThread t = debuggerImpl.getThread (tr);
408             if (debuggerImpl.stopHere(t)) {
409                 //S ystem.out.println("/nStepAction.exec end - do not resume");
410
return false; // do not resume
411
}
412
413             // do not stop here -> start smart stepping!
414
VirtualMachine vm = debuggerImpl.getVirtualMachine ();
415             if (vm == null) {
416                 return false; // The session has finished
417
}
418             StepRequest stepRequest = vm.eventRequestManager ().createStepRequest (
419                 tr,
420                 StepRequest.STEP_LINE,
421                 StepRequest.STEP_INTO
422             );
423             stepRequest.addCountFilter(1);
424             debuggerImpl.getOperator ().register (stepRequest, this);
425             stepRequest.setSuspendPolicy (debugger.getSuspend ());
426             try {
427                 stepRequest.enable ();
428             } catch (IllegalThreadStateException JavaDoc itsex) {
429                 // the thread named in the request has died.
430
debuggerImpl.getOperator ().unregister (stepRequest);
431             }
432             return true; // resume
433
}
434     }
435     
436     public static final class MethodExitBreakpointListener implements JPDABreakpointListener {
437         
438         private MethodBreakpoint mb;
439         private Variable returnValue;
440         
441         public MethodExitBreakpointListener(MethodBreakpoint mb) {
442             this.mb = mb;
443         }
444         
445         public void breakpointReached(JPDABreakpointEvent event) {
446             returnValue = event.getVariable();
447         }
448         
449         public Variable getReturnValue() {
450             return returnValue;
451         }
452         
453         public void destroy() {
454             mb.removeJPDABreakpointListener(this);
455             DebuggerManager.getDebuggerManager().removeBreakpoint(mb);
456         }
457         
458     }
459     
460     public static final class SingleThreadedStepWatch implements Runnable JavaDoc {
461         
462         private static final int DELAY = 5000;
463         
464         private static final RequestProcessor stepWatchRP = new RequestProcessor("Debugger Step Watch", 1);
465         
466         private static final Map JavaDoc<StepRequest, SingleThreadedStepWatch> STEP_WATCH_POOL = new HashMap JavaDoc<StepRequest, SingleThreadedStepWatch>();
467         
468         private RequestProcessor.Task watchTask;
469         private JPDADebuggerImpl debugger;
470         private StepRequest request;
471         private Dialog JavaDoc dialog;
472         private List JavaDoc<JPDAThread> resumedThreads;
473         
474         public SingleThreadedStepWatch(JPDADebuggerImpl debugger, StepRequest request) {
475             this.debugger = debugger;
476             this.request = request;
477             watchTask = stepWatchRP.post(this, DELAY);
478             synchronized (STEP_WATCH_POOL) {
479                 STEP_WATCH_POOL.put(request, this);
480             }
481         }
482         
483         public static void stepRequestDeleted(StepRequest request) {
484             SingleThreadedStepWatch stepWatch;
485             synchronized (STEP_WATCH_POOL) {
486                 stepWatch = STEP_WATCH_POOL.remove(request);
487             }
488             if (stepWatch != null) stepWatch.done();
489         }
490         
491         public void done() {
492             synchronized (this) {
493                 watchTask.cancel();
494                 watchTask = null;
495                 if (dialog != null) {
496                     dialog.setVisible(false);
497                 }
498                 if (resumedThreads != null) {
499                     synchronized (debugger.LOCK) {
500                         suspendThreads(resumedThreads);
501                     }
502                     resumedThreads = null;
503                 }
504             }
505             synchronized (STEP_WATCH_POOL) {
506                 STEP_WATCH_POOL.remove(request);
507             }
508         }
509     
510         public void run() {
511             synchronized (this) {
512                 if (watchTask == null) return ; // We're done
513
if (request.thread().isSuspended()) {
514                     watchTask.schedule(DELAY);
515                     return ;
516                 }
517             }
518             String JavaDoc message = NbBundle.getMessage(JPDAStepImpl.class, "SingleThreadedStepBlocked");
519             final boolean[] yes = new boolean[] { true };
520             DialogDescriptor dd = new DialogDescriptor(
521                     message,
522                     new NotifyDescriptor.Confirmation(message, NotifyDescriptor.YES_NO_OPTION).getTitle(),
523                     true,
524                     NotifyDescriptor.YES_NO_OPTION,
525                     null,
526                     new ActionListener JavaDoc() {
527                         public void actionPerformed(ActionEvent JavaDoc evt) {
528                             synchronized (yes) {
529                                 yes[0] = evt.getSource() == NotifyDescriptor.YES_OPTION;
530                             }
531                         }
532                     });
533             dd.setMessageType(NotifyDescriptor.QUESTION_MESSAGE);
534             Dialog JavaDoc theDialog;
535             synchronized (this) {
536                 dialog = org.openide.DialogDisplayer.getDefault().createDialog(dd);
537                 theDialog = dialog;
538             }
539             theDialog.setVisible(true);
540             boolean doResume;
541             synchronized (yes) {
542                 doResume = yes[0];
543             }
544             synchronized (this) {
545                 dialog = null;
546                 if (watchTask == null) return ;
547                 if (doResume) {
548                     synchronized (debugger.LOCK) {
549                         List JavaDoc<JPDAThread> suspendedThreads = new ArrayList JavaDoc<JPDAThread>();
550                         JPDAThreadGroup[] tgs = debugger.getTopLevelThreadGroups();
551                         for (JPDAThreadGroup tg: tgs) {
552                             fillSuspendedThreads(tg, suspendedThreads);
553                         }
554                         resumeThreads(suspendedThreads);
555                         resumedThreads = suspendedThreads;
556                     }
557                 }
558             }
559             /*
560             Object option = org.openide.DialogDisplayer.getDefault().notify(
561                     new NotifyDescriptor.Confirmation(message, NotifyDescriptor.YES_NO_OPTION));
562             if (NotifyDescriptor.YES_OPTION == option) {
563                 debugger.resume();
564             }
565              */

566         }
567         
568         private static void fillSuspendedThreads(JPDAThreadGroup tg, List JavaDoc<JPDAThread> sts) {
569             for (JPDAThread t : tg.getThreads()) {
570                 if (t.isSuspended()) sts.add(t);
571             }
572             for (JPDAThreadGroup tgg : tg.getThreadGroups()) {
573                 fillSuspendedThreads(tgg, sts);
574             }
575         }
576         
577         private static void suspendThreads(List JavaDoc<JPDAThread> ts) {
578             for (JPDAThread t : ts) {
579                 t.suspend();
580             }
581         }
582         
583         private static void resumeThreads(List JavaDoc<JPDAThread> ts) {
584             for (JPDAThread t : ts) {
585                 t.resume();
586             }
587         }
588         
589     }
590
591 }
592
Popular Tags