private void commandFrame(StringTokenizer t) throws NoSessionException { ThreadReference current = context.getCurrentThread(); if (current == null) { env.failure("No current thread."); return; } if (!t.hasMoreTokens()) { env.error("usage: frame <frame-index>"); return; } String idToken = t.nextToken(); int n; try { n = Integer.valueOf(idToken).intValue(); } catch (NumberFormatException e) { n = 0; } if (n <= 0) { env.error("use positive frame index"); return; } try { int delta = context.setCurrentFrameIndex(current, n); if (delta == 0) { env.notice("Frame unchanged."); } else if (delta < 0) { env.notice("Moved up " + -delta + " frames."); } else { env.notice("Moved down " + delta + " frames."); } } catch (VMNotInterruptedException e) { env.failure("Target VM must be in interrupted state."); } }
private void dumpStack(ThreadReference thread, boolean showPC) { // ### Check for these. // env.failure("Thread no longer exists."); // env.failure("Target VM must be in interrupted state."); // env.failure("Current thread isn't suspended."); // ### Should handle extremely long stack traces sensibly for user. List<StackFrame> stack = null; try { stack = thread.frames(); } catch (IncompatibleThreadStateException e) { env.failure("Thread is not suspended."); } // ### Fix this! // ### Previously mishandled cases where thread was not current. // ### Now, prints all of the stack regardless of current frame. int frameIndex = 0; // int frameIndex = context.getCurrentFrameIndex(); if (stack == null) { env.failure("Thread is not running (no stack)."); } else { OutputSink out = env.getOutputSink(); int nFrames = stack.size(); for (int i = frameIndex; i < nFrames; i++) { StackFrame frame = stack.get(i); Location loc = frame.location(); Method meth = loc.method(); out.print(" [" + (i + 1) + "] "); out.print(meth.declaringType().name()); out.print('.'); out.print(meth.name()); out.print(" ("); if (meth.isNative()) { out.print("native method"); } else if (loc.lineNumber() != -1) { try { out.print(loc.sourceName()); } catch (AbsentInformationException e) { out.print("<unknown>"); } out.print(':'); out.print(loc.lineNumber()); } out.print(')'); if (showPC) { long pc = loc.codeIndex(); if (pc != -1) { out.print(", pc = " + pc); } } out.println(); } out.show(); } }
private void commandNext() throws NoSessionException { ThreadReference current = context.getCurrentThread(); if (current == null) { env.failure("No current thread."); return; } try { runtime.stepOverLine(current); } catch (AbsentInformationException e) { env.failure( "No linenumber information available -- " + "Try \"nexti\" to step by instructions."); } }
private void commandLocals() throws NoSessionException { ThreadReference current = context.getCurrentThread(); if (current == null) { env.failure("No default thread specified: " + "use the \"thread\" command first."); return; } StackFrame frame; try { frame = context.getCurrentFrame(current); if (frame == null) { env.failure("Thread has not yet created any stack frames."); return; } } catch (VMNotInterruptedException e) { env.failure("Target VM must be in interrupted state."); return; } List<LocalVariable> vars; try { vars = frame.visibleVariables(); if (vars == null || vars.size() == 0) { env.failure("No local variables"); return; } } catch (AbsentInformationException e) { env.failure( "Local variable information not available." + " Compile with -g to generate variable information"); return; } OutputSink out = env.getOutputSink(); out.println("Method arguments:"); for (LocalVariable var : vars) { if (var.isArgument()) { printVar(out, var, frame); } } out.println("Local variables:"); for (LocalVariable var : vars) { if (!var.isArgument()) { printVar(out, var, frame); } } out.show(); return; }
private void commandKill(StringTokenizer t) throws NoSessionException { // ### Should change the way in which thread ids and threadgroup names // ### are distinguished. if (!t.hasMoreTokens()) { env.error("Usage: kill <threadgroup name> or <thread id>"); return; } while (t.hasMoreTokens()) { String idToken = t.nextToken(); ThreadReference thread = findThread(idToken); if (thread != null) { runtime.stopThread(thread); env.notice("Thread " + thread.name() + " killed."); return; } else { /* Check for threadgroup name, NOT skipping "system". */ // ### Should skip "system"? Classic 'jdb' does this. // ### Should deal with possible non-uniqueness of threadgroup names. ThreadGroupIterator itg = allThreadGroups(); while (itg.hasNext()) { ThreadGroupReference tg = itg.nextThreadGroup(); if (tg.name().equals(idToken)) { ThreadIterator it = new ThreadIterator(tg); while (it.hasNext()) { runtime.stopThread(it.nextThread()); } env.notice("Threadgroup " + tg.name() + "killed."); return; } } env.failure("\"" + idToken + "\" is not a valid threadgroup or id."); } } }
private void commandConnect(StringTokenizer t) { try { LaunchTool.queryAndLaunchVM(runtime); } catch (VMLaunchFailureException e) { env.failure("Attempt to connect failed."); } }
private ThreadReference findThread(String idToken) throws NoSessionException { String id; ThreadReference thread = null; if (idToken.startsWith("t@")) { id = idToken.substring(2); } else { id = idToken; } try { ThreadReference[] threads = threads(); long threadID = Long.parseLong(id, 16); for (ThreadReference thread2 : threads) { if (thread2.uniqueID() == threadID) { thread = thread2; break; } } if (thread == null) { // env.failure("No thread for id \"" + idToken + "\""); env.failure("\"" + idToken + "\" is not a valid thread id."); } } catch (NumberFormatException e) { env.error("Thread id \"" + idToken + "\" is ill-formed."); thread = null; } return thread; }
private void commandMethods(StringTokenizer t) throws NoSessionException { if (!t.hasMoreTokens()) { env.error("No class specified."); return; } String idClass = t.nextToken(); ReferenceType cls = findClass(idClass); if (cls != null) { List<Method> methods = cls.allMethods(); OutputSink out = env.getOutputSink(); for (int i = 0; i < methods.size(); i++) { Method method = methods.get(i); out.print(method.declaringType().name() + " " + method.name() + "("); Iterator<String> it = method.argumentTypeNames().iterator(); if (it.hasNext()) { while (true) { out.print(it.next()); if (!it.hasNext()) { break; } out.print(", "); } } out.println(")"); } out.show(); } else { // ### Should validate class name syntax. env.failure("\"" + idClass + "\" is not a valid id or class name."); } }
private void commandPrint(StringTokenizer t, boolean dumpObject) throws NoSessionException { if (!t.hasMoreTokens()) { // ### Probably confused if expresion contains whitespace. env.error("No expression specified."); return; } ThreadReference current = context.getCurrentThread(); if (current == null) { env.failure("No default thread specified: " + "use the \"thread\" command first."); return; } StackFrame frame; try { frame = context.getCurrentFrame(current); if (frame == null) { env.failure("Thread has not yet created any stack frames."); return; } } catch (VMNotInterruptedException e) { env.failure("Target VM must be in interrupted state."); return; } while (t.hasMoreTokens()) { String expr = t.nextToken(""); Value val = null; try { val = runtime.evaluate(frame, expr); } catch (Exception e) { env.error("Exception: " + e); // ### Fix this! } if (val == null) { return; // Error message already printed } OutputSink out = env.getOutputSink(); if (dumpObject && (val instanceof ObjectReference) && !(val instanceof StringReference)) { ObjectReference obj = (ObjectReference) val; ReferenceType refType = obj.referenceType(); out.println(expr + " = " + val.toString() + " {"); dump(out, obj, refType, refType); out.println("}"); } else { out.println(expr + " = " + val.toString()); } out.show(); } }
private void commandNexti() throws NoSessionException { ThreadReference current = context.getCurrentThread(); if (current == null) { env.failure("No current thread."); return; } runtime.stepOverInstruction(current); }
private void commandStep(StringTokenizer t) throws NoSessionException { ThreadReference current = context.getCurrentThread(); if (current == null) { env.failure("No current thread."); return; } try { if (t.hasMoreTokens() && t.nextToken().toLowerCase().equals("up")) { runtime.stepOut(current); } else { runtime.stepIntoLine(current); } } catch (AbsentInformationException e) { env.failure( "No linenumber information available -- " + "Try \"stepi\" to step by instructions."); } }
private boolean doLoad(boolean suspended, StringTokenizer t) throws NoSessionException { String clname; if (!t.hasMoreTokens()) { clname = context.getMainClassName(); if (!clname.equals("")) { // Run from prevously-set class name. try { String vmArgs = context.getVmArguments(); runtime.run(suspended, vmArgs, clname, context.getProgramArguments()); return true; } catch (VMLaunchFailureException e) { env.failure("Attempt to launch main class \"" + clname + "\" failed."); } } else { env.failure("No main class specifed and no current default defined."); } } else { clname = t.nextToken(); StringBuffer sbuf = new StringBuffer(); // Allow VM arguments to be specified here? while (t.hasMoreTokens()) { String tok = t.nextToken(); sbuf.append(tok); if (t.hasMoreTokens()) { sbuf.append(' '); } } String args = sbuf.toString(); try { String vmArgs = context.getVmArguments(); runtime.run(suspended, vmArgs, clname, args); context.setMainClassName(clname); // context.setVmArguments(vmArgs); context.setProgramArguments(args); return true; } catch (VMLaunchFailureException e) { env.failure("Attempt to launch main class \"" + clname + "\" failed."); } } return false; }
private void commandDown(StringTokenizer t) throws NoSessionException { ThreadReference current = context.getCurrentThread(); if (current == null) { env.failure("No current thread."); return; } int nLevels = readCount(t); if (nLevels <= 0) { env.error("usage: down [n frames]"); return; } try { int delta = context.moveCurrentFrameIndex(current, nLevels); if (delta == 0) { env.notice("Already at bottom of stack."); } else if (delta < nLevels) { env.notice("Moved down " + delta + " frames to bottom of stack."); } } catch (VMNotInterruptedException e) { env.failure("Target VM must be in interrupted state."); } }
private void commandThreadGroup(StringTokenizer t) throws NoSessionException { if (!t.hasMoreTokens()) { env.error("Threadgroup name not specified."); return; } String name = t.nextToken(); ThreadGroupReference tg = findThreadGroup(name); if (tg == null) { env.failure(name + " is not a valid threadgroup name."); } else { // ### Should notify user. setDefaultThreadGroup(tg); } }
private void commandAttach(StringTokenizer t) { String portName; if (!t.hasMoreTokens()) { portName = context.getRemotePort(); if (!portName.equals("")) { try { runtime.attach(portName); } catch (VMLaunchFailureException e) { env.failure("Attempt to attach to port \"" + portName + "\" failed."); } } else { env.failure("No port specifed and no current default defined."); } } else { portName = t.nextToken(); try { runtime.attach(portName); } catch (VMLaunchFailureException e) { env.failure("Attempt to attach to port \"" + portName + "\" failed."); } context.setRemotePort(portName); } }
private void commandThreads(StringTokenizer t) throws NoSessionException { if (!t.hasMoreTokens()) { OutputSink out = env.getOutputSink(); printThreadGroup(out, getDefaultThreadGroup(), 0); out.show(); return; } String name = t.nextToken(); ThreadGroupReference tg = findThreadGroup(name); if (tg == null) { env.failure(name + " is not a valid threadgroup name."); } else { OutputSink out = env.getOutputSink(); printThreadGroup(out, tg, 0); out.show(); } }
private void commandList(StringTokenizer t) throws NoSessionException { ThreadReference current = context.getCurrentThread(); if (current == null) { env.error("No thread specified."); return; } Location loc; try { StackFrame frame = context.getCurrentFrame(current); if (frame == null) { env.failure("Thread has not yet begun execution."); return; } loc = frame.location(); } catch (VMNotInterruptedException e) { env.failure("Target VM must be in interrupted state."); return; } SourceModel source = sourceManager.sourceForLocation(loc); if (source == null) { if (loc.method().isNative()) { env.failure("Current method is native."); return; } env.failure("No source available for " + Utils.locationString(loc) + "."); return; } ReferenceType refType = loc.declaringType(); int lineno = loc.lineNumber(); if (t.hasMoreTokens()) { String id = t.nextToken(); // See if token is a line number. try { lineno = Integer.valueOf(id).intValue(); } catch (NumberFormatException nfe) { // It isn't -- see if it's a method name. List<Method> meths = refType.methodsByName(id); if (meths == null || meths.size() == 0) { env.failure( id + " is not a valid line number or " + "method name for class " + refType.name()); return; } else if (meths.size() > 1) { env.failure(id + " is an ambiguous method name in" + refType.name()); return; } loc = meths.get(0).location(); lineno = loc.lineNumber(); } } int startLine = (lineno > 4) ? lineno - 4 : 1; int endLine = startLine + 9; String sourceLine = source.sourceLine(lineno); if (sourceLine == null) { env.failure("" + lineno + " is an invalid line number for " + refType.name()); } else { OutputSink out = env.getOutputSink(); for (int i = startLine; i <= endLine; i++) { sourceLine = source.sourceLine(i); if (sourceLine == null) { break; } out.print(i); out.print("\t"); if (i == lineno) { out.print("=> "); } else { out.print(" "); } out.println(sourceLine); } out.show(); } }