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 commandStop(StringTokenizer t) throws NoSessionException { String token; if (!t.hasMoreTokens()) { listEventRequests(); } else { token = t.nextToken(); // Ignore optional "at" or "in" token. // Allowed for backward compatibility. if (token.equals("at") || token.equals("in")) { if (t.hasMoreTokens()) { token = t.nextToken(); } else { env.error("Missing breakpoint specification."); return; } } BreakpointSpec bpSpec = parseBreakpointSpec(token); if (bpSpec != null) { // ### Add sanity-checks for deferred breakpoint. runtime.install(bpSpec); } else { env.error("Ill-formed breakpoint specification."); } } }
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."); } }
/** Command: unmonitor Unmonitor an expression */ private void commandUnmonitor(StringTokenizer t) throws NoSessionException { if (!t.hasMoreTokens()) { env.error("Argument required"); } else { env.getMonitorListModel().remove(t.nextToken("")); } }
private void commandWhere(StringTokenizer t, boolean showPC) throws NoSessionException { ThreadReference current = context.getCurrentThread(); if (!t.hasMoreTokens()) { if (current == null) { env.error("No thread specified."); return; } dumpStack(current, showPC); } else { String token = t.nextToken(); if (token.toLowerCase().equals("all")) { ThreadIterator it = allThreads(); while (it.hasNext()) { ThreadReference thread = it.next(); out.println(thread.name() + ": "); dumpStack(thread, showPC); } } else { ThreadReference thread = findThread(t.nextToken()); // ### Do we want to set current thread here? // ### Should notify user of change. if (thread != null) { context.setCurrentThread(thread); } dumpStack(thread, showPC); } } }
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 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 commandClear(StringTokenizer t) throws NoSessionException { if (!t.hasMoreTokens()) { // Print set breakpoints listEventRequests(); return; } // ### need 'clear all' BreakpointSpec bpSpec = parseBreakpointSpec(t.nextToken()); if (bpSpec != null) { List<EventRequestSpec> specs = runtime.eventRequestSpecs(); if (specs.isEmpty()) { env.notice("No breakpoints set."); } else { List<EventRequestSpec> toDelete = new ArrayList<EventRequestSpec>(); for (EventRequestSpec spec : specs) { if (spec.equals(bpSpec)) { toDelete.add(spec); } } // The request used for matching should be found if (toDelete.size() <= 1) { env.notice("No matching breakpoint set."); } for (EventRequestSpec spec : toDelete) { runtime.delete(spec); } } } else { env.error("Ill-formed breakpoint specification."); } }
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(); } }
/** Check expression type */ public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) { vset = right.checkValue(env, ctx, vset, exp); if (index == null) { env.error(where, "array.index.required"); return vset; } vset = index.checkValue(env, ctx, vset, exp); index = convert(env, ctx, Type.tInt, index); if (!right.type.isType(TC_ARRAY)) { if (!right.type.isType(TC_ERROR)) { env.error(where, "not.array", right.type); } return vset; } type = right.type.getElementType(); return vset; }
/** Generate code */ public void write(Environment env, DataOutputStream out, MemberDefinition field, ConstantPool tab) throws IOException { // listing(System.out); if ((field != null) && field.getArguments() != null) { int sum = 0; Vector v = field.getArguments(); for (Enumeration e = v.elements(); e.hasMoreElements(); ) { MemberDefinition f = ((MemberDefinition) e.nextElement()); sum += f.getType().stackSize(); } maxvar = sum; } // Make sure the stack balances. Also calculate maxvar and maxstack try { balance(first, 0); } catch (CompilerError e) { System.out.println("ERROR: " + e); listing(System.out); throw e; } // Assign PCs int pc = 0, nexceptions = 0; for (Instruction inst = first; inst != null; inst = inst.next) { inst.pc = pc; int sz = inst.size(tab); if (pc < 65536 && (pc + sz) >= 65536) { env.error(inst.where, "warn.method.too.long"); } pc += sz; if (inst.opc == opc_try) { nexceptions += ((TryData) inst.value).catches.size(); } } // Write header out.writeShort(maxdepth); out.writeShort(maxvar); out.writeInt(maxpc = pc); // Generate code for (Instruction inst = first.next; inst != null; inst = inst.next) { inst.write(out, tab); } // write exceptions out.writeShort(nexceptions); if (nexceptions > 0) { // listing(System.out); writeExceptions(env, out, tab, first, last); } }
private void commandThread(StringTokenizer t) throws NoSessionException { if (!t.hasMoreTokens()) { env.error("Thread number not specified."); return; } ThreadReference thread = findThread(t.nextToken()); if (thread != null) { // ### Should notify user. context.setCurrentThread(thread); } }
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 commandView(StringTokenizer t) throws NoSessionException { if (!t.hasMoreTokens()) { env.error("Argument required"); } else { String name = t.nextToken(); if (name.endsWith(".java") || name.indexOf(File.separatorChar) >= 0) { env.viewSource(name); } else { // ### JDI crashes taking line number for class. /** * *** ReferenceType cls = findClass(name); if (cls != null) { * env.viewLocation(cls.location()); } else { env.failure("No such class"); } *** */ String fileName = name.replace('.', File.separatorChar) + ".java"; env.viewSource(fileName); } } }
public Vset checkAmbigName( Environment env, Context ctx, Vset vset, Hashtable exp, UnaryExpression loc) { if (index == null) { vset = right.checkAmbigName(env, ctx, vset, exp, this); if (right.type == Type.tPackage) { FieldExpression.reportFailedPackagePrefix(env, right); return vset; } // Nope. Is this field expression a type? if (right instanceof TypeExpression) { Type atype = Type.tArray(right.type); loc.right = new TypeExpression(where, atype); return vset; } env.error(where, "array.index.required"); return vset; } return super.checkAmbigName(env, ctx, vset, exp, loc); }
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."); } }
/** Check statement */ Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) { checkLabel(env, ctx); vset = reach(env, vset); if (expr != null) { vset = expr.checkValue(env, ctx, vset, exp); } // Make sure the return isn't inside a static initializer if (ctx.field.isInitializer()) { env.error(where, "return.inside.static.initializer"); return DEAD_END; } // Check return type if (ctx.field.getType().getReturnType().isType(TC_VOID)) { if (expr != null) { if (ctx.field.isConstructor()) { env.error(where, "return.with.value.constr", ctx.field); } else { env.error(where, "return.with.value", ctx.field); } expr = null; } } else { if (expr == null) { env.error(where, "return.without.value", ctx.field); } else { expr = convert(env, ctx, ctx.field.getType().getReturnType(), expr); } } CheckContext mctx = ctx.getReturnContext(); if (mctx != null) { mctx.vsBreak = mctx.vsBreak.join(vset); } CheckContext exitctx = ctx.getTryExitContext(); if (exitctx != null) { exitctx.vsTryExit = exitctx.vsTryExit.join(vset); } if (expr != null) { // see if we are returning a value out of a try or synchronized // statement. If so, find the outermost one. . . . Node outerFinallyNode = null; for (Context c = ctx; c != null; c = c.prev) { if (c.node == null) { continue; } if (c.node.op == METHOD) { // Don't search outside current method. Fixes 4084230. break; } if (c.node.op == SYNCHRONIZED) { outerFinallyNode = c.node; break; } else if (c.node.op == FINALLY && ((CheckContext) c).vsContinue != null) { outerFinallyNode = c.node; } } if (outerFinallyNode != null) { if (outerFinallyNode.op == FINALLY) { ((FinallyStatement) outerFinallyNode).needReturnSlot = true; } else { ((SynchronizedStatement) outerFinallyNode).needReturnSlot = true; } } } return DEAD_END; }
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(); } }
/** Select the type */ final void selectType(Environment env, Context ctx, int tm) { Type rtype = null; // special conversion type for RHS switch (op) { case ASGADD: if (left.type == Type.tString) { if (right.type == Type.tVoid) { // The type of the right hand side can be // anything except void. Fix for 4119864. env.error(where, "incompatible.type", opNames[op], Type.tVoid, Type.tString); type = Type.tError; } else { type = itype = Type.tString; } return; } /* Fall through */ case ASGDIV: case ASGMUL: case ASGSUB: case ASGREM: if ((tm & TM_DOUBLE) != 0) { itype = Type.tDouble; } else if ((tm & TM_FLOAT) != 0) { itype = Type.tFloat; } else if ((tm & TM_LONG) != 0) { itype = Type.tLong; } else { itype = Type.tInt; } break; case ASGBITAND: case ASGBITOR: case ASGBITXOR: if ((tm & TM_BOOLEAN) != 0) { itype = Type.tBoolean; } else if ((tm & TM_LONG) != 0) { itype = Type.tLong; } else { itype = Type.tInt; } break; case ASGLSHIFT: case ASGRSHIFT: case ASGURSHIFT: rtype = Type.tInt; // Fix for bug 4134459. // We allow any integral type (even long) to // be the right hand side of a shift operation. if (right.type.inMask(TM_INTEGER)) { right = new ConvertExpression(where, Type.tInt, right); } // The intermediate type of the expression is the // type of the left hand side after undergoing // unary (not binary) type promotion. We ignore // tm -- it contains information about both left // and right hand sides -- and we compute the // type only from the type of the lhs. if (left.type == Type.tLong) { itype = Type.tLong; } else { itype = Type.tInt; } break; default: throw new CompilerError("Bad assignOp type: " + op); } if (rtype == null) { rtype = itype; } right = convert(env, ctx, rtype, right); // The result is always the type of the left operand. type = left.type; }
Type toType(Environment env, Type t) { if (index != null) { env.error(index.where, "array.dim.in.type"); } return Type.tArray(t); }