Mercurial > hg > truffle
annotate agent/test/jdi/TestScaffold.java @ 17833:bfdf528be8e8
8038498: Fix includes and C inlining after 8035330
Summary: Change 8035330: Remove G1ParScanPartialArrayClosure and G1ParScanHeapEvacClosure broke the debug build on AIX. The method do_oop_partial_array() is added in a header, but requires the inline function par_write_ref() through several inlined calls. In some cpp files, like arguments.cpp, par_write_ref() is not defined as the corresponding inline header and is not included. The AIX debug VM does not start because of the missing symbol. This change solves this by cleaning up include dependencies.
Reviewed-by: tschatzl, stefank
author | tschatzl |
---|---|
date | Fri, 04 Apr 2014 10:43:56 +0200 |
parents | c18cbe5936b8 |
children |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. |
0 | 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. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 import com.sun.jdi.*; | |
26 import com.sun.jdi.request.*; | |
27 import com.sun.jdi.event.*; | |
28 import java.util.*; | |
29 import java.io.*; | |
30 | |
31 /** | |
32 * Framework used by all JDI regression tests | |
33 */ | |
34 abstract public class TestScaffold extends TargetAdapter { | |
35 private boolean shouldTrace = false; | |
36 private VMConnection connection; | |
37 private VirtualMachine vm; | |
38 private EventRequestManager requestManager; | |
39 private List listeners = Collections.synchronizedList(new LinkedList()); | |
40 | |
41 /** | |
42 * We create a VMDeathRequest, SUSPEND_ALL, to sync the BE and FE. | |
43 */ | |
44 //private VMDeathRequest ourVMDeathRequest = null; | |
45 Object ourVMDeathRequest = null; | |
46 | |
47 /** | |
48 * We create an ExceptionRequest, SUSPEND_NONE so that we can | |
49 * catch it and output a msg if an exception occurs in the | |
50 * debuggee. | |
51 */ | |
52 private ExceptionRequest ourExceptionRequest = null; | |
53 | |
54 /** | |
55 * If we do catch an uncaught exception, we set this true | |
56 * so the testcase can find out if it wants to. | |
57 */ | |
58 private boolean exceptionCaught = false; | |
59 ThreadReference vmStartThread = null; | |
60 boolean vmDied = false; | |
61 boolean vmDisconnected = false; | |
62 final String[] args; | |
63 protected boolean testFailed = false; | |
64 | |
65 static private class ArgInfo { | |
66 String targetVMArgs = ""; | |
67 String targetAppCommandLine = ""; | |
68 String connectorSpec = "com.sun.jdi.CommandLineLaunch:"; | |
69 int traceFlags = 0; | |
70 } | |
71 | |
72 /** | |
73 * An easy way to sleep for awhile | |
74 */ | |
75 public void mySleep(int millis) { | |
76 try { | |
77 Thread.sleep(millis); | |
78 } catch (InterruptedException ee) { | |
79 } | |
80 } | |
81 | |
82 boolean getExceptionCaught() { | |
83 return exceptionCaught; | |
84 } | |
85 | |
86 void setExceptionCaught(boolean value) { | |
87 exceptionCaught = value; | |
88 } | |
89 | |
90 /** | |
91 * Return true if eventSet contains the VMDeathEvent for the request in | |
92 * the ourVMDeathRequest ivar. | |
93 */ | |
94 private boolean containsOurVMDeathRequest(EventSet eventSet) { | |
95 if (ourVMDeathRequest != null) { | |
96 Iterator myIter = eventSet.iterator(); | |
97 while (myIter.hasNext()) { | |
98 Event myEvent = (Event)myIter.next(); | |
99 if (!(myEvent instanceof VMDeathEvent)) { | |
100 // We assume that an EventSet contains only VMDeathEvents | |
101 // or no VMDeathEvents. | |
102 break; | |
103 } | |
104 if (ourVMDeathRequest.equals(myEvent.request())) { | |
105 return true; | |
106 } | |
107 } | |
108 } | |
109 return false; | |
110 } | |
111 | |
112 /************************************************************************ | |
113 * The following methods override those in our base class, TargetAdapter. | |
114 *************************************************************************/ | |
115 | |
116 /** | |
117 * Events handled directly by scaffold always resume (well, almost always) | |
118 */ | |
119 public void eventSetComplete(EventSet set) { | |
120 // The listener in connect(..) resumes after receiving our | |
121 // special VMDeathEvent. We can't also do the resume | |
122 // here or we will probably get a VMDisconnectedException | |
123 if (!containsOurVMDeathRequest(set)) { | |
124 traceln("TS: set.resume() called"); | |
125 set.resume(); | |
126 } | |
127 } | |
128 | |
129 /** | |
130 * This method sets up default requests. | |
131 * Testcases can override this to change default behavior. | |
132 */ | |
133 protected void createDefaultEventRequests() { | |
134 createDefaultVMDeathRequest(); | |
135 createDefaultExceptionRequest(); | |
136 } | |
137 | |
138 /** | |
139 * We want the BE to stop when it issues a VMDeathEvent in order to | |
140 * give the FE time to complete handling events that occured before | |
141 * the VMDeath. When we get the VMDeathEvent for this request in | |
142 * the listener in connect(), we will do a resume. | |
143 * If a testcase wants to do something special with VMDeathEvent's, | |
144 * then it should override this method with an empty method or | |
145 * whatever in order to suppress the automatic resume. The testcase | |
146 * will then be responsible for the handling of VMDeathEvents. It | |
147 * has to be sure that it does a resume if it gets a VMDeathEvent | |
148 * with SUSPEND_ALL, and it has to be sure that it doesn't do a | |
149 * resume after getting a VMDeath with SUSPEND_NONE (the automatically | |
150 * generated VMDeathEvent.) | |
151 */ | |
152 protected void createDefaultVMDeathRequest() { | |
153 // ourVMDeathRequest = requestManager.createVMDeathRequest(); | |
154 // ourVMDeathRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); | |
155 // ourVMDeathRequest.enable(); | |
156 } | |
157 | |
158 /** | |
159 * This will allow us to print a warning if a debuggee gets an | |
160 * unexpected exception. The unexpected exception will be handled in | |
161 * the exceptionThrown method in the listener created in the connect() | |
162 * method. | |
163 * If a testcase does not want an uncaught exception to cause a | |
164 * msg, it must override this method. | |
165 */ | |
166 protected void createDefaultExceptionRequest() { | |
167 ourExceptionRequest = requestManager.createExceptionRequest(null, | |
168 false, true); | |
169 | |
170 // We can't afford to make this be other than SUSPEND_NONE. Otherwise, | |
171 // it would have to be resumed. If our connect() listener resumes it, | |
172 // what about the case where the EventSet contains other events with | |
173 // SUSPEND_ALL and there are other listeners who expect the BE to still | |
174 // be suspended when their handlers get called? | |
175 ourExceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); | |
176 ourExceptionRequest.enable(); | |
177 } | |
178 | |
179 private class EventHandler implements Runnable { | |
180 EventHandler() { | |
181 Thread thread = new Thread(this); | |
182 thread.setDaemon(true); | |
183 thread.start(); | |
184 } | |
185 | |
186 private void notifyEvent(TargetListener listener, Event event) { | |
187 if (event instanceof BreakpointEvent) { | |
188 listener.breakpointReached((BreakpointEvent)event); | |
189 } else if (event instanceof ExceptionEvent) { | |
190 listener.exceptionThrown((ExceptionEvent)event); | |
191 } else if (event instanceof StepEvent) { | |
192 listener.stepCompleted((StepEvent)event); | |
193 } else if (event instanceof ClassPrepareEvent) { | |
194 listener.classPrepared((ClassPrepareEvent)event); | |
195 } else if (event instanceof ClassUnloadEvent) { | |
196 listener.classUnloaded((ClassUnloadEvent)event); | |
197 } else if (event instanceof MethodEntryEvent) { | |
198 listener.methodEntered((MethodEntryEvent)event); | |
199 } else if (event instanceof MethodExitEvent) { | |
200 listener.methodExited((MethodExitEvent)event); | |
201 } else if (event instanceof AccessWatchpointEvent) { | |
202 listener.fieldAccessed((AccessWatchpointEvent)event); | |
203 } else if (event instanceof ModificationWatchpointEvent) { | |
204 listener.fieldModified((ModificationWatchpointEvent)event); | |
205 } else if (event instanceof ThreadStartEvent) { | |
206 listener.threadStarted((ThreadStartEvent)event); | |
207 } else if (event instanceof ThreadDeathEvent) { | |
208 listener.threadDied((ThreadDeathEvent)event); | |
209 } else if (event instanceof VMStartEvent) { | |
210 listener.vmStarted((VMStartEvent)event); | |
211 } else if (event instanceof VMDeathEvent) { | |
212 listener.vmDied((VMDeathEvent)event); | |
213 } else if (event instanceof VMDisconnectEvent) { | |
214 listener.vmDisconnected((VMDisconnectEvent)event); | |
215 } else { | |
216 throw new InternalError("Unknown event type: " + event.getClass()); | |
217 } | |
218 } | |
219 | |
220 private void traceSuspendPolicy(int policy) { | |
221 if (shouldTrace) { | |
222 switch (policy) { | |
223 case EventRequest.SUSPEND_NONE: | |
224 traceln("TS: eventHandler: suspend = SUSPEND_NONE"); | |
225 break; | |
226 case EventRequest.SUSPEND_ALL: | |
227 traceln("TS: eventHandler: suspend = SUSPEND_ALL"); | |
228 break; | |
229 case EventRequest.SUSPEND_EVENT_THREAD: | |
230 traceln("TS: eventHandler: suspend = SUSPEND_EVENT_THREAD"); | |
231 break; | |
232 } | |
233 } | |
234 } | |
235 | |
236 public void run() { | |
237 boolean connected = true; | |
238 do { | |
239 try { | |
240 EventSet set = vm.eventQueue().remove(); | |
241 traceSuspendPolicy(set.suspendPolicy()); | |
242 synchronized (listeners) { | |
243 ListIterator iter = listeners.listIterator(); | |
244 while (iter.hasNext()) { | |
245 TargetListener listener = (TargetListener)iter.next(); | |
246 traceln("TS: eventHandler: listener = " + listener); | |
247 listener.eventSetReceived(set); | |
248 if (listener.shouldRemoveListener()) { | |
249 iter.remove(); | |
250 } else { | |
251 Iterator jter = set.iterator(); | |
252 while (jter.hasNext()) { | |
253 Event event = (Event)jter.next(); | |
254 traceln("TS: eventHandler: event = " + event.getClass()); | |
255 | |
256 if (event instanceof VMDisconnectEvent) { | |
257 connected = false; | |
258 } | |
259 listener.eventReceived(event); | |
260 if (listener.shouldRemoveListener()) { | |
261 iter.remove(); | |
262 break; | |
263 } | |
264 notifyEvent(listener, event); | |
265 if (listener.shouldRemoveListener()) { | |
266 iter.remove(); | |
267 break; | |
268 } | |
269 } | |
270 traceln("TS: eventHandler: end of events loop"); | |
271 if (!listener.shouldRemoveListener()) { | |
272 traceln("TS: eventHandler: calling ESC"); | |
273 listener.eventSetComplete(set); | |
274 if (listener.shouldRemoveListener()) { | |
275 iter.remove(); | |
276 } | |
277 } | |
278 } | |
279 traceln("TS: eventHandler: end of listeners loop"); | |
280 } | |
281 } | |
282 } catch (InterruptedException e) { | |
283 traceln("TS: eventHandler: InterruptedException"); | |
284 } catch (Exception e) { | |
285 failure("FAILED: Exception occured in eventHandler: " + e); | |
286 e.printStackTrace(); | |
287 connected = false; | |
288 synchronized(TestScaffold.this) { | |
289 // This will make the waiters such as waitForVMDisconnect | |
290 // exit their wait loops. | |
291 vmDisconnected = true; | |
292 TestScaffold.this.notifyAll(); | |
293 } | |
294 } | |
295 traceln("TS: eventHandler: End of outerloop"); | |
296 } while (connected); | |
297 traceln("TS: eventHandler: finished"); | |
298 } | |
299 } | |
300 | |
301 /** | |
302 * Constructor | |
303 */ | |
304 public TestScaffold(String[] args) { | |
305 this.args = args; | |
306 } | |
307 | |
308 public void enableScaffoldTrace() { | |
309 this.shouldTrace = true; | |
310 } | |
311 | |
312 public void disableScaffoldTrace() { | |
313 this.shouldTrace = false; | |
314 } | |
315 | |
316 | |
317 protected void startUp(String targetName) { | |
318 List argList = new ArrayList(Arrays.asList(args)); | |
319 argList.add(targetName); | |
320 println("run args: " + argList); | |
321 connect((String[]) argList.toArray(args)); | |
322 waitForVMStart(); | |
323 } | |
324 | |
325 protected BreakpointEvent startToMain(String targetName) { | |
326 startUp(targetName); | |
327 traceln("TS: back from startUp"); | |
328 BreakpointEvent bpr = resumeTo(targetName, "main", "([Ljava/lang/String;)V"); | |
329 waitForInput(); | |
330 return bpr; | |
331 } | |
332 | |
333 protected void waitForInput() { | |
334 if (System.getProperty("jpda.wait") != null) { | |
335 try { | |
336 System.err.println("Press <enter> to continue"); | |
337 System.in.read(); | |
338 System.err.println("running..."); | |
339 | |
340 } catch(Exception e) { | |
341 } | |
342 } | |
343 } | |
344 | |
345 /* | |
346 * Test cases should implement tests in runTests and should | |
347 * initiate testing by calling run(). | |
348 */ | |
349 abstract protected void runTests() throws Exception; | |
350 | |
351 final public void startTests() throws Exception { | |
352 try { | |
353 runTests(); | |
354 } finally { | |
355 shutdown(); | |
356 } | |
357 } | |
358 | |
359 protected void println(String str) { | |
360 System.err.println(str); | |
361 } | |
362 | |
363 protected void print(String str) { | |
364 System.err.print(str); | |
365 } | |
366 | |
367 protected void traceln(String str) { | |
368 if (shouldTrace) { | |
369 println(str); | |
370 } | |
371 } | |
372 | |
373 protected void failure(String str) { | |
374 println(str); | |
375 testFailed = true; | |
376 } | |
377 | |
378 private ArgInfo parseArgs(String args[]) { | |
379 ArgInfo argInfo = new ArgInfo(); | |
380 for (int i = 0; i < args.length; i++) { | |
381 if (args[i].equals("-connect")) { | |
382 i++; | |
383 argInfo.connectorSpec = args[i]; | |
384 } else if (args[i].equals("-trace")) { | |
385 i++; | |
386 argInfo.traceFlags = Integer.decode(args[i]).intValue(); | |
387 } else if (args[i].startsWith("-J")) { | |
388 argInfo.targetVMArgs += (args[i].substring(2) + ' '); | |
389 | |
390 /* | |
391 * classpath can span two arguments so we need to handle | |
392 * it specially. | |
393 */ | |
394 if (args[i].equals("-J-classpath")) { | |
395 i++; | |
396 argInfo.targetVMArgs += (args[i] + ' '); | |
397 } | |
398 } else { | |
399 argInfo.targetAppCommandLine += (args[i] + ' '); | |
400 } | |
401 } | |
402 return argInfo; | |
403 } | |
404 | |
405 /** | |
406 * This is called to connect to a debuggee VM. It starts the VM and | |
407 * installs a listener to catch VMStartEvent, our default events, and | |
408 * VMDisconnectedEvent. When these events appear, that is remembered | |
409 * and waiters are notified. | |
410 * This is normally called in the main thread of the test case. | |
411 * It starts up an EventHandler thread that gets events coming in | |
412 * from the debuggee and distributes them to listeners. That thread | |
413 * keeps running until a VMDisconnectedEvent occurs or some exception | |
414 * occurs during its processing. | |
415 * | |
416 * The 'listenUntilVMDisconnect' method adds 'this' as a listener. | |
417 * This means that 'this's vmDied method will get called. This has a | |
418 * default impl in TargetAdapter.java which can be overridden in the | |
419 * testcase. | |
420 * | |
421 * waitForRequestedEvent also adds an adaptor listener that listens | |
422 * for the particular event it is supposed to wait for (and it also | |
423 * catches VMDisconnectEvents.) This listener is removed once | |
424 * its eventReceived method is called. | |
425 * waitForRequestedEvent is called by most of the methods to do bkpts, | |
426 * etc. | |
427 */ | |
428 public void connect(String args[]) { | |
429 ArgInfo argInfo = parseArgs(args); | |
430 | |
431 argInfo.targetVMArgs += VMConnection.getDebuggeeVMOptions(); | |
432 connection = new VMConnection(argInfo.connectorSpec, | |
433 argInfo.traceFlags); | |
434 | |
435 addListener(new TargetAdapter() { | |
436 public void eventSetComplete(EventSet set) { | |
437 if (TestScaffold.this.containsOurVMDeathRequest(set)) { | |
438 traceln("TS: connect: set.resume() called"); | |
439 set.resume(); | |
440 | |
441 // Note that we want to do the above resume before | |
442 // waking up any sleepers. | |
443 synchronized(TestScaffold.this) { | |
444 TestScaffold.this.notifyAll(); | |
445 } | |
446 } | |
447 } | |
448 | |
449 public void vmStarted(VMStartEvent event) { | |
450 synchronized(TestScaffold.this) { | |
451 vmStartThread = event.thread(); | |
452 TestScaffold.this.notifyAll(); | |
453 } | |
454 } | |
455 /** | |
456 * By default, we catch uncaught exceptions and print a msg. | |
457 * The testcase must override the createDefaultExceptionRequest | |
458 * method if it doesn't want this behavior. | |
459 */ | |
460 public void exceptionThrown(ExceptionEvent event) { | |
461 if (TestScaffold.this.ourExceptionRequest != null && | |
462 TestScaffold.this.ourExceptionRequest.equals( | |
463 event.request())) { | |
464 println("Note: Unexpected Debuggee Exception: " + | |
465 event.exception().referenceType().name() + | |
466 " at line " + event.location().lineNumber()); | |
467 TestScaffold.this.exceptionCaught = true; | |
468 } | |
469 } | |
470 | |
471 public void vmDied(VMDeathEvent event) { | |
472 vmDied = true; | |
473 traceln("TS: vmDied called"); | |
474 } | |
475 | |
476 public void vmDisconnected(VMDisconnectEvent event) { | |
477 synchronized(TestScaffold.this) { | |
478 vmDisconnected = true; | |
479 TestScaffold.this.notifyAll(); | |
480 } | |
481 } | |
482 }); | |
483 if (connection.connector().name().equals("com.sun.jdi.CommandLineLaunch")) { | |
484 if (argInfo.targetVMArgs.length() > 0) { | |
485 if (connection.connectorArg("options").length() > 0) { | |
486 throw new IllegalArgumentException("VM options in two places"); | |
487 } | |
488 connection.setConnectorArg("options", argInfo.targetVMArgs); | |
489 } | |
490 if (argInfo.targetAppCommandLine.length() > 0) { | |
491 if (connection.connectorArg("main").length() > 0) { | |
492 throw new IllegalArgumentException("Command line in two places"); | |
493 } | |
494 connection.setConnectorArg("main", argInfo.targetAppCommandLine); | |
495 } | |
496 } | |
497 | |
498 vm = connection.open(); | |
499 requestManager = vm.eventRequestManager(); | |
500 createDefaultEventRequests(); | |
501 new EventHandler(); | |
502 } | |
503 | |
504 | |
505 public VirtualMachine vm() { | |
506 return vm; | |
507 } | |
508 | |
509 public EventRequestManager eventRequestManager() { | |
510 return requestManager; | |
511 } | |
512 | |
513 public void addListener(TargetListener listener) { | |
514 traceln("TS: Adding listener " + listener); | |
515 listeners.add(listener); | |
516 } | |
517 | |
518 public void removeListener(TargetListener listener) { | |
519 traceln("TS: Removing listener " + listener); | |
520 listeners.remove(listener); | |
521 } | |
522 | |
523 | |
524 protected void listenUntilVMDisconnect() { | |
525 try { | |
526 addListener (this); | |
527 } catch (Exception ex){ | |
528 ex.printStackTrace(); | |
529 testFailed = true; | |
530 } finally { | |
531 // Allow application to complete and shut down | |
532 resumeToVMDisconnect(); | |
533 } | |
534 } | |
535 | |
536 public synchronized ThreadReference waitForVMStart() { | |
537 while ((vmStartThread == null) && !vmDisconnected) { | |
538 try { | |
539 wait(); | |
540 } catch (InterruptedException e) { | |
541 } | |
542 } | |
543 | |
544 if (vmStartThread == null) { | |
545 throw new VMDisconnectedException(); | |
546 } | |
547 | |
548 return vmStartThread; | |
549 } | |
550 | |
551 public synchronized void waitForVMDisconnect() { | |
552 traceln("TS: waitForVMDisconnect"); | |
553 while (!vmDisconnected) { | |
554 try { | |
555 wait(); | |
556 } catch (InterruptedException e) { | |
557 } | |
558 } | |
559 traceln("TS: waitForVMDisconnect: done"); | |
560 } | |
561 | |
562 public Event waitForRequestedEvent(final EventRequest request) { | |
563 class EventNotification { | |
564 Event event; | |
565 boolean disconnected = false; | |
566 } | |
567 final EventNotification en = new EventNotification(); | |
568 | |
569 TargetAdapter adapter = new TargetAdapter() { | |
570 public void eventReceived(Event event) { | |
571 if (request.equals(event.request())) { | |
572 traceln("TS:Listener2: got requested event"); | |
573 synchronized (en) { | |
574 en.event = event; | |
575 en.notifyAll(); | |
576 } | |
577 removeThisListener(); | |
578 } else if (event instanceof VMDisconnectEvent) { | |
579 traceln("TS:Listener2: got VMDisconnectEvent"); | |
580 synchronized (en) { | |
581 en.disconnected = true; | |
582 en.notifyAll(); | |
583 } | |
584 removeThisListener(); | |
585 } | |
586 } | |
587 }; | |
588 | |
589 addListener(adapter); | |
590 | |
591 try { | |
592 synchronized (en) { | |
593 traceln("TS: waitForRequestedEvent: vm.resume called"); | |
594 vm.resume(); | |
595 | |
596 while (!en.disconnected && (en.event == null)) { | |
597 en.wait(); | |
598 } | |
599 } | |
600 } catch (InterruptedException e) { | |
601 return null; | |
602 } | |
603 | |
604 if (en.disconnected) { | |
605 throw new RuntimeException("VM Disconnected before requested event occurred"); | |
606 } | |
607 return en.event; | |
608 } | |
609 | |
610 private StepEvent doStep(ThreadReference thread, int gran, int depth) { | |
611 final StepRequest sr = | |
612 requestManager.createStepRequest(thread, gran, depth); | |
613 | |
614 sr.addClassExclusionFilter("java.*"); | |
615 sr.addClassExclusionFilter("sun.*"); | |
616 sr.addClassExclusionFilter("com.sun.*"); | |
617 sr.addCountFilter(1); | |
618 sr.enable(); | |
619 StepEvent retEvent = (StepEvent)waitForRequestedEvent(sr); | |
620 requestManager.deleteEventRequest(sr); | |
621 return retEvent; | |
622 } | |
623 | |
624 public StepEvent stepIntoInstruction(ThreadReference thread) { | |
625 return doStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO); | |
626 } | |
627 | |
628 public StepEvent stepIntoLine(ThreadReference thread) { | |
629 return doStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); | |
630 } | |
631 | |
632 public StepEvent stepOverInstruction(ThreadReference thread) { | |
633 return doStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OVER); | |
634 } | |
635 | |
636 public StepEvent stepOverLine(ThreadReference thread) { | |
637 return doStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER); | |
638 } | |
639 | |
640 public StepEvent stepOut(ThreadReference thread) { | |
641 return doStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_OUT); | |
642 } | |
643 | |
644 public BreakpointEvent resumeTo(Location loc) { | |
645 final BreakpointRequest request = | |
646 requestManager.createBreakpointRequest(loc); | |
647 request.addCountFilter(1); | |
648 request.enable(); | |
649 return (BreakpointEvent)waitForRequestedEvent(request); | |
650 } | |
651 | |
652 public ReferenceType findReferenceType(String name) { | |
653 List rts = vm.classesByName(name); | |
654 Iterator iter = rts.iterator(); | |
655 while (iter.hasNext()) { | |
656 ReferenceType rt = (ReferenceType)iter.next(); | |
657 if (rt.name().equals(name)) { | |
658 return rt; | |
659 } | |
660 } | |
661 return null; | |
662 } | |
663 | |
664 public Method findMethod(ReferenceType rt, String name, String signature) { | |
665 List methods = rt.methods(); | |
666 Iterator iter = methods.iterator(); | |
667 while (iter.hasNext()) { | |
668 Method method = (Method)iter.next(); | |
669 if (method.name().equals(name) && | |
670 method.signature().equals(signature)) { | |
671 return method; | |
672 } | |
673 } | |
674 return null; | |
675 } | |
676 | |
677 public Location findLocation(ReferenceType rt, int lineNumber) | |
678 throws AbsentInformationException { | |
679 List locs = rt.locationsOfLine(lineNumber); | |
680 if (locs.size() == 0) { | |
681 throw new IllegalArgumentException("Bad line number"); | |
682 } else if (locs.size() > 1) { | |
683 throw new IllegalArgumentException("Line number has multiple locations"); | |
684 } | |
685 | |
686 return (Location)locs.get(0); | |
687 } | |
688 | |
689 public BreakpointEvent resumeTo(String clsName, String methodName, | |
690 String methodSignature) { | |
691 ReferenceType rt = findReferenceType(clsName); | |
692 if (rt == null) { | |
693 rt = resumeToPrepareOf(clsName).referenceType(); | |
694 } | |
695 | |
696 Method method = findMethod(rt, methodName, methodSignature); | |
697 if (method == null) { | |
698 throw new IllegalArgumentException("Bad method name/signature"); | |
699 } | |
700 | |
701 return resumeTo(method.location()); | |
702 } | |
703 | |
704 public BreakpointEvent resumeTo(String clsName, int lineNumber) throws AbsentInformationException { | |
705 ReferenceType rt = findReferenceType(clsName); | |
706 if (rt == null) { | |
707 rt = resumeToPrepareOf(clsName).referenceType(); | |
708 } | |
709 | |
710 return resumeTo(findLocation(rt, lineNumber)); | |
711 } | |
712 | |
713 public ClassPrepareEvent resumeToPrepareOf(String className) { | |
714 final ClassPrepareRequest request = | |
715 requestManager.createClassPrepareRequest(); | |
716 request.addClassFilter(className); | |
717 request.addCountFilter(1); | |
718 request.enable(); | |
719 return (ClassPrepareEvent)waitForRequestedEvent(request); | |
720 } | |
721 | |
722 public void resumeToVMDisconnect() { | |
723 try { | |
724 traceln("TS: resumeToVMDisconnect: vm.resume called"); | |
725 vm.resume(); | |
726 } catch (VMDisconnectedException e) { | |
727 // clean up below | |
728 } | |
729 waitForVMDisconnect(); | |
730 } | |
731 | |
732 public void shutdown() { | |
733 shutdown(null); | |
734 } | |
735 | |
736 public void shutdown(String message) { | |
737 traceln("TS: shutdown: vmDied= " + vmDied + | |
738 ", vmDisconnected= " + vmDisconnected + | |
739 ", connection = " + connection); | |
740 | |
741 if ((connection != null)) { | |
742 try { | |
743 connection.disposeVM(); | |
744 } catch (VMDisconnectedException e) { | |
745 // Shutting down after the VM has gone away. This is | |
746 // not an error, and we just ignore it. | |
747 } | |
748 } else { | |
749 traceln("TS: shutdown: disposeVM not called"); | |
750 } | |
751 if (message != null) { | |
752 println(message); | |
753 } | |
754 | |
755 vmDied = true; | |
756 vmDisconnected = true; | |
757 } | |
758 } |