1 33 34 package edu.rice.cs.drjava.model.debug; 35 36 import java.io.*; 37 import java.util.Enumeration ; 38 import java.util.Iterator ; 39 import java.util.LinkedList ; 40 import java.util.List ; 41 import java.util.Map ; 42 import java.util.NoSuchElementException ; 43 import java.util.Stack ; 44 import java.util.StringTokenizer ; 45 import java.util.Vector ; 46 47 import edu.rice.cs.util.StringOps; 49 import edu.rice.cs.util.UnexpectedException; 50 import edu.rice.cs.util.swing.Utilities; 51 import edu.rice.cs.drjava.model.DefaultGlobalModel; 52 import edu.rice.cs.drjava.model.repl.DefaultInteractionsModel; 53 import edu.rice.cs.drjava.model.repl.DummyInteractionsListener; 54 import edu.rice.cs.drjava.model.repl.InteractionsListener; 55 import edu.rice.cs.drjava.model.GlobalModelListener; 56 import edu.rice.cs.drjava.model.OpenDefinitionsDocument; 57 import edu.rice.cs.util.Log; 58 import edu.rice.cs.util.Lambda; 59 60 import com.sun.jdi.*; 61 import com.sun.jdi.connect.*; 62 import com.sun.jdi.request.*; 63 import com.sun.jdi.event.*; 64 import javax.swing.SwingUtilities ; 65 66 76 public class JPDADebugger implements Debugger, DebugModelCallback { 77 78 79 private static final Log _log = new Log("GlobalModelTest.txt", false); 80 81 private static final int OBJECT_COLLECTED_TRIES = 5; 84 85 86 private volatile DefaultGlobalModel _model; 87 88 89 private volatile VirtualMachine _vm; 90 91 92 private volatile EventRequestManager _eventManager; 93 94 95 private final Vector <DebugWatchData> _watches = new Vector <DebugWatchData>(); 96 97 100 private final PendingRequestManager _pendingRequestManager = new PendingRequestManager(this); 101 102 103 final DebugEventNotifier _notifier = new DebugEventNotifier(); 104 105 106 private volatile ThreadReference _runningThread; 107 108 109 private volatile RandomAccessStack _suspendedThreads; 110 111 112 private volatile ObjectReference _interpreterJVM; 113 114 private volatile InteractionsListener _watchListener; 115 116 117 private volatile Throwable _eventHandlerError; 118 119 122 public JPDADebugger(DefaultGlobalModel model) { 123 _model = model; 124 _vm = null; 125 _eventManager = null; 126 127 _suspendedThreads = new RandomAccessStack(); 128 _runningThread = null; 129 _interpreterJVM = null; 130 _eventHandlerError = null; 131 132 _watchListener = new DummyInteractionsListener() { 135 public void interactionEnded() { 136 try { _updateWatches(); } 137 catch(DebugException de) { _log("couldn't update watches", de); } 138 } 139 }; 140 } 141 142 145 public void addListener(DebugListener listener) { 146 _notifier.addListener(listener); 147 _model.getBreakpointManager().addListener(listener); 148 } 149 150 153 public void removeListener(DebugListener listener) { 154 _notifier.removeListener(listener); 155 _model.getBreakpointManager().removeListener(listener); 156 } 157 158 159 VirtualMachine getVM() { return _vm; } 160 161 164 private void _log(String message) { _log.log(message); } 165 166 170 private void _log(String message, Throwable t) { _log.log(message, t); } 171 172 175 public boolean isAvailable() { return true; } 176 177 178 public boolean isReady() { return _vm != null; } 179 180 185 private void _ensureReady() throws DebugException { 186 if (! isReady()) throw new IllegalStateException ("Debugger is not active."); 187 188 if (_eventHandlerError != null) { 189 Throwable t = _eventHandlerError; 190 _eventHandlerError = null; 191 throw new DebugException("Error in Debugger Event Handler: " + t); 192 } 193 } 194 195 199 void eventHandlerError(Throwable t) { 200 _log("Error in EventHandlerThread: " + t); 201 _eventHandlerError = t; 202 } 203 204 205 public synchronized void startUp() throws DebugException { 206 if (! isReady()) { 207 _eventHandlerError = null; 208 for (OpenDefinitionsDocument doc: _model.getOpenDefinitionsDocuments()) { 210 doc.checkIfClassFileInSync(); 211 } 212 213 try { _attachToVM(); } 214 catch(DebugException e1) { try { 216 try { Thread.sleep(100); } catch (InterruptedException e) { } 218 _attachToVM(); 219 System.out.println("Two attempts required for debugger to attach to slave JVM"); 220 } 221 catch(DebugException e2) { 222 try { Thread.sleep(100); } catch (InterruptedException e) { } 224 _attachToVM(); 225 System.out.println("Three attempts required for debugger to attach to slave JVM"); 226 } } 228 229 ThreadDeathRequest tdr = _eventManager.createThreadDeathRequest(); 231 tdr.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); 232 tdr.enable(); 233 234 EventHandlerThread eventHandler = new EventHandlerThread(this, _vm); 236 eventHandler.start(); 237 238 240 SwingUtilities.invokeLater(new Runnable () { 241 public void run() { _model.getInteractionsModel().addListener(_watchListener); } 242 }); 243 244 Vector <Breakpoint> oldBreakpoints = new Vector <Breakpoint>(_model.getBreakpointManager().getRegions()); 246 _model.getBreakpointManager().clearRegions(); 247 for (int i = 0; i < oldBreakpoints.size(); i++) { 248 Breakpoint bp = oldBreakpoints.get(i); 249 setBreakpoint(new Breakpoint(bp.getDocument(), bp.getOffset(), bp.getLineNumber(), bp.isEnabled(), this)); 250 } 251 } 252 253 else 254 throw new IllegalStateException ("Debugger has already been started."); 256 } 257 258 259 260 private void _attachToVM() throws DebugException { 261 _model.waitForInterpreter(); 263 264 AttachingConnector connector = _getAttachingConnector(); 266 267 Map <String , Connector.Argument> args = connector.defaultArguments(); 269 Connector.Argument port = args.get("port"); 270 Connector.Argument host = args.get("hostname"); 271 try { 272 int debugPort = _model.getDebugPort(); 273 port.setValue("" + debugPort); 274 host.setValue("127.0.0.1"); _vm = connector.attach(args); 276 _eventManager = _vm.eventRequestManager(); 277 } 278 catch(Exception e) { throw new DebugException("Could not connect to VM: " + e); } 279 280 _interpreterJVM = _getInterpreterJVMRef(); 281 } 282 283 284 private AttachingConnector _getAttachingConnector() 285 throws DebugException { 286 VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); 287 List <AttachingConnector> connectors = vmm.attachingConnectors(); 288 AttachingConnector connector = null; 289 for (AttachingConnector conn: connectors) { 290 if (conn.name().equals("com.sun.jdi.SocketAttach")) connector = conn; 291 } 292 if (connector == null) throw new DebugException("Could not find an AttachingConnector!"); 293 return connector; 294 } 295 296 299 private ObjectReference _getInterpreterJVMRef() 300 throws DebugException { 301 String className = "edu.rice.cs.drjava.model.repl.newjvm.InterpreterJVM"; 302 List <ReferenceType> referenceTypes = _vm.classesByName(className); if (referenceTypes.size() > 0) { 304 ReferenceType rt = referenceTypes.get(0); 305 Field field = rt.fieldByName("ONLY"); 306 if (field == null) throw new DebugException("Unable to get ONLY field"); 307 return (ObjectReference) rt.getValue(field); 308 } 309 else throw new DebugException("Could not get a reference to interpreterJVM"); 310 } 311 312 315 public synchronized void shutdown() { 316 if (isReady()) { 317 Runnable command = new Runnable () { public void run() { _model.getInteractionsModel().removeListener(_watchListener); } }; 318 319 321 SwingUtilities.invokeLater(command); 322 323 _removeAllDebugInterpreters(); 324 325 try { _vm.dispose(); } 326 catch (VMDisconnectedException vmde) { 327 } 329 finally { 330 _model.getInteractionsModel().setToDefaultInterpreter(); 331 _vm = null; 332 _suspendedThreads = new RandomAccessStack(); 333 _eventManager = null; 334 _runningThread = null; 335 try { _updateWatches(); } 336 catch (DebugException de) { 337 _log("Could not remove breakpoints/watches or update watches: " + de); 339 } 340 } 341 } 342 } 343 344 345 346 EventRequestManager getEventRequestManager() { return _eventManager; } 347 348 349 PendingRequestManager getPendingRequestManager() { return _pendingRequestManager; } 350 351 363 synchronized boolean setCurrentThread(ThreadReference thread) { 364 if (! thread.isSuspended()) { 365 throw new IllegalArgumentException ("Thread must be suspended to set as current. Given: " + thread); 366 } 367 368 try { 369 if ((_suspendedThreads.isEmpty() || !_suspendedThreads.contains(thread.uniqueID())) && 370 (thread.frameCount() > 0)) { 371 _suspendedThreads.push(thread); 372 return true; 373 } 374 else return false; 375 } 376 catch (IncompatibleThreadStateException itse) { 377 throw new UnexpectedException(itse); 380 } 381 } 382 383 391 public synchronized void setCurrentThread(DebugThreadData threadData) throws DebugException { 392 _ensureReady(); 393 394 if (threadData == null) { 395 throw new IllegalArgumentException ("Cannot set current thread to null."); 396 } 397 398 ThreadReference threadRef = _getThreadFromDebugThreadData(threadData); 399 400 403 410 if (_suspendedThreads.contains(threadRef.uniqueID())) _suspendedThreads.remove(threadRef.uniqueID()); 413 414 if (!threadRef.isSuspended()) { 415 throw new IllegalArgumentException ("Given thread must be suspended."); 416 } 436 437 _suspendedThreads.push(threadRef); 438 439 try { 440 if (threadRef.frameCount() <= 0) { 441 printMessage(threadRef.name() + " could not be suspended since it has no stackframes."); 442 resume(); 443 return; 444 } 445 } 446 catch (IncompatibleThreadStateException e) { 447 throw new DebugException("Could not suspend thread: " + e); 448 } 449 450 _switchToInterpreterForThreadReference(threadRef); 452 _switchToSuspendedThread(); 453 printMessage("The current thread has changed."); 454 } 455 456 457 ThreadReference getCurrentThread() { 458 return _suspendedThreads.peek(); 460 } 461 462 465 ThreadReference getThreadAt(int i) { return _suspendedThreads.peekAt(i); } 466 467 468 ThreadReference getCurrentRunningThread() { return _runningThread; } 469 470 471 public synchronized boolean hasSuspendedThreads() throws DebugException { 472 if (! isReady()) return false; 473 return _suspendedThreads.size() > 0; 474 } 475 476 477 public synchronized boolean isCurrentThreadSuspended() throws DebugException { 478 if (! isReady()) return false; 479 return hasSuspendedThreads() && !hasRunningThread(); 480 } 481 482 483 public synchronized boolean hasRunningThread() throws DebugException { 484 if (! isReady()) return false; 485 return _runningThread != null; 486 } 487 488 493 Vector <ReferenceType> getReferenceTypes(String className) { 494 return getReferenceTypes(className, DebugAction.ANY_LINE); 495 } 496 497 507 synchronized Vector <ReferenceType> getReferenceTypes(String className, int lineNumber) { 508 List <ReferenceType> classes; 510 511 try { classes = _vm.classesByName(className); } 512 catch (VMDisconnectedException vmde) { 513 return new Vector <ReferenceType>(); 515 } 516 517 Vector <ReferenceType> refTypes = new Vector <ReferenceType>(); 519 ReferenceType ref; 520 for (int i=0; i < classes.size(); i++) { 521 ref = classes.get(i); 522 523 if (lineNumber != DebugAction.ANY_LINE) { 524 List <Location> lines = new LinkedList <Location>(); 525 try { 526 lines = ref.locationsOfLine(lineNumber); } 528 catch (AbsentInformationException aie) { 529 } 531 catch (ClassNotPreparedException cnpe) { 532 continue; 534 } 535 if (lines.size() == 0) { 537 List <ReferenceType> innerRefs = ref.nestedTypes(); ref = null; 541 for (int j = 0; j < innerRefs.size(); j++) { 542 try { 543 ReferenceType currRef = innerRefs.get(j); 544 lines = currRef.locationsOfLine(lineNumber); if (lines.size() > 0) { 546 ref = currRef; 547 break; 548 } 549 } 550 catch (AbsentInformationException aie) { 551 } 553 catch (ClassNotPreparedException cnpe) { 554 } 556 } 557 } 558 } 559 if ((ref != null) && ref.isPrepared()) { 560 refTypes.add(ref); 561 } 562 } 563 return refTypes; 564 } 565 566 570 private ThreadReference _getThreadFromDebugThreadData(DebugThreadData d) throws NoSuchElementException { 571 List <ThreadReference> threads = _vm.allThreads(); 572 Iterator <ThreadReference> iterator = threads.iterator(); 573 while (iterator.hasNext()) { 574 ThreadReference threadRef = iterator.next(); 575 if (threadRef.uniqueID() == d.getUniqueID()) { 576 return threadRef; 577 } 578 } 579 throw new NoSuchElementException ("Thread " + d.getName() + " not found in virtual machine!"); 581 } 582 583 605 606 621 622 625 private void _resumeFromStep() throws DebugException { _resumeHelper(true); } 626 627 628 public synchronized void resume() throws DebugException { 629 _ensureReady(); 630 _resumeHelper(false); 631 } 632 633 637 private void _resumeHelper(boolean fromStep) throws DebugException { 638 try { 639 ThreadReference thread = _suspendedThreads.pop(); 640 641 _log.log("In resumeThread()"); 642 _resumeThread(thread, fromStep); 643 } 644 catch (NoSuchElementException e) { throw new DebugException("No thread to resume."); } 645 } 646 647 650 public synchronized void resume(DebugThreadData threadData) throws DebugException { 651 _ensureReady(); 652 ThreadReference thread = _suspendedThreads.remove(threadData.getUniqueID()); 653 _resumeThread(thread, false); 654 } 655 656 665 private void _resumeThread(ThreadReference thread, boolean fromStep) throws DebugException { 666 if (thread == null) { 667 throw new IllegalArgumentException ("Cannot resume a null thread"); 668 } 669 670 int suspendCount = thread.suspendCount(); 671 _log.log("Getting suspendCount = " + suspendCount); 672 673 674 _runningThread = thread; 675 if (!fromStep) { 676 _copyVariablesFromInterpreter(); 678 _updateWatches(); 679 } 680 try { 681 _removeCurrentDebugInterpreter(fromStep); 682 currThreadResumed(); 683 } 684 catch(DebugException e) { throw new UnexpectedException(e); } 685 686 for (int i=suspendCount; i>0; i--) thread.resume(); 688 689 691 if (! fromStep && ! _suspendedThreads.isEmpty()) _switchToSuspendedThread(); 693 } 694 695 701 public synchronized void step(int flag) throws DebugException { 702 _ensureReady(); 703 _stepHelper(flag, true); 704 } 705 706 711 private void _stepHelper(int flag, boolean shouldNotify) throws DebugException { 712 if (_suspendedThreads.size() <= 0 || _runningThread != null) { 713 throw new IllegalStateException ("Cannot step if the current thread is not suspended."); 714 } 715 716 _log.log(this + "is About to peek ..."); 717 718 ThreadReference thread = _suspendedThreads.peek(); 719 _log.log(this + "is Stepping " + thread.toString()); 720 721 _runningThread = thread; 725 _copyVariablesFromInterpreter(); 726 727 _log.log(this + " is Deleting pending requests ..."); 728 729 List <StepRequest> steps = _eventManager.stepRequests(); for (int i = 0; i < steps.size(); i++) { 733 StepRequest step = steps.get(i); 734 if (step.thread().equals(thread)) { 735 _eventManager.deleteEventRequest(step); 736 break; 737 } 738 } 739 740 _log.log(this + " Issued step request"); 741 new Step(this, StepRequest.STEP_LINE, flag); 743 if (shouldNotify) notifyStepRequested(); 744 _log.log(this + " About to resume"); 745 _resumeFromStep(); 746 } 747 748 749 753 public synchronized void addWatch(String field) throws DebugException { 754 756 final DebugWatchData w = new DebugWatchData(field); 757 _watches.add(w); 758 _updateWatches(); 759 760 Utilities.invokeLater(new Runnable () { public void run() { _notifier.watchSet(w); } }); 761 } 762 763 768 public synchronized void removeWatch(String field) throws DebugException { 769 771 for (int i=0; i < _watches.size(); i++) { 772 final DebugWatchData watch = _watches.get(i); 773 if (watch.getName().equals(field)) { 774 _watches.remove(i); 775 Utilities.invokeLater(new Runnable () { public void run() { _notifier.watchRemoved(watch); } }); 776 } 777 } 778 } 779 780 784 public synchronized void removeWatch(int index) throws DebugException { 785 787 if (index < _watches.size()) { 788 final DebugWatchData watch = _watches.get(index); 789 _watches.remove(index); 790 Utilities.invokeLater(new Runnable () { public void run() { _notifier.watchRemoved(watch); } }); 791 } 792 } 793 794 797 public synchronized void removeAllWatches() throws DebugException { 798 800 while (_watches.size() > 0) { 801 removeWatch( _watches.get(0).getName()); 802 } 803 } 804 805 809 public synchronized void notifyBreakpointChange(Breakpoint breakpoint) { 810 _model.getBreakpointManager().changeRegion(breakpoint, new Lambda<Object , Breakpoint>() { 811 public Object apply(Breakpoint bp) { 812 return null; 814 } 815 }); 816 } 817 818 824 public synchronized void toggleBreakpoint(OpenDefinitionsDocument doc, int offset, int lineNum, boolean isEnabled) 825 throws DebugException { 826 827 Breakpoint breakpoint = _model.getBreakpointManager().getRegionAt(doc, offset); 828 829 if (breakpoint == null) { 830 if (doc.getLineStartPos(offset) == doc.getLineEndPos(offset)) { 831 Utilities.show("Cannot set a breakpoint on an empty line."); 832 } 833 else { 834 try { setBreakpoint(new Breakpoint (doc, offset, lineNum, isEnabled, this)); } 835 catch(LineNotExecutableException lnee) { Utilities.show(lnee.getMessage()); } 836 } 837 } 838 else _model.getBreakpointManager().removeRegion(breakpoint); 839 } 840 841 844 public synchronized void setBreakpoint(final Breakpoint breakpoint) throws DebugException { 845 breakpoint.getDocument().checkIfClassFileInSync(); 846 847 _model.getBreakpointManager().addRegion(breakpoint); 848 } 849 850 853 public synchronized void removeBreakpoint(final Breakpoint breakpoint) throws DebugException { 854 Vector <BreakpointRequest> requests = breakpoint.getRequests(); 855 if (requests.size() > 0 && _eventManager != null) { 856 try { 858 for (int i=0; i < requests.size(); i++) { 859 _eventManager.deleteEventRequest(requests.get(i)); 860 } 861 } 862 catch (VMMismatchException vme) { 863 _log("VMMismatch when removing breakpoint.", vme); 866 } 867 catch (VMDisconnectedException vmde) { 868 _log("VMDisconnected when removing breakpoint.", vmde); 871 } 872 } 873 874 _pendingRequestManager.removePendingRequest(breakpoint); 876 } 877 878 882 synchronized void reachedBreakpoint(BreakpointRequest request) { 883 Object property = request.getProperty("debugAction"); 885 if ( (property != null) && (property instanceof Breakpoint) ) { 886 final Breakpoint breakpoint = (Breakpoint) property; 887 printMessage("Breakpoint hit in class " + breakpoint.getClassName() + " [line " + breakpoint.getLineNumber() + "]"); 888 889 Utilities.invokeLater(new Runnable () { public void run() { _notifier.breakpointReached(breakpoint); } }); 890 } 891 else { 892 _log("Reached a breakpoint without a debugAction property: " + request); 894 } 895 } 896 897 898 public synchronized Vector <DebugWatchData> getWatches() throws DebugException { 899 return _watches; 901 } 902 903 907 public synchronized Vector <DebugThreadData> getCurrentThreadData() throws DebugException { 908 if (! isReady()) { return new Vector <DebugThreadData>(); } 909 List <ThreadReference> listThreads; try { 911 listThreads = _vm.allThreads(); } 913 catch (VMDisconnectedException vmde) { 914 return new Vector <DebugThreadData>(); 916 } 917 918 Iterator <ThreadReference> iter = listThreads.iterator(); Vector <DebugThreadData> threads = new Vector <DebugThreadData>(); 921 while (iter.hasNext()) { 922 try { 923 threads.add(new DebugThreadData(iter.next())); 924 } 925 catch (ObjectCollectedException e) { 926 } 928 } 929 return threads; 930 } 931 932 938 public synchronized Vector <DebugStackData> getCurrentStackFrameData() 939 throws DebugException 940 { 941 if (! isReady()) return new Vector <DebugStackData>(); 942 943 if (_runningThread != null || _suspendedThreads.size() <= 0) { 944 throw new DebugException("No suspended thread to obtain stack frames."); 945 } 946 947 try { 948 ThreadReference thread = _suspendedThreads.peek(); 949 Iterator <StackFrame> iter = thread.frames().iterator(); Vector <DebugStackData> frames = new Vector <DebugStackData>(); 951 while (iter.hasNext()) { 952 frames.add(new DebugStackData(iter.next())); 953 } 954 return frames; 955 } 956 catch (IncompatibleThreadStateException itse) { 957 _log("Unable to obtain stack frame.", itse); 958 return new Vector <DebugStackData>(); 959 } 960 catch (VMDisconnectedException vmde) { 961 _log("VMDisconnected when getting the current stack frame data.", vmde); 962 return new Vector <DebugStackData>(); 963 } 964 catch (InvalidStackFrameException isfe) { 965 _log("The stack frame requested is invalid.", isfe); 966 return new Vector <DebugStackData>(); 967 } 968 } 969 970 974 synchronized void scrollToSource(LocatableEvent e) { 975 Location location = e.location(); 976 977 EventRequest request = e.request(); 979 Object docProp = request.getProperty("document"); 980 if ((docProp != null) && (docProp instanceof OpenDefinitionsDocument)) { 981 openAndScroll((OpenDefinitionsDocument) docProp, location, true); 982 } 983 else scrollToSource(location); 984 } 985 986 987 synchronized void scrollToSource(Location location) { 988 scrollToSource(location, true); 989 } 990 991 992 synchronized void scrollToSource(Location location, boolean shouldHighlight) { 993 OpenDefinitionsDocument doc = null; 994 995 ReferenceType rt = location.declaringType(); 997 String fileName; 998 try { fileName = getPackageDir(rt.name()) + rt.sourceName(); } 999 catch (AbsentInformationException aie) { 1000 String className = rt.name(); 1003 String ps = System.getProperty("file.separator"); 1004 className = StringOps.replace(className, ".", ps); 1006 1007 int indexOfDollar = className.indexOf('$'); 1009 if (indexOfDollar > -1) { 1010 className = className.substring(0, indexOfDollar); 1011 } 1012 1013 fileName = className + ".java"; 1014 } 1015 1016 File f = _model.getSourceFile(fileName); 1018 1030 if (f != null) { 1031 try { doc = _model.getDocumentForFile(f); } 1033 catch (IOException ioe) { 1034 } 1036 } 1037 1038 openAndScroll(doc, location, shouldHighlight); 1039 } 1040 1041 1046 public synchronized void scrollToSource(DebugStackData stackData) throws DebugException { 1047 _ensureReady(); 1048 if (_runningThread != null) { 1049 throw new DebugException("Cannot scroll to source unless thread is suspended."); 1050 } 1051 1052 ThreadReference threadRef = _suspendedThreads.peek(); 1053 Iterator <StackFrame> i; 1054 1055 try { 1056 if (threadRef.frameCount() <= 0 ) { 1057 printMessage("Could not scroll to source. The current thread had no stack frames."); 1058 return; 1059 } 1060 i = threadRef.frames().iterator(); } 1062 catch (IncompatibleThreadStateException e) { 1063 throw new DebugException("Unable to find stack frames: " + e); 1064 } 1065 1066 while (i.hasNext()) { 1067 StackFrame frame = i.next(); 1068 1069 if (frame.location().lineNumber() == stackData.getLine() && 1070 stackData.getMethod().equals(frame.location().declaringType().name() + "." + 1071 frame.location().method().name())) 1072 { 1073 scrollToSource(frame.location(), false); 1074 } 1075 } 1076 } 1077 1078 1081 public synchronized void scrollToSource(Breakpoint bp) { 1082 openAndScroll(bp.getDocument(), bp.getLineNumber(), bp.getClassName(), false); 1083 } 1084 1085 1093 public synchronized Breakpoint getBreakpoint(int line, String className) { 1094 for (int i = 0; i < _model.getBreakpointManager().getRegions().size(); i++) { 1095 Breakpoint bp = _model.getBreakpointManager().getRegions().get(i); 1096 if ((bp.getLineNumber() == line) && (bp.getClassName().equals(className))) { 1097 return bp; 1098 } 1099 } 1100 return null; 1102 } 1103 1104 1111 synchronized void openAndScroll(OpenDefinitionsDocument doc, Location location, boolean shouldHighlight) { 1112 openAndScroll(doc, location.lineNumber(), location.declaringType().name(), shouldHighlight); 1113 } 1114 1115 1121 synchronized void openAndScroll(final OpenDefinitionsDocument doc, final int line, String className, final boolean shouldHighlight) { 1122 if (doc != null) { 1124 doc.checkIfClassFileInSync(); 1125 1127 Utilities.invokeLater(new Runnable () { public void run() { _notifier.threadLocationUpdated(doc, line, shouldHighlight); } }); 1128 } 1129 else printMessage(" (Source for " + className + " not found.)"); 1130 } 1131 1132 1140 String getPackageDir(String className) { 1141 int lastDotIndex = className.lastIndexOf("."); 1143 if (lastDotIndex == -1) { 1144 return ""; 1146 } 1147 else { 1148 String packageName = className.substring(0, lastDotIndex); 1149 String ps = System.getProperty("file.separator"); 1151 packageName = StringOps.replace(packageName, ".", ps); 1152 return packageName + ps; 1153 } 1154 } 1155 1156 1160 synchronized void printMessage(String message) { 1161 _model.printDebugMessage(message); 1162 } 1163 1164 1170 private boolean hasAnonymous(ReferenceType rt) { 1171 String className = rt.name(); 1172 StringTokenizer st = new StringTokenizer (className, "$"); 1173 while (st.hasMoreElements()) { 1174 String currToken = st.nextToken(); 1175 try { 1176 Integer anonymousNum = Integer.valueOf(currToken); 1177 return true; 1178 } 1179 catch(NumberFormatException nfe) { 1180 } 1182 } 1183 return false; 1184 } 1185 1186 private boolean _getWatchFromInterpreter(DebugWatchData currWatch) { 1187 String currName = currWatch.getName(); 1188 String value = _model.getInteractionsModel().getVariableToString(currName); 1190 if (value != null) { 1191 String type = _model.getInteractionsModel().getVariableClassName(currName); 1192 currWatch.setValue(value); 1193 currWatch.setType(type); 1194 return true; 1195 } 1196 else { 1197 return false; 1198 } 1199 } 1200 1201 1205 private synchronized void _hideWatches() { 1206 for (int i = 0; i < _watches.size(); i++) { 1207 DebugWatchData currWatch = _watches.get(i); 1208 currWatch.hideValueAndType(); 1209 } 1210 } 1211 1212 1213 private synchronized void _updateWatches() throws DebugException { 1214 if (! isReady()) return; 1215 1216 if (_suspendedThreads.size() <= 0) { 1217 for (int i = 0; i < _watches.size(); i++) { 1219 DebugWatchData currWatch = _watches.get(i); 1220 if (!_getWatchFromInterpreter(currWatch)) currWatch.hideValueAndType(); 1221 } 1222 return; 1223 } 1229 1230 try { 1231 StackFrame currFrame; 1232 List <StackFrame> frames; 1233 ThreadReference thread = _suspendedThreads.peek(); 1234 if (thread.frameCount() <= 0 ) { 1235 printMessage("Could not update watch values. The current thread had no stack frames."); 1236 return; 1237 } 1238 frames = thread.frames(); currFrame = frames.get(0); 1240 Location location = currFrame.location(); 1241 1242 ReferenceType rt = location.declaringType(); 1243 ObjectReference obj = currFrame.thisObject(); 1244 1246 String rtName = rt.name(); 1248 int numDollars = 0; 1249 int dollarIndex = rtName.indexOf("$", 0); 1250 while (dollarIndex != -1) { 1251 numDollars++; 1252 dollarIndex = rtName.indexOf("$", dollarIndex+1); 1253 } 1254 1255 for (int i = 0; i < _watches.size(); i++) { 1256 DebugWatchData currWatch = _watches.get(i); 1257 String currName = currWatch.getName(); 1258 if (_getWatchFromInterpreter(currWatch)) { 1259 continue; 1260 } 1261 1275 ReferenceType outerRt = rt; 1325 ObjectReference outer = obj; Field field = outerRt.fieldByName(currName); 1327 1328 if (obj != null) { 1329 1331 int outerIndex = numDollars - 1; 1335 if (hasAnonymous(outerRt)) { 1336 List <Field> fields = outerRt.allFields(); Iterator <Field> iter = fields.iterator(); 1340 while (iter.hasNext()) { 1341 Field f = iter.next(); 1342 String name = f.name(); 1343 if (name.startsWith("this$")) { 1344 int lastIndex = name.lastIndexOf("$"); 1345 outerIndex = Integer.valueOf(name.substring(lastIndex+1, name.length())).intValue(); 1346 break; 1347 } 1348 } 1349 } 1350 Field outerThis = outerRt.fieldByName("this$" + outerIndex); 1351 if (field == null) { 1352 field = outerRt.fieldByName("val$" + currName); 1355 } 1356 1357 while ((field == null) && (outerThis != null)) { 1358 outer = (ObjectReference) outer.getValue(outerThis); 1359 if (outer == null) { 1360 break; 1364 } 1365 outerRt = outer.referenceType(); 1366 field = outerRt.fieldByName(currName); 1367 1368 if (field == null) { 1369 field = outerRt.fieldByName("val$" + currName); 1372 1373 if (field == null) { 1374 outerIndex--; 1376 outerThis = outerRt.fieldByName("this$" + outerIndex); 1377 } 1378 } 1379 } 1380 } 1381 else { 1382 1384 String rtClassName = outerRt.name(); 1389 int index = rtClassName.lastIndexOf("$"); 1390 while ((field == null) && (index != -1)) { 1391 rtClassName = rtClassName.substring(0, index); 1392 List <ReferenceType> l = _vm.classesByName(rtClassName); if (l.isEmpty()) { 1394 break; 1397 } 1398 outerRt = l.get(0); 1399 field = outerRt.fieldByName(currName); 1400 1401 if (field == null) { 1402 index = rtClassName.lastIndexOf("$"); 1404 } 1405 } 1406 } 1407 1408 if ((field != null) && 1412 (field.isStatic() || (outer != null))) { 1413 Value v = (field.isStatic()) ? 1414 outerRt.getValue(field) : 1415 outer.getValue(field); 1416 currWatch.setValue(_getValue(v)); 1417 try { 1418 currWatch.setType(field.type().name()); 1419 } 1420 catch (ClassNotLoadedException cnle) { 1421 List <ReferenceType> classes = _vm.classesByName(field.typeName()); if (!classes.isEmpty()) { 1423 currWatch.setType(classes.get(0).name()); 1424 } 1425 else { 1426 currWatch.setTypeNotLoaded(); 1427 } 1428 } 1429 } 1430 else { 1431 currWatch.setNoValue(); 1432 currWatch.setNoType(); 1433 } 1434 1435 } 1436 } 1437 catch (IncompatibleThreadStateException itse) { 1438 _log("Exception updating watches.", itse); 1439 } 1440 catch (InvalidStackFrameException isfe) { 1441 _log("Exception updating watches.", isfe); 1442 } 1443 catch (VMDisconnectedException vmde) { 1444 _log("Exception updating watches.", vmde); 1445 shutdown(); 1446 } 1447 } 1448 1449 1454 private String _getValue(Value value) throws DebugException { 1455 if (value == null) { 1458 return "null"; 1459 } 1460 1461 if (!(value instanceof ObjectReference)) { 1462 return value.toString(); 1463 } 1464 ObjectReference object = (ObjectReference) value; 1465 ReferenceType rt = object.referenceType(); 1466 ThreadReference thread = _suspendedThreads.peek(); 1467 List <Method> toStrings = rt.methodsByName("toString"); if (toStrings.size() == 0) { 1469 return value.toString(); 1471 } 1472 Method method = toStrings.get(0); 1474 try { 1475 Value stringValue = 1476 object.invokeMethod(thread, method, new LinkedList <Value>(), ObjectReference.INVOKE_SINGLE_THREADED); 1477 if (stringValue == null) return "null"; 1478 return stringValue.toString(); 1479 } 1480 catch (InvalidTypeException ite) { 1481 throw new UnexpectedException(ite); 1483 } 1484 catch (ClassNotLoadedException cnle) { 1485 throw new UnexpectedException(cnle); 1487 } 1488 catch (IncompatibleThreadStateException itse) { 1489 throw new DebugException("Cannot determine value from thread: " + itse); 1490 } 1491 catch (InvocationException ie) { 1492 throw new DebugException("Could not invoke toString: " + ie); 1493 } 1494 } 1495 1496 1497 private Method _getDefineVariableMethod(ReferenceType interpreterRef, Value val) throws DebugException { 1498 List <Method> methods; 1499 String signature_beginning = "(Ljava/lang/String;"; 1500 String signature_end = ")V"; 1501 String signature_mid; 1502 String signature; 1503 1504 if ((val == null) || ( val instanceof ObjectReference )) { 1505 signature_mid = "Ljava/lang/Object;Ljava/lang/Class;"; 1506 } 1507 else if ( val instanceof BooleanValue ) { 1508 signature_mid = "Z"; 1509 } 1510 else if ( val instanceof ByteValue ) { 1511 signature_mid = "B"; 1512 } 1513 else if ( val instanceof CharValue ) { 1514 signature_mid = "C"; 1515 } 1516 else if ( val instanceof DoubleValue ) { 1517 signature_mid = "D"; 1518 } 1519 else if ( val instanceof FloatValue ) { 1520 signature_mid = "F"; 1521 } 1522 else if ( val instanceof IntegerValue ) { 1523 signature_mid = "I"; 1524 } 1525 else if ( val instanceof LongValue ) { 1526 signature_mid = "J"; 1527 } 1528 else if ( val instanceof ShortValue ) { 1529 signature_mid = "S"; 1530 } 1531 else{ 1532 throw new IllegalArgumentException ("Tried to define a variable which is\n" + 1533 "not an Object or a primitive type:\n" + 1534 val); 1535 } 1536 1537 signature = signature_beginning + signature_mid + signature_end; 1538 methods = interpreterRef.methodsByName("defineVariable", signature); if (methods.size() <= 0) { 1540 throw new DebugException("Could not find defineVariable method."); 1541 } 1542 1543 Method tempMethod = methods.get(0); 1545 for (int i = 1; i < methods.size() && tempMethod.isAbstract(); i++) { 1546 tempMethod = methods.get(i); 1547 } 1548 if (tempMethod.isAbstract()) { 1549 throw new DebugException("Could not find concrete defineVariable method."); 1550 } 1551 1552 return tempMethod; 1553 } 1554 1555 1556 private ObjectReference _getDebugInterpreter() throws InvalidTypeException, ClassNotLoadedException, 1557 IncompatibleThreadStateException, InvocationException, DebugException { 1558 1559 ThreadReference threadRef = _suspendedThreads.peek(); 1560 String interpreterName = _getUniqueThreadName(threadRef); 1561 return _getDebugInterpreter(interpreterName, threadRef); 1562 } 1563 1564 1569 private ObjectReference _getDebugInterpreter(String interpreterName, ThreadReference threadRef) throws 1570 InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException, 1571 DebugException { 1572 1573 if (!threadRef.isSuspended()) { 1574 throw new IllegalStateException ("threadRef must be suspended to get a debug interpreter."); 1575 } 1576 1577 Method m = _getMethod(_interpreterJVM.referenceType(), "getJavaInterpreter"); 1579 1580 1585 int tries = 0; 1586 StringReference sr = null; 1587 while (tries < OBJECT_COLLECTED_TRIES) { 1588 try{ 1589 LinkedList <StringReference> args = new LinkedList <StringReference>(); sr = _vm.mirrorOf(interpreterName); 1591 sr.disableCollection(); 1592 args.add(sr); _log.log("Invoking " + m.toString() + " on " + args.toString()); 1594 _log.log("Thread is " + threadRef.toString() + " <suspended = " + threadRef.isSuspended() + ">"); 1595 1596 ObjectReference tmpInterpreter = 1597 (ObjectReference) _interpreterJVM.invokeMethod(threadRef, m, args, ObjectReference.INVOKE_SINGLE_THREADED); 1598 1599 _log.log("Returning..."); 1600 return tmpInterpreter; 1601 } 1602 catch (ObjectCollectedException e) { tries++; } 1603 finally { sr.enableCollection(); } 1604 } 1605 throw new DebugException("The debugInterpreter: " + interpreterName + " could not be obtained from interpreterJVM"); 1606 } 1607 1608 1619 1620 1625 private void _dumpVariablesIntoInterpreterAndSwitch() throws DebugException, AbsentInformationException { 1626 _log.log(this + " invoked dumpVariablesIntoInterpreterAndSwitch"); 1627 try { 1628 ThreadReference suspendedThreadRef = _suspendedThreads.peek(); 1629 StackFrame frame = suspendedThreadRef.frame(0); 1630 Location l = frame.location(); 1631 ReferenceType rt = l.declaringType(); 1632 String className = rt.name(); 1633 1634 String interpreterName = _getUniqueThreadName(suspendedThreadRef); 1636 _model.getInteractionsModel().addDebugInterpreter(interpreterName, className); 1637 ObjectReference debugInterpreter = _getDebugInterpreter(); 1638 _log.log(this + " executing: frame = suspendedThreadRef.frame(0);"); 1639 frame = suspendedThreadRef.frame(0); 1640 1641 List <LocalVariable> vars = frame.visibleVariables(); Iterator <LocalVariable> varsIterator = vars.iterator(); 1643 1644 _log.log(this + " got visibleVariables"); 1645 1646 while(varsIterator.hasNext()) { 1648 LocalVariable localVar = varsIterator.next(); 1649 _log.log(this + " defined local variable: " + localVar); 1650 frame = suspendedThreadRef.frame(0); 1652 Value val = frame.getValue(localVar); 1653 Type type; 1654 if (val != null) { 1655 type = val.type(); 1656 } 1657 else { 1658 try { 1659 type = localVar.type(); 1660 } 1661 catch(ClassNotLoadedException e) { 1662 List <ReferenceType> classes = _vm.classesByName(localVar.typeName()); if (!classes.isEmpty()) { 1664 type = classes.get(0); 1665 } 1666 else { 1667 type = null; 1668 } 1669 } 1670 } 1671 _defineVariable(suspendedThreadRef, debugInterpreter, 1672 localVar.name(), val, type); 1673 } 1674 1675 frame = suspendedThreadRef.frame(0); 1677 1678 Value thisVal = frame.thisObject(); 1680 if (thisVal != null) { 1681 _defineVariable(suspendedThreadRef, debugInterpreter, 1682 "this", thisVal, thisVal.type()); 1683 } 1685 1686 String prompt = _getPromptString(suspendedThreadRef); 1688 _log.log(this + " is setting active interpreter"); 1689 _model.getInteractionsModel().setActiveInterpreter(interpreterName, prompt); 1690 } 1691 catch(InvalidTypeException exc) { 1692 throw new DebugException(exc.toString()); 1693 } 1694 catch(IncompatibleThreadStateException e2) { 1695 throw new DebugException(e2.toString()); 1696 } 1697 catch(ClassNotLoadedException e3) { 1698 throw new DebugException(e3.toString()); 1699 } 1700 catch(InvocationException e4) { 1701 throw new DebugException(e4.toString()); 1702 } 1703 } 1704 1705 1709 private String _getPromptString(ThreadReference threadRef) { 1710 return "[" + threadRef.name() + "] > "; 1711 } 1712 1713 1724 private void _defineVariable(ThreadReference suspendedThreadRef, 1725 ObjectReference debugInterpreter, 1726 String name, Value val, Type type) 1727 throws InvalidTypeException, IncompatibleThreadStateException, 1728 ClassNotLoadedException, InvocationException, DebugException 1729 { 1730 ReferenceType rtDebugInterpreter = debugInterpreter.referenceType(); 1731 Method method2Call = _getDefineVariableMethod(rtDebugInterpreter, val); 1732 1733 1738 int tries = 0; 1739 StringReference sr = null; 1740 while (tries < OBJECT_COLLECTED_TRIES) { 1741 try { 1742 List <Value> args = new LinkedList <Value>(); 1744 1747 sr = _vm.mirrorOf(name); 1748 sr.disableCollection(); 1749 args.add(sr); 1750 args.add(val); 1751 if (type == null) args.add(null); 1752 else if (type instanceof ReferenceType) { 1753 args.add(((ReferenceType)type).classObject()); 1754 } 1755 1756 1757 debugInterpreter.invokeMethod(suspendedThreadRef, method2Call, args, ObjectReference.INVOKE_SINGLE_THREADED); 1758 return; 1759 } 1760 catch (ObjectCollectedException oce) { 1761 tries++; 1762 } 1763 finally { 1764 sr.enableCollection(); 1765 } 1766 } 1767 throw new DebugException("The variable: " + name + 1768 " could not be defined in the debug interpreter"); 1769 } 1770 1771 1772 synchronized void currThreadSuspended() { 1773 try { 1774 try { 1775 _dumpVariablesIntoInterpreterAndSwitch(); 1778 _switchToSuspendedThread(); 1779 } 1780 catch(AbsentInformationException aie) { 1781 printMessage("No debug information available for this class.\nMake sure to compile classes to be debugged with the -g flag."); 1784 _hideWatches(); 1785 _switchToSuspendedThread(false); 1788 } 1789 } 1790 catch(DebugException de) { 1791 throw new UnexpectedException(de); 1792 } 1793 } 1794 1795 1796 private void _switchToSuspendedThread() throws DebugException { _switchToSuspendedThread(true); } 1797 1798 1802 private void _switchToSuspendedThread(boolean updateWatches) throws DebugException { 1803 _log.log(this + " executing _switchToSuspendedThread()"); 1804 _runningThread = null; 1805 if (updateWatches) _updateWatches(); 1806 final ThreadReference currThread = _suspendedThreads.peek(); 1807 _notifier.currThreadSuspended(); 1808 _notifier.currThreadSet(new DebugThreadData(currThread)); 1812 1813 try { 1814 if (currThread.frameCount() > 0) { 1815 scrollToSource(currThread.frame(0).location()); 1816 } 1817 } 1818 catch (IncompatibleThreadStateException itse) { 1819 throw new UnexpectedException(itse); 1820 } 1821 } 1822 1823 1826 private String _getUniqueThreadName(ThreadReference thread) { 1827 return Long.toString(thread.uniqueID()); 1828 } 1829 1830 1833 private Method _getGetVariableMethod(ReferenceType rtInterpreter) { 1834 return _getMethod(rtInterpreter, "getVariable"); 1835 } 1836 1837 1843 private Method _getMethod(ReferenceType rt, String name) { 1844 List <Method> methods = rt.methodsByName(name); Iterator <Method> methodsIterator = methods.iterator(); 1846 1847 while( methodsIterator.hasNext() ) { 1849 Method m = methodsIterator.next(); 1850 if ( !m.isAbstract() ) { 1851 return m; 1852 } 1853 } 1854 1855 throw new NoSuchElementException ("No non-abstract method called " + name + " found in " + rt.name()); 1856 } 1857 1858 1867 private Value _convertToActualType(ThreadReference threadRef, LocalVariable localVar, 1868 Value v) 1869 throws InvalidTypeException, ClassNotLoadedException, 1870 IncompatibleThreadStateException, InvocationException 1871 { 1872 String typeSignature; 1873 try { 1874 typeSignature = localVar.type().signature(); 1875 } 1876 catch (ClassNotLoadedException cnle) { 1877 return v; 1878 } 1879 Method m; 1880 ObjectReference ref = (ObjectReference)v; 1881 ReferenceType rt = ref.referenceType(); 1882 1883 if ( typeSignature.equals("Z") ) { 1884 m = _getMethod(rt, "booleanValue"); 1885 } 1886 else if ( typeSignature.equals("B") ) { 1887 m = _getMethod(rt, "byteValue"); 1888 } 1889 else if ( typeSignature.equals("C") ) { 1890 m = _getMethod(rt, "charValue"); 1891 } 1892 else if ( typeSignature.equals("S") ) { 1893 m = _getMethod(rt, "shortValue"); 1894 } 1895 else if ( typeSignature.equals("I") ) { 1896 m = _getMethod(rt, "intValue"); 1897 } 1898 else if ( typeSignature.equals("J") ) { 1899 m = _getMethod(rt, "longValue"); 1900 } 1901 else if ( typeSignature.equals("F") ) { 1902 m = _getMethod(rt, "floatValue"); 1903 } 1904 else if ( typeSignature.equals("D") ) { 1905 m = _getMethod(rt, "doubleValue"); 1906 } 1907 else{ 1908 return v; 1909 } 1910 1911 return ref.invokeMethod(threadRef, m, new LinkedList <Value>(), ObjectReference.INVOKE_SINGLE_THREADED); 1912 } 1913 1914 1949 private Value _getValueOfLocalVariable(LocalVariable var, ThreadReference thread) 1950 throws InvalidTypeException, ClassNotLoadedException, 1951 IncompatibleThreadStateException, InvocationException, DebugException 1952 { 1953 ObjectReference interpreter = _getDebugInterpreter(_getUniqueThreadName(thread), thread); 1954 ReferenceType rtInterpreter = interpreter.referenceType(); 1955 Method method2Call = _getGetVariableMethod(rtInterpreter); 1956 1957 1962 int tries = 0; 1963 StringReference sr = null; 1964 String varName = var.name(); 1965 while (tries < OBJECT_COLLECTED_TRIES) { 1966 try { 1967 List <Value> args = new LinkedList <Value>(); sr = _vm.mirrorOf(varName); 1969 sr.disableCollection(); 1970 args.add(sr); 1971 Value v = interpreter.invokeMethod(thread, method2Call, args, ObjectReference.INVOKE_SINGLE_THREADED); 1972 if (v != null) v = _convertToActualType(thread, var, v); 1973 1974 return v; 1975 } 1976 catch (ObjectCollectedException oce) { tries++; } 1977 finally { sr.enableCollection(); } 1978 } 1979 throw new DebugException("The value of variable: " + varName + 1980 " could not be obtained from the debug interpreter"); 1981 1982 } 1983 1984 1985 private void _copyBack(ThreadReference threadRef) throws IncompatibleThreadStateException, AbsentInformationException, 1986 InvocationException, DebugException { 1987 _log.log("Getting debug interpreter"); 1988 _log.log("Getting variables"); 1989 StackFrame frame = threadRef.frame(0); 1990 List <LocalVariable> vars = frame.visibleVariables(); Iterator <LocalVariable> varsIterator = vars.iterator(); 1992 1993 while(varsIterator.hasNext()) { 1995 _log.log("Iterating through vars"); 1996 LocalVariable localVar = varsIterator.next(); 1997 1998 try { 1999 Value v = _getValueOfLocalVariable(localVar, threadRef); 2000 frame = threadRef.frame(0); 2001 frame.setValue(localVar, v); 2002 } 2003 catch (ClassNotLoadedException cnle) { 2004 printMessage("Could not update the value of '" + localVar.name() + "' (class not loaded)"); 2005 } 2006 catch (InvalidTypeException ite) { 2007 printMessage("Could not update the value of '" + localVar.name() + "' (invalid type exception)"); 2008 } 2009 } 2010 } 2011 2012 2013 private void _copyVariablesFromInterpreter() throws DebugException { 2014 try { 2015 _log.log("In _copyBack()"); 2018 _copyBack(_runningThread); 2019 _log.log("Out of _copyBack()"); 2020 } 2021 catch(AbsentInformationException e2) { 2022 } 2026 catch(IncompatibleThreadStateException e) { 2027 throw new DebugException(e.toString()); 2028 } 2029 catch(InvocationException e4) { 2030 throw new DebugException(e4.toString()); 2031 } 2032 } 2033 2034 2035 private void _removeAllDebugInterpreters() { 2036 DefaultInteractionsModel interactionsModel = _model.getInteractionsModel(); 2037 String oldInterpreterName; 2038 if (_runningThread != null) { 2039 oldInterpreterName = _getUniqueThreadName(_runningThread); 2040 interactionsModel.removeInterpreter(oldInterpreterName); 2041 } 2042 while (!_suspendedThreads.isEmpty()) { 2043 ThreadReference threadRef = _suspendedThreads.pop(); 2044 oldInterpreterName = _getUniqueThreadName(threadRef); 2045 interactionsModel.removeInterpreter(oldInterpreterName); 2046 } 2047 } 2048 2049 2057 private void _removeCurrentDebugInterpreter(boolean fromStep) { 2058 DefaultInteractionsModel interactionsModel = 2059 _model.getInteractionsModel(); 2060 if (fromStep || _suspendedThreads.isEmpty()) { 2062 interactionsModel.setToDefaultInterpreter(); 2063 } 2064 else { 2065 ThreadReference threadRef = _suspendedThreads.peek(); 2066 _switchToInterpreterForThreadReference(threadRef); 2067 } 2068 String oldInterpreterName = _getUniqueThreadName(_runningThread); 2069 interactionsModel.removeInterpreter(oldInterpreterName); 2070 } 2071 2072 2075 synchronized void currThreadResumed() throws DebugException { 2076 _log.log(this + " is executing currThreadResumed()"); 2077 Utilities.invokeLater(new Runnable () { public void run() { _notifier.currThreadResumed(); } }); 2078 } 2079 2080 2083 private void _switchToInterpreterForThreadReference(ThreadReference threadRef) { 2084 String threadName = _getUniqueThreadName(threadRef); 2085 String prompt = _getPromptString(threadRef); 2086 _model.getInteractionsModel().setActiveInterpreter(threadName, prompt); 2087 } 2088 2089 synchronized void threadStarted() { 2090 Utilities.invokeLater(new Runnable () { public void run() { _notifier.threadStarted(); } }); 2091 } 2092 2093 2096 synchronized void currThreadDied() throws DebugException { 2097 printMessage("The current thread has finished."); 2098 _runningThread = null; 2099 2100 _updateWatches(); 2101 2102 if (_suspendedThreads.size() > 0) { 2103 ThreadReference thread = _suspendedThreads.peek(); 2104 _switchToInterpreterForThreadReference(thread); 2105 2106 try { 2107 if (thread.frameCount() <= 0) { 2108 printMessage("Could not scroll to source for " + thread.name() + ". It has no stackframes."); 2109 } 2110 else scrollToSource(thread.frame(0).location()); 2111 } 2112 catch(IncompatibleThreadStateException e) { throw new UnexpectedException(e); } 2113 2114 _switchToSuspendedThread(); 2117 } 2118 Utilities.invokeLater(new Runnable () { public void run() { _notifier.currThreadDied(); } }); 2119 } 2120 2121 void nonCurrThreadDied() { 2122 Utilities.invokeLater(new Runnable () { public void run() { _notifier.nonCurrThreadDied(); } }); 2123 } 2124 2125 2128 void notifyDebuggerShutdown() { 2129 Utilities.invokeLater(new Runnable () { public void run() { _notifier.debuggerShutdown(); } }); 2130 } 2131 2132 2133 void notifyDebuggerStarted() { 2134 Utilities.invokeLater(new Runnable () { public void run() { _notifier.debuggerStarted(); } }); 2135 } 2136 2137 2138 void notifyStepRequested() { 2139 Utilities.invokeLater(new Runnable () { public void run() { _notifier.stepRequested(); } }); 2140 } 2141 2142 2146 private static class RandomAccessStack extends Stack <ThreadReference> { 2147 2148 public ThreadReference peekAt(int i) { return get(i); } 2149 2150 public ThreadReference remove(long id) throws NoSuchElementException { 2151 synchronized(this) { 2152 for (int i = 0; i < size(); i++) { 2153 if (get(i).uniqueID() == id) { 2154 ThreadReference t = get(i); 2155 remove(i); 2156 return t; 2157 } 2158 } 2159 } 2160 2161 throw new NoSuchElementException ("Thread " + id + " not found in debugger suspended threads stack!"); 2162 } 2163 2164 public synchronized boolean contains(long id) { 2165 for(int i = 0; i < size(); i++) { 2166 if (get(i).uniqueID() == id) return true; 2167 } 2168 return false; 2169 } 2170 2171 public boolean isEmpty() { return empty(); } 2172 } 2173 2174} 2207 | Popular Tags |