1 7 34 35 package com.sun.tools.example.debug.gui; 36 37 import java.io.*; 38 import java.util.*; 39 40 import com.sun.jdi.*; 41 import com.sun.jdi.request.*; 42 43 import com.sun.tools.example.debug.bdi.*; 44 45 public class CommandInterpreter { 46 47 boolean echo; 48 49 Environment env; 50 51 private ContextManager context; 52 private ExecutionManager runtime; 53 private ClassManager classManager; 54 private SourceManager sourceManager; 55 56 private OutputSink out; private String lastCommand = "help"; 58 59 public CommandInterpreter(Environment env) { 60 this(env, true); 61 } 62 63 public CommandInterpreter(Environment env, boolean echo) { 64 this.env = env; 65 this.echo = echo; 66 this.runtime = env.getExecutionManager(); 67 this.context = env.getContextManager(); 68 this.classManager = env.getClassManager(); 69 this.sourceManager = env.getSourceManager(); 70 } 71 72 private ThreadReference[] threads = null; 73 74 81 82 private ThreadReference[] threads() throws NoSessionException { 83 if (threads == null) { 84 ThreadIterator ti = new ThreadIterator(getDefaultThreadGroup()); 85 List tlist = new ArrayList(); 86 while (ti.hasNext()) { 87 tlist.add(ti.nextThread()); 88 } 89 threads = (ThreadReference[])tlist.toArray(new ThreadReference[tlist.size()]); 90 } 91 return threads; 92 } 93 94 private ThreadReference findThread(String idToken) throws NoSessionException { 95 String id; 96 ThreadReference thread = null; 97 if (idToken.startsWith("t@")) { 98 id = idToken.substring(2); 99 } else { 100 id = idToken; 101 } 102 try { 103 ThreadReference[] threads = threads(); 104 long threadID = Long.parseLong(id, 16); 105 for (int i = 0; i < threads.length; i++) { 106 if (threads[i].uniqueID() == threadID) { 107 thread = threads[i]; 108 break; 109 } 110 } 111 if (thread == null) { 112 env.failure("\"" + idToken + "\" is not a valid thread id."); 114 } 115 } catch (NumberFormatException e) { 116 env.error("Thread id \"" + idToken + "\" is ill-formed."); 117 thread = null; 118 } 119 return thread; 120 } 121 122 private ThreadIterator allThreads() throws NoSessionException { 123 threads = null; 124 return new ThreadIterator(runtime.topLevelThreadGroups()); 126 } 127 128 private ThreadIterator currentThreadGroupThreads() throws NoSessionException { 129 threads = null; 130 return new ThreadIterator(getDefaultThreadGroup()); 131 } 132 133 private ThreadGroupIterator allThreadGroups() throws NoSessionException { 134 threads = null; 135 return new ThreadGroupIterator(runtime.topLevelThreadGroups()); 136 } 137 138 private ThreadGroupReference defaultThreadGroup; 139 140 private ThreadGroupReference getDefaultThreadGroup() throws NoSessionException { 141 if (defaultThreadGroup == null) { 142 defaultThreadGroup = runtime.systemThreadGroup(); 143 } 144 return defaultThreadGroup; 145 } 146 147 private void setDefaultThreadGroup(ThreadGroupReference tg) { 148 defaultThreadGroup = tg; 149 } 150 151 154 155 157 private void commandClasses() throws NoSessionException { 158 List list = runtime.allClasses(); 159 OutputSink out = env.getOutputSink(); 160 for (int i = 0 ; i < list.size() ; i++) { 162 ReferenceType refType = (ReferenceType)list.get(i); 163 out.println(refType.name()); 164 } 165 out.show(); 166 } 167 168 169 171 private void commandMethods(StringTokenizer t) throws NoSessionException { 172 if (!t.hasMoreTokens()) { 173 env.error("No class specified."); 174 return; 175 } 176 String idClass = t.nextToken(); 177 ReferenceType cls = findClass(idClass); 178 if (cls != null) { 179 List methods = cls.allMethods(); 180 OutputSink out = env.getOutputSink(); 181 for (int i = 0; i < methods.size(); i++) { 182 Method method = (Method)methods.get(i); 183 out.print(method.declaringType().name() + " " + 184 method.name() + "("); 185 Iterator it = method.argumentTypeNames().iterator(); 186 if (it.hasNext()) { 187 while (true) { 188 out.print((String )it.next()); 189 if (!it.hasNext()) { 190 break; 191 } 192 out.print(", "); 193 } 194 } 195 out.println(")"); 196 } 197 out.show(); 198 } else { 199 env.failure("\"" + idClass + "\" is not a valid id or class name."); 201 } 202 } 203 204 private ReferenceType findClass(String pattern) throws NoSessionException { 205 List results = runtime.findClassesMatchingPattern(pattern); 206 if (results.size() > 0) { 207 return (ReferenceType)results.get(0); 209 } 210 return null; 211 } 212 213 215 private void commandThreads(StringTokenizer t) throws NoSessionException { 216 if (!t.hasMoreTokens()) { 217 OutputSink out = env.getOutputSink(); 218 printThreadGroup(out, getDefaultThreadGroup(), 0); 219 out.show(); 220 return; 221 } 222 String name = t.nextToken(); 223 ThreadGroupReference tg = findThreadGroup(name); 224 if (tg == null) { 225 env.failure(name + " is not a valid threadgroup name."); 226 } else { 227 OutputSink out = env.getOutputSink(); 228 printThreadGroup(out, tg, 0); 229 out.show(); 230 } 231 } 232 233 private ThreadGroupReference findThreadGroup(String name) throws NoSessionException { 234 ThreadGroupIterator tgi = allThreadGroups(); 236 while (tgi.hasNext()) { 237 ThreadGroupReference tg = tgi.nextThreadGroup(); 238 if (tg.name().equals(name)) { 239 return tg; 240 } 241 } 242 return null; 243 } 244 245 private int printThreadGroup(OutputSink out, ThreadGroupReference tg, int iThread) { 246 out.println("Group " + tg.name() + ":"); 247 List tlist = tg.threads(); 248 int maxId = 0; 249 int maxName = 0; 250 for (int i = 0 ; i < tlist.size() ; i++) { 251 ThreadReference thr = (ThreadReference)tlist.get(i); 252 int len = Utils.description(thr).length(); 253 if (len > maxId) 254 maxId = len; 255 String name = thr.name(); 256 int iDot = name.lastIndexOf('.'); 257 if (iDot >= 0 && name.length() > iDot) { 258 name = name.substring(iDot + 1); 259 } 260 if (name.length() > maxName) 261 maxName = name.length(); 262 } 263 String maxNumString = String.valueOf(iThread + tlist.size()); 264 int maxNumDigits = maxNumString.length(); 265 for (int i = 0 ; i < tlist.size() ; i++) { 266 ThreadReference thr = (ThreadReference)tlist.get(i); 267 char buf[] = new char[80]; 268 for (int j = 0; j < 79; j++) { 269 buf[j] = ' '; 270 } 271 buf[79] = '\0'; 272 StringBuffer sbOut = new StringBuffer (); 273 sbOut.append(buf); 274 275 String numString = String.valueOf(iThread + i + 1); 277 sbOut.insert(maxNumDigits - numString.length(), 278 numString); 279 sbOut.insert(maxNumDigits, "."); 280 281 int iBuf = maxNumDigits + 2; 282 sbOut.insert(iBuf, Utils.description(thr)); 283 iBuf += maxId + 1; 284 String name = thr.name(); 285 int iDot = name.lastIndexOf('.'); 286 if (iDot >= 0 && name.length() > iDot) { 287 name = name.substring(iDot + 1); 288 } 289 sbOut.insert(iBuf, name); 290 iBuf += maxName + 1; 291 sbOut.insert(iBuf, Utils.getStatus(thr)); 292 sbOut.setLength(79); 293 out.println(sbOut.toString()); 294 } 295 List tglist = tg.threadGroups(); 296 for (int ig = 0; ig < tglist.size(); ig++) { 297 ThreadGroupReference tg0 = (ThreadGroupReference)tglist.get(ig); 298 if (!tg.equals(tg0)) { iThread += printThreadGroup(out, tg0, iThread + tlist.size()); 300 } 301 } 302 return tlist.size(); 303 } 304 305 307 private void commandThreadGroups() throws NoSessionException { 308 ThreadGroupIterator it = allThreadGroups(); 309 int cnt = 0; 310 OutputSink out = env.getOutputSink(); 311 while (it.hasNext()) { 312 ThreadGroupReference tg = it.nextThreadGroup(); 313 ++cnt; 314 out.println("" + cnt + ". " + Utils.description(tg) + " " + tg.name()); 315 } 316 out.show(); 317 } 318 319 321 private void commandThread(StringTokenizer t) throws NoSessionException { 322 if (!t.hasMoreTokens()) { 323 env.error("Thread number not specified."); 324 return; 325 } 326 ThreadReference thread = findThread(t.nextToken()); 327 if (thread != null) { 328 context.setCurrentThread(thread); 330 } 331 } 332 333 335 private void commandThreadGroup(StringTokenizer t) throws NoSessionException { 336 if (!t.hasMoreTokens()) { 337 env.error("Threadgroup name not specified."); 338 return; 339 } 340 String name = t.nextToken(); 341 ThreadGroupReference tg = findThreadGroup(name); 342 if (tg == null) { 343 env.failure(name + " is not a valid threadgroup name."); 344 } else { 345 setDefaultThreadGroup(tg); 347 } 348 } 349 350 352 private void commandRun(StringTokenizer t) throws NoSessionException { 353 if (doLoad(false, t)) { 354 env.notice("Running ..."); 355 } 356 } 357 358 360 private void commandLoad(StringTokenizer t) throws NoSessionException { 361 if (doLoad(true, t)) {} 362 } 363 364 private boolean doLoad(boolean suspended, 365 StringTokenizer t) throws NoSessionException { 366 367 String clname; 368 369 if (!t.hasMoreTokens()) { 370 clname = context.getMainClassName(); 371 if (!clname.equals("")) { 372 try { 374 String vmArgs = context.getVmArguments(); 375 runtime.run(suspended, 376 vmArgs, 377 clname, 378 context.getProgramArguments()); 379 return true; 380 } catch (VMLaunchFailureException e) { 381 env.failure("Attempt to launch main class \"" + clname + "\" failed."); 382 } 383 } else { 384 env.failure("No main class specifed and no current default defined."); 385 } 386 } else { 387 clname = t.nextToken(); 388 StringBuffer sbuf = new StringBuffer (); 389 while (t.hasMoreTokens()) { 391 String tok = t.nextToken(); 392 sbuf.append(tok); 393 if (t.hasMoreTokens()) { 394 sbuf.append(' '); 395 } 396 } 397 String args = sbuf.toString(); 398 try { 399 String vmArgs = context.getVmArguments(); 400 runtime.run(suspended, vmArgs, clname, args); 401 context.setMainClassName(clname); 402 context.setProgramArguments(args); 404 return true; 405 } catch (VMLaunchFailureException e) { 406 env.failure("Attempt to launch main class \"" + clname + "\" failed."); 407 } 408 } 409 return false; 410 } 411 412 414 private void commandConnect(StringTokenizer t) { 415 try { 416 LaunchTool.queryAndLaunchVM(runtime); 417 } catch (VMLaunchFailureException e) { 418 env.failure("Attempt to connect failed."); 419 } 420 } 421 422 424 private void commandAttach(StringTokenizer t) { 425 String portName; 426 if (!t.hasMoreTokens()) { 427 portName = context.getRemotePort(); 428 if (!portName.equals("")) { 429 try { 430 runtime.attach(portName); 431 } catch (VMLaunchFailureException e) { 432 env.failure("Attempt to attach to port \"" + portName + "\" failed."); 433 } 434 } else { 435 env.failure("No port specifed and no current default defined."); 436 } 437 } else { 438 portName = t.nextToken(); 439 try { 440 runtime.attach(portName); 441 } catch (VMLaunchFailureException e) { 442 env.failure("Attempt to attach to port \"" + portName + "\" failed."); 443 } 444 context.setRemotePort(portName); 445 } 446 } 447 448 450 private void commandDetach(StringTokenizer t) throws NoSessionException { 451 runtime.detach(); 452 } 453 454 456 private void commandInterrupt(StringTokenizer t) throws NoSessionException { 457 runtime.interrupt(); 458 } 459 460 462 private void commandSuspend(StringTokenizer t) throws NoSessionException { 463 if (!t.hasMoreTokens()) { 464 ThreadIterator ti = currentThreadGroupThreads(); 468 while (ti.hasNext()) { 469 ti.nextThread().suspend(); 471 } 472 env.notice("All (non-system) threads suspended."); 473 } else { 474 while (t.hasMoreTokens()) { 475 ThreadReference thread = findThread(t.nextToken()); 476 if (thread != null) { 477 runtime.suspendThread(thread); 479 } 480 } 481 } 482 } 483 484 486 private void commandResume(StringTokenizer t) throws NoSessionException { 487 if (!t.hasMoreTokens()) { 488 ThreadIterator ti = currentThreadGroupThreads(); 492 while (ti.hasNext()) { 493 ti.nextThread().resume(); 495 } 496 env.notice("All threads resumed."); 497 } else { 498 while (t.hasMoreTokens()) { 499 ThreadReference thread = findThread(t.nextToken()); 500 if (thread != null) { 501 runtime.resumeThread(thread); 503 } 504 } 505 } 506 } 507 508 510 private void commandCont() throws NoSessionException { 511 try { 512 runtime.go(); 513 } catch (VMNotInterruptedException e) { 514 env.notice("Target VM is already running."); 516 } 517 } 518 519 521 private void commandStep(StringTokenizer t) throws NoSessionException{ 522 ThreadReference current = context.getCurrentThread(); 523 if (current == null) { 524 env.failure("No current thread."); 525 return; 526 } 527 try { 528 if (t.hasMoreTokens() && 529 t.nextToken().toLowerCase().equals("up")) { 530 runtime.stepOut(current); 531 } else { 532 runtime.stepIntoLine(current); 533 } 534 } catch (AbsentInformationException e) { 535 env.failure("No linenumber information available -- " + 536 "Try \"stepi\" to step by instructions."); 537 } 538 } 539 540 542 private void commandStepi() throws NoSessionException { 543 ThreadReference current = context.getCurrentThread(); 544 if (current == null) { 545 env.failure("No current thread."); 546 return; 547 } 548 runtime.stepIntoInstruction(current); 549 } 550 551 553 private void commandNext() throws NoSessionException { 554 ThreadReference current = context.getCurrentThread(); 555 if (current == null) { 556 env.failure("No current thread."); 557 return; 558 } 559 try { 560 runtime.stepOverLine(current); 561 } catch (AbsentInformationException e) { 562 env.failure("No linenumber information available -- " + 563 "Try \"nexti\" to step by instructions."); 564 } 565 } 566 567 569 private void commandNexti() throws NoSessionException { 570 ThreadReference current = context.getCurrentThread(); 571 if (current == null) { 572 env.failure("No current thread."); 573 return; 574 } 575 runtime.stepOverInstruction(current); 576 } 577 578 580 private void commandKill(StringTokenizer t) throws NoSessionException { 581 if (!t.hasMoreTokens()) { 584 env.error("Usage: kill <threadgroup name> or <thread id>"); 585 return; 586 } 587 while (t.hasMoreTokens()) { 588 String idToken = t.nextToken(); 589 ThreadReference thread = findThread(idToken); 590 if (thread != null) { 591 runtime.stopThread(thread); 592 env.notice("Thread " + thread.name() + " killed."); 593 return; 594 } else { 595 596 ThreadGroupIterator itg = allThreadGroups(); 599 while (itg.hasNext()) { 600 ThreadGroupReference tg = itg.nextThreadGroup(); 601 if (tg.name().equals(idToken)) { 602 ThreadIterator it = new ThreadIterator(tg); 603 while (it.hasNext()) { 604 runtime.stopThread(it.nextThread()); 605 } 606 env.notice("Threadgroup " + tg.name() + "killed."); 607 return; 608 } 609 } 610 env.failure("\"" + idToken + 611 "\" is not a valid threadgroup or id."); 612 } 613 } 614 } 615 616 617 623 624 626 628 int readCount(StringTokenizer t) { 629 int cnt = 1; 630 if (t.hasMoreTokens()) { 631 String idToken = t.nextToken(); 632 int n; 633 try { 634 cnt = Integer.valueOf(idToken).intValue(); 635 } catch (NumberFormatException e) { 636 cnt = -1; 637 } 638 } 639 return cnt; 640 } 641 642 void commandUp(StringTokenizer t) throws NoSessionException { 643 ThreadReference current = context.getCurrentThread(); 644 if (current == null) { 645 env.failure("No current thread."); 646 return; 647 } 648 int nLevels = readCount(t); 649 if (nLevels <= 0) { 650 env.error("usage: up [n frames]"); 651 return; 652 } 653 try { 654 int delta = context.moveCurrentFrameIndex(current, -nLevels); 655 if (delta == 0) { 656 env.notice("Already at top of stack."); 657 } else if (-delta < nLevels) { 658 env.notice("Moved up " + delta + " frames to top of stack."); 659 } 660 } catch (VMNotInterruptedException e) { 661 env.failure("Target VM must be in interrupted state."); 662 } 663 } 664 665 private void commandDown(StringTokenizer t) throws NoSessionException { 666 ThreadReference current = context.getCurrentThread(); 667 if (current == null) { 668 env.failure("No current thread."); 669 return; 670 } 671 int nLevels = readCount(t); 672 if (nLevels <= 0) { 673 env.error("usage: down [n frames]"); 674 return; 675 } 676 try { 677 int delta = context.moveCurrentFrameIndex(current, nLevels); 678 if (delta == 0) { 679 env.notice("Already at bottom of stack."); 680 } else if (delta < nLevels) { 681 env.notice("Moved down " + delta + " frames to bottom of stack."); 682 } 683 } catch (VMNotInterruptedException e) { 684 env.failure("Target VM must be in interrupted state."); 685 } 686 } 687 688 690 private void commandFrame(StringTokenizer t) throws NoSessionException { 691 ThreadReference current = context.getCurrentThread(); 692 if (current == null) { 693 env.failure("No current thread."); 694 return; 695 } 696 if (!t.hasMoreTokens()) { 697 env.error("usage: frame <frame-index>"); 698 return; 699 } 700 String idToken = t.nextToken(); 701 int n; 702 try { 703 n = Integer.valueOf(idToken).intValue(); 704 } catch (NumberFormatException e) { 705 n = 0; 706 } 707 if (n <= 0) { 708 env.error("use positive frame index"); 709 return; 710 } 711 try { 712 int delta = context.setCurrentFrameIndex(current, n); 713 if (delta == 0) { 714 env.notice("Frame unchanged."); 715 } else if (delta < 0) { 716 env.notice("Moved up " + -delta + " frames."); 717 } else { 718 env.notice("Moved down " + delta + " frames."); 719 } 720 } catch (VMNotInterruptedException e) { 721 env.failure("Target VM must be in interrupted state."); 722 } 723 } 724 725 727 731 private void commandWhere(StringTokenizer t, boolean showPC) 732 throws NoSessionException { 733 ThreadReference current = context.getCurrentThread(); 734 if (!t.hasMoreTokens()) { 735 if (current == null) { 736 env.error("No thread specified."); 737 return; 738 } 739 dumpStack(current, showPC); 740 } else { 741 String token = t.nextToken(); 742 if (token.toLowerCase().equals("all")) { 743 ThreadIterator it = allThreads(); 744 while (it.hasNext()) { 745 ThreadReference thread = (ThreadReference)it.next(); 746 out.println(thread.name() + ": "); 747 dumpStack(thread, showPC); 748 } 749 } else { 750 ThreadReference thread = findThread(t.nextToken()); 751 if (thread != null) { 754 context.setCurrentThread(thread); 755 } 756 dumpStack(thread, showPC); 757 } 758 } 759 } 760 761 private void dumpStack(ThreadReference thread, boolean showPC) { 762 List stack = null; 768 try { 769 stack = thread.frames(); 770 } catch (IncompatibleThreadStateException e) { 771 env.failure("Thread is not suspended."); 772 } 773 int frameIndex = 0; 777 if (stack == null) { 779 env.failure("Thread is not running (no stack)."); 780 } else { 781 OutputSink out = env.getOutputSink(); 782 int nFrames = stack.size(); 783 for (int i = frameIndex; i < nFrames; i++) { 784 StackFrame frame = (StackFrame)stack.get(i); 785 Location loc = frame.location(); 786 Method meth = loc.method(); 787 out.print(" [" + (i + 1) + "] "); 788 out.print(meth.declaringType().name()); 789 out.print('.'); 790 out.print(meth.name()); 791 out.print(" ("); 792 if (meth instanceof Method && ((Method)meth).isNative()) { 793 out.print("native method"); 794 } else if (loc.lineNumber() != -1) { 795 try { 796 out.print(loc.sourceName()); 797 } catch (AbsentInformationException e) { 798 out.print("<unknown>"); 799 } 800 out.print(':'); 801 out.print(loc.lineNumber()); 802 } 803 out.print(')'); 804 if (showPC) { 805 long pc = loc.codeIndex(); 806 if (pc != -1) { 807 out.print(", pc = " + pc); 808 } 809 } 810 out.println(); 811 } 812 out.show(); 813 } 814 } 815 816 private void listEventRequests() throws NoSessionException { 817 Iterator iter = runtime.eventRequestSpecs().iterator(); 819 if (!iter.hasNext()) { 820 env.notice("No breakpoints/watchpoints/exceptions set."); 821 } else { 822 OutputSink out = env.getOutputSink(); 823 out.println("Current breakpoints/watchpoints/exceptions set:"); 824 while (iter.hasNext()) { 825 EventRequestSpec bp = (EventRequestSpec)iter.next(); 826 out.println("\t" + bp); 827 } 828 out.show(); 829 } 830 } 831 832 private BreakpointSpec parseBreakpointSpec(String bptSpec) { 833 StringTokenizer t = new StringTokenizer(bptSpec); 834 BreakpointSpec bpSpec = null; 835 String token = t.nextToken("@:( \t\n\r"); 837 String rest; 840 try { 841 rest = t.nextToken("").trim(); 842 } catch (NoSuchElementException e) { 843 rest = null; 844 } 845 if ((rest != null) && rest.startsWith("@")) { 846 t = new StringTokenizer(rest.substring(1)); 847 String sourceName = token; 848 String lineToken = t.nextToken(); 849 int lineNumber = Integer.valueOf(lineToken).intValue(); 850 if (t.hasMoreTokens()) { 851 return null; 852 } 853 bpSpec = runtime.createSourceLineBreakpoint(sourceName, 854 lineNumber); 855 } else if ((rest != null) && rest.startsWith(":")) { 856 t = new StringTokenizer(rest.substring(1)); 857 String classId = token; 858 String lineToken = t.nextToken(); 859 int lineNumber = Integer.valueOf(lineToken).intValue(); 860 if (t.hasMoreTokens()) { 861 return null; 862 } 863 bpSpec = runtime.createClassLineBreakpoint(classId, lineNumber); 864 } else { 865 int idot = token.lastIndexOf("."); 867 if ( (idot <= 0) || 868 (idot >= token.length() - 1) ) { 869 return null; 870 } 871 String methodName = token.substring(idot + 1); 872 String classId = token.substring(0, idot); 873 List argumentList = null; 874 if (rest != null) { 875 if (!rest.startsWith("(") || !rest.endsWith(")")) { 876 return null; 880 } 881 rest = rest.substring(1, rest.length() - 1); 884 argumentList = new ArrayList(); 885 t = new StringTokenizer(rest, ","); 886 while (t.hasMoreTokens()) { 887 argumentList.add(t.nextToken()); 888 } 889 } 890 bpSpec = runtime.createMethodBreakpoint(classId, 891 methodName, 892 argumentList); 893 } 894 return bpSpec; 899 } 900 901 private void commandStop(StringTokenizer t) throws NoSessionException { 902 Location bploc; 903 String token; 904 905 if (!t.hasMoreTokens()) { 906 listEventRequests(); 907 } else { 908 token = t.nextToken(); 909 if (token.equals("at") || token.equals("in")) { 912 if (t.hasMoreTokens()) { 913 token = t.nextToken(); 914 } else { 915 env.error("Missing breakpoint specification."); 916 return; 917 } 918 } 919 BreakpointSpec bpSpec = parseBreakpointSpec(token); 920 if (bpSpec != null) { 921 runtime.install(bpSpec); 923 } else { 924 env.error("Ill-formed breakpoint specification."); 925 } 926 } 927 } 928 929 private void commandClear(StringTokenizer t) throws NoSessionException { 930 if (!t.hasMoreTokens()) { 931 listEventRequests(); 933 return; 934 } 935 BreakpointSpec bpSpec = parseBreakpointSpec(t.nextToken()); 937 if (bpSpec != null) { 938 Iterator iter = runtime.eventRequestSpecs().iterator(); 939 if (!iter.hasNext()) { 940 env.notice("No breakpoints set."); 941 } else { 942 List toDelete = new ArrayList(); 943 while (iter.hasNext()) { 944 BreakpointSpec spec = (BreakpointSpec)iter.next(); 945 if (spec.equals(bpSpec)) { 946 toDelete.add(spec); 947 } 948 } 949 if (toDelete.size() <= 1) { 951 env.notice("No matching breakpoint set."); 952 } 953 for (Iterator it = toDelete.iterator(); it.hasNext();) { 954 BreakpointSpec spec = (BreakpointSpec)it.next(); 955 runtime.delete(spec); 956 } 957 } 958 } else { 959 env.error("Ill-formed breakpoint specification."); 960 } 961 } 962 963 965 private void commandList(StringTokenizer t) throws NoSessionException { 966 ThreadReference current = context.getCurrentThread(); 967 if (current == null) { 968 env.error("No thread specified."); 969 return; 970 } 971 Location loc; 972 try { 973 StackFrame frame = context.getCurrentFrame(current); 974 if (frame == null) { 975 env.failure("Thread has not yet begun execution."); 976 return; 977 } 978 loc = frame.location(); 979 } catch (VMNotInterruptedException e) { 980 env.failure("Target VM must be in interrupted state."); 981 return; 982 } 983 SourceModel source = sourceManager.sourceForLocation(loc); 984 if (source == null) { 985 if (loc.method().isNative()) { 986 env.failure("Current method is native."); 987 return; 988 } 989 env.failure("No source available for " + Utils.locationString(loc) + "."); 990 return; 991 } 992 ReferenceType refType = loc.declaringType(); 993 int lineno = loc.lineNumber(); 994 if (t.hasMoreTokens()) { 995 String id = t.nextToken(); 996 try { 998 lineno = Integer.valueOf(id).intValue(); 999 } catch (NumberFormatException nfe) { 1000 List meths = refType.methodsByName(id); 1002 if (meths == null || meths.size() == 0) { 1003 env.failure(id + 1004 " is not a valid line number or " + 1005 "method name for class " + 1006 refType.name()); 1007 return; 1008 } else if (meths.size() > 1) { 1009 env.failure(id + 1010 " is an ambiguous method name in" + 1011 refType.name()); 1012 return; 1013 } 1014 loc = ((Method)meths.get(0)).location(); 1015 lineno = loc.lineNumber(); 1016 } 1017 } 1018 int startLine = (lineno > 4) ? lineno - 4 : 1; 1019 int endLine = startLine + 9; 1020 String sourceLine = source.sourceLine(lineno); 1021 if (sourceLine == null) { 1022 env.failure("" + 1023 lineno + 1024 " is an invalid line number for " + 1025 refType.name()); 1026 } else { 1027 OutputSink out = env.getOutputSink(); 1028 for (int i = startLine; i <= endLine; i++) { 1029 sourceLine = source.sourceLine(i); 1030 if (sourceLine == null) { 1031 break; 1032 } 1033 out.print(i); 1034 out.print("\t"); 1035 if (i == lineno) { 1036 out.print("=> "); 1037 } else { 1038 out.print(" "); 1039 } 1040 out.println(sourceLine); 1041 } 1042 out.show(); 1043 } 1044 } 1045 1046 1049 private void commandUse(StringTokenizer t) { 1050 if (!t.hasMoreTokens()) { 1051 out.println(sourceManager.getSourcePath().asString()); 1052 } else { 1053 sourceManager.setSourcePath(new SearchPath(t.nextToken())); 1056 } 1057 } 1058 1059 1062 private void commandSourcepath(StringTokenizer t) { 1063 if (!t.hasMoreTokens()) { 1064 out.println(sourceManager.getSourcePath().asString()); 1065 } else { 1066 sourceManager.setSourcePath(new SearchPath(t.nextToken())); 1069 } 1070 } 1071 1072 1075 private void commandClasspath(StringTokenizer t) { 1076 if (!t.hasMoreTokens()) { 1077 out.println(classManager.getClassPath().asString()); 1078 } else { 1079 classManager.setClassPath(new SearchPath(t.nextToken())); 1082 } 1083 } 1084 1085 1088 private void commandView(StringTokenizer t) throws NoSessionException { 1089 if (!t.hasMoreTokens()) { 1090 env.error("Argument required"); 1091 } else { 1092 String name = t.nextToken(); 1093 if (name.endsWith(".java") || 1094 name.indexOf(File.separatorChar) >= 0) { 1095 env.viewSource(name); 1096 } else { 1097 1106 String fileName = name.replace('.', File.separatorChar) + ".java"; 1107 env.viewSource(fileName); 1108 } 1109 } 1110 } 1111 1112 1115 private void commandLocals() throws NoSessionException { 1116 ThreadReference current = context.getCurrentThread(); 1117 if (current == null) { 1118 env.failure("No default thread specified: " + 1119 "use the \"thread\" command first."); 1120 return; 1121 } 1122 StackFrame frame; 1123 try { 1124 frame = context.getCurrentFrame(current); 1125 if (frame == null) { 1126 env.failure("Thread has not yet created any stack frames."); 1127 return; 1128 } 1129 } catch (VMNotInterruptedException e) { 1130 env.failure("Target VM must be in interrupted state."); 1131 return; 1132 } 1133 1134 List vars; 1135 try { 1136 vars = frame.visibleVariables(); 1137 if (vars == null || vars.size() == 0) { 1138 env.failure("No local variables"); 1139 return; 1140 } 1141 } catch (AbsentInformationException e) { 1142 env.failure("Local variable information not available." + 1143 " Compile with -g to generate variable information"); 1144 return; 1145 } 1146 1147 OutputSink out = env.getOutputSink(); 1148 out.println("Method arguments:"); 1149 for (Iterator it = vars.iterator(); it.hasNext(); ) { 1150 LocalVariable var = (LocalVariable)it.next(); 1151 if (var.isArgument()) { 1152 printVar(out, var, frame); 1153 } 1154 } 1155 out.println("Local variables:"); 1156 for (Iterator it = vars.iterator(); it.hasNext(); ) { 1157 LocalVariable var = (LocalVariable)it.next(); 1158 if (!var.isArgument()) { 1159 printVar(out, var, frame); 1160 } 1161 } 1162 out.show(); 1163 return; 1164 } 1165 1166 1170 private void commandMonitor(StringTokenizer t) throws NoSessionException { 1171 if (!t.hasMoreTokens()) { 1172 env.error("Argument required"); 1173 } else { 1174 env.getMonitorListModel().add(t.nextToken("")); 1175 } 1176 } 1177 1178 1182 private void commandUnmonitor(StringTokenizer t) throws NoSessionException { 1183 if (!t.hasMoreTokens()) { 1184 env.error("Argument required"); 1185 } else { 1186 env.getMonitorListModel().remove(t.nextToken("")); 1187 } 1188 } 1189 1190 1192 private void printVar(OutputSink out, LocalVariable var, StackFrame frame) { 1193 out.print(" " + var.name()); 1194 if (var.isVisible(frame)) { 1195 Value val = frame.getValue(var); 1196 out.println(" = " + val.toString()); 1197 } else { 1198 out.println(" is not in scope"); 1199 } 1200 } 1201 1202 1205 private void commandPrint(StringTokenizer t, boolean dumpObject) throws NoSessionException { 1206 if (!t.hasMoreTokens()) { 1207 env.error("No expression specified."); 1209 return; 1210 } 1211 ThreadReference current = context.getCurrentThread(); 1212 if (current == null) { 1213 env.failure("No default thread specified: " + 1214 "use the \"thread\" command first."); 1215 return; 1216 } 1217 StackFrame frame; 1218 try { 1219 frame = context.getCurrentFrame(current); 1220 if (frame == null) { 1221 env.failure("Thread has not yet created any stack frames."); 1222 return; 1223 } 1224 } catch (VMNotInterruptedException e) { 1225 env.failure("Target VM must be in interrupted state."); 1226 return; 1227 } 1228 while (t.hasMoreTokens()) { 1229 String expr = t.nextToken(""); 1230 Value val = null; 1231 try { 1232 val = runtime.evaluate(frame, expr); 1233 } catch(Exception e) { 1234 env.error("Exception: " + e); 1235 } 1237 if (val == null) { 1238 return; } 1240 OutputSink out = env.getOutputSink(); 1241 if (dumpObject && (val instanceof ObjectReference) && 1242 !(val instanceof StringReference)) { 1243 ObjectReference obj = (ObjectReference)val; 1244 ReferenceType refType = obj.referenceType(); 1245 out.println(expr + " = " + val.toString() + " {"); 1246 dump(out, obj, refType, refType); 1247 out.println("}"); 1248 } else { 1249 out.println(expr + " = " + val.toString()); 1250 } 1251 out.show(); 1252 } 1253 } 1254 1255 private void dump(OutputSink out, 1256 ObjectReference obj, ReferenceType refType, 1257 ReferenceType refTypeBase) { 1258 for (Iterator it = refType.fields().iterator(); it.hasNext(); ) { 1259 Field field = (Field)it.next(); 1260 out.print(" "); 1261 if (!refType.equals(refTypeBase)) { 1262 out.print(refType.name() + "."); 1263 } 1264 out.print(field.name() + ": "); 1265 Object o = obj.getValue(field); 1266 out.println((o == null) ? "null" : o.toString()); } 1268 if (refType instanceof ClassType) { 1269 ClassType sup = ((ClassType)refType).superclass(); 1270 if (sup != null) { 1271 dump(out, obj, sup, refTypeBase); 1272 } 1273 } else if (refType instanceof InterfaceType) { 1274 List sups = ((InterfaceType)refType).superinterfaces(); 1275 for (Iterator it = sups.iterator(); it.hasNext(); ) { 1276 dump(out, obj, (ReferenceType)it.next(), refTypeBase); 1277 } 1278 } 1279 } 1280 1281 1284 1285 private void help() { 1286 out.println("** command list **"); 1287 out.println("threads [threadgroup] -- list threads"); 1288 out.println("thread <thread id> -- set default thread"); 1289 out.println("suspend [thread id(s)] -- suspend threads (default: all)"); 1290 out.println("resume [thread id(s)] -- resume threads (default: all)"); 1291 out.println("where [thread id] | all -- dump a thread's stack"); 1292 out.println("wherei [thread id] | all -- dump a thread's stack, with pc info"); 1293 out.println("threadgroups -- list threadgroups"); 1294 out.println("threadgroup <name> -- set current threadgroup\n"); 1295 out.println("dump <expression> -- print all object information\n"); 1297 out.println("locals -- print all local variables in current stack frame\n"); 1299 out.println("classes -- list currently known classes"); 1300 out.println("methods <class id> -- list a class's methods\n"); 1301 out.println("stop [in] <class id>.<method>[(argument_type,...)] -- set a breakpoint in a method"); 1302 out.println("stop [at] <class id>:<line> -- set a breakpoint at a line"); 1303 out.println("up [n frames] -- move up a thread's stack"); 1304 out.println("down [n frames] -- move down a thread's stack"); 1305 out.println("frame <frame-id> -- to a frame"); 1306 out.println("clear <class id>.<method>[(argument_type,...)] -- clear a breakpoint in a method"); 1307 out.println("clear <class id>:<line> -- clear a breakpoint at a line"); 1308 out.println("clear -- list breakpoints"); 1309 out.println("step -- execute current line"); 1310 out.println("step up -- execute until the current method returns to its caller"); 1311 out.println("stepi -- execute current instruction"); 1312 out.println("next -- step one line (step OVER calls)"); 1313 out.println("nexti -- step one instruction (step OVER calls)"); 1314 out.println("cont -- continue execution from breakpoint\n"); 1315 out.println("view classname|filename -- display source file"); 1318 out.println("list [line number|method] -- print source code context at line or method"); 1319 out.println("use <source file path> -- display or change the source path\n"); 1320 out.println("sourcepath <source file path> -- display or change the source path\n"); 1322 out.println("classpath <class file path> -- display or change the class path\n"); 1324 out.println("monitor <expression> -- evaluate an expression each time the program stops\n"); 1325 out.println("unmonitor <monitor#> -- delete a monitor\n"); 1326 out.println("read <filename> -- read and execute a command file\n"); 1327 out.println("run <class> [args] -- start execution of a Java class"); 1330 out.println("run -- re-execute last class run"); 1331 out.println("load <class> [args] -- start execution of a Java class, initially suspended"); 1332 out.println("load -- re-execute last class run, initially suspended"); 1333 out.println("attach <portname> -- debug existing process\n"); 1334 out.println("detach -- detach from debuggee process\n"); 1335 out.println("kill <thread(group)> -- kill a thread or threadgroup\n"); 1336 out.println("!! -- repeat last command"); 1337 out.println("help (or ?) -- list commands"); 1338 out.println("exit (or quit) -- exit debugger"); 1339 } 1340 1341 1344 1345 public void executeCommand(String command) { 1346 out = env.getOutputSink(); 1348 if (echo) { 1349 out.println(">>> " + command); 1350 } 1351 StringTokenizer t = new StringTokenizer(command); 1352 try { 1353 String cmd; 1354 if (t.hasMoreTokens()) { 1355 cmd = t.nextToken().toLowerCase(); 1356 lastCommand = cmd; 1357 } else { 1358 cmd = lastCommand; 1359 } 1360 if (cmd.equals("print")) { 1361 commandPrint(t, false); 1362 } else if (cmd.equals("eval")) { 1363 commandPrint(t, false); 1364 } else if (cmd.equals("dump")) { 1365 commandPrint(t, true); 1366 } else if (cmd.equals("locals")) { 1367 commandLocals(); 1368 } else if (cmd.equals("classes")) { 1369 commandClasses(); 1370 } else if (cmd.equals("methods")) { 1371 commandMethods(t); 1372 } else if (cmd.equals("threads")) { 1373 commandThreads(t); 1374 } else if (cmd.equals("thread")) { 1375 commandThread(t); 1376 } else if (cmd.equals("suspend")) { 1377 commandSuspend(t); 1378 } else if (cmd.equals("resume")) { 1379 commandResume(t); 1380 } else if (cmd.equals("cont")) { 1381 commandCont(); 1382 } else if (cmd.equals("threadgroups")) { 1383 commandThreadGroups(); 1384 } else if (cmd.equals("threadgroup")) { 1385 commandThreadGroup(t); 1386 } else if (cmd.equals("run")) { 1387 commandRun(t); 1388 } else if (cmd.equals("load")) { 1389 commandLoad(t); 1390 } else if (cmd.equals("connect")) { 1391 commandConnect(t); 1392 } else if (cmd.equals("attach")) { 1393 commandAttach(t); 1394 } else if (cmd.equals("detach")) { 1395 commandDetach(t); 1396 } else if (cmd.equals("interrupt")) { 1397 commandInterrupt(t); 1398 } else if (cmd.equals("step")) { 1405 commandStep(t); 1406 } else if (cmd.equals("stepi")) { 1407 commandStepi(); 1408 } else if (cmd.equals("next")) { 1409 commandNext(); 1410 } else if (cmd.equals("nexti")) { 1411 commandNexti(); 1412 } else if (cmd.equals("kill")) { 1413 commandKill(t); 1414 } else if (cmd.equals("where")) { 1415 commandWhere(t, false); 1416 } else if (cmd.equals("wherei")) { 1417 commandWhere(t, true); 1418 } else if (cmd.equals("up")) { 1419 commandUp(t); 1420 } else if (cmd.equals("down")) { 1421 commandDown(t); 1422 } else if (cmd.equals("frame")) { 1423 commandFrame(t); 1424 } else if (cmd.equals("stop")) { 1425 commandStop(t); 1426 } else if (cmd.equals("clear")) { 1427 commandClear(t); 1428 } else if (cmd.equals("list")) { 1429 commandList(t); 1430 } else if (cmd.equals("use")) { 1431 commandUse(t); 1432 } else if (cmd.equals("sourcepath")) { 1433 commandSourcepath(t); 1434 } else if (cmd.equals("classpath")) { 1435 commandClasspath(t); 1436 } else if (cmd.equals("monitor")) { 1437 commandMonitor(t); 1438 } else if (cmd.equals("unmonitor")) { 1439 commandUnmonitor(t); 1440 } else if (cmd.equals("view")) { 1441 commandView(t); 1442 } else if (cmd.equals("help") || cmd.equals("?")) { 1445 help(); 1446 } else if (cmd.equals("quit") || cmd.equals("exit")) { 1447 try { 1448 runtime.detach(); 1449 } catch (NoSessionException e) { 1450 } 1452 env.terminate(); 1453 } else { 1454 if (t.hasMoreTokens()) { 1456 try { 1457 int repeat = Integer.parseInt(cmd); 1458 String subcom = t.nextToken(""); 1459 while (repeat-- > 0) { 1460 executeCommand(subcom); 1461 } 1462 return; 1463 } catch (NumberFormatException exc) { 1464 } 1465 } 1466 out.println("huh? Try help..."); 1467 out.flush(); 1468 } 1469 } catch (NoSessionException e) { 1470 out.println("There is no currently attached VM session."); 1471 out.flush(); 1472 } catch (Exception e) { 1473 out.println("Internal exception: " + e.toString()); 1474 out.flush(); 1475 System.out.println("JDB internal exception: " + e.toString()); 1476 e.printStackTrace(); 1477 } 1478 out.show(); 1479 } 1480} 1481 1482 1483 1484 1485 1486 1487 1488 | Popular Tags |