/* attach to running target vm */ private VirtualMachine attachTarget() { AttachingConnector attacher = (AttachingConnector) connector; try { return attacher.attach(connectorArgs); } catch (IOException ioe) { ioe.printStackTrace(); MessageOutput.fatalError("Unable to attach to target VM."); } catch (IllegalConnectorArgumentsException icae) { icae.printStackTrace(); MessageOutput.fatalError("Internal debugger error."); } return null; // Shuts up the compiler }
static void shutdown(String message) { if (connection != null) { try { connection.disposeVM(); } catch (VMDisconnectedException e) { // Shutting down after the VM has gone away. This is // not an error, and we just ignore it. } } if (message != null) { MessageOutput.lnprint(message); MessageOutput.println(); } System.exit(0); }
synchronized VirtualMachine open() { if (connector instanceof LaunchingConnector) { vm = launchTarget(); } else if (connector instanceof AttachingConnector) { vm = attachTarget(); } else if (connector instanceof ListeningConnector) { vm = listenTarget(); } else { throw new InternalError(MessageOutput.format("Invalid connect type")); } vm.setDebugTraceMode(traceFlags); if (vm.canBeModified()) { setEventRequests(vm); resolveEventRequests(); } /* * Now that the vm connection is open, fetch the debugee * classpath and set up a default sourcepath. * (Unless user supplied a sourcepath on the command line) * (Bug ID 4186582) */ if (Env.getSourcePath().length() == 0) { if (vm instanceof PathSearchingVirtualMachine) { PathSearchingVirtualMachine psvm = (PathSearchingVirtualMachine) vm; Env.setSourcePath(psvm.classPath()); } else { Env.setSourcePath("."); } } return vm; }
/* listen for connection from target vm */ private VirtualMachine listenTarget() { ListeningConnector listener = (ListeningConnector) connector; try { String retAddress = listener.startListening(connectorArgs); MessageOutput.println("Listening at address:", retAddress); vm = listener.accept(connectorArgs); listener.stopListening(connectorArgs); return vm; } catch (IOException ioe) { ioe.printStackTrace(); MessageOutput.fatalError("Unable to attach to target VM."); } catch (IllegalConnectorArgumentsException icae) { icae.printStackTrace(); MessageOutput.fatalError("Internal debugger error."); } return null; // Shuts up the compiler }
private void dumpFailedLaunchInfo(Process process) { try { dumpStream(process.getErrorStream()); dumpStream(process.getInputStream()); } catch (IOException e) { MessageOutput.println("Unable to display process output:", e.getMessage()); } }
/** Return a description of an object. */ static String description(ObjectReference ref) { ReferenceType clazz = ref.referenceType(); long id = ref.uniqueID(); if (clazz == null) { return toHex(id); } else { return MessageOutput.format( "object description and hex id", new Object[] {clazz.name(), toHex(id)}); } }
static void removeThread(ThreadReference thread) { if (thread.equals(ThreadInfo.current)) { // Current thread has died. // Be careful getting the thread name. If its death happens // as part of VM termination, it may be too late to get the // information, and an exception will be thrown. String currentThreadName; try { currentThreadName = "\"" + thread.name() + "\""; } catch (Exception e) { currentThreadName = ""; } setCurrentThread(null); MessageOutput.println(); MessageOutput.println("Current thread died. Execution continuing...", currentThreadName); } threads.remove(getThreadInfo(thread)); }
/* launch child target vm */ private VirtualMachine launchTarget() { LaunchingConnector launcher = (LaunchingConnector) connector; try { VirtualMachine vm = launcher.launch(connectorArgs); process = vm.process(); displayRemoteOutput(process.getErrorStream()); displayRemoteOutput(process.getInputStream()); return vm; } catch (IOException ioe) { ioe.printStackTrace(); MessageOutput.fatalError("Unable to launch target VM."); } catch (IllegalConnectorArgumentsException icae) { icae.printStackTrace(); MessageOutput.fatalError("Internal debugger error."); } catch (VMStartException vmse) { MessageOutput.println("vmstartexception", vmse.getMessage()); MessageOutput.println(); dumpFailedLaunchInfo(vmse.process()); MessageOutput.fatalError("Target VM failed to initialize."); } return null; // Shuts up the compiler }
private void dumpStream(InputStream stream) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(stream)); int i; try { while ((i = in.read()) != -1) { MessageOutput.printDirect((char) i); // Special case: use // printDirect() } } catch (IOException ex) { String s = ex.getMessage(); if (!s.startsWith("Bad file number")) { throw ex; } // else we got a Bad file number IOException which just means // that the debuggee has gone away. We'll just treat it the // same as if we got an EOF. } }
VMConnection(String connectSpec, int traceFlags) { String nameString; String argString; int index = connectSpec.indexOf(':'); if (index == -1) { nameString = connectSpec; argString = ""; } else { nameString = connectSpec.substring(0, index); argString = connectSpec.substring(index + 1); } connector = findConnector(nameString); if (connector == null) { throw new IllegalArgumentException(MessageOutput.format("No connector named:", nameString)); } connectorArgs = parseConnectorArgs(connector, argString); this.traceFlags = traceFlags; }
private Map<String, com.sun.jdi.connect.Connector.Argument> parseConnectorArgs( Connector connector, String argString) { Map<String, com.sun.jdi.connect.Connector.Argument> arguments = connector.defaultArguments(); /* * We are parsing strings of the form: * name1=value1,[name2=value2,...] * However, the value1...valuen substrings may contain * embedded comma(s), so make provision for quoting inside * the value substrings. (Bug ID 4285874) */ String regexPattern = "(quote=[^,]+,)|" + // special case for quote=., "(\\w+=)" + // name= "(((\"[^\"]*\")|" + // ( "l , ue" "('[^']*')|" + // 'l , ue' "([^,'\"]+))+,)"; // v a l u e )+ , Pattern p = Pattern.compile(regexPattern); Matcher m = p.matcher(argString); while (m.find()) { int startPosition = m.start(); int endPosition = m.end(); if (startPosition > 0) { /* * It is an error if parsing skips over any part of argString. */ throw new IllegalArgumentException( MessageOutput.format("Illegal connector argument", argString)); } String token = argString.substring(startPosition, endPosition); int index = token.indexOf('='); String name = token.substring(0, index); String value = token.substring(index + 1, token.length() - 1); // Remove comma delimiter /* * for values enclosed in quotes (single and/or double quotes) * strip off enclosing quote chars * needed for quote enclosed delimited substrings */ if (name.equals("options")) { StringBuilder sb = new StringBuilder(); for (String s : splitStringAtNonEnclosedWhiteSpace(value)) { while (isEnclosed(s, "\"") || isEnclosed(s, "'")) { s = s.substring(1, s.length() - 1); } sb.append(s); sb.append(" "); } value = sb.toString(); } Connector.Argument argument = arguments.get(name); if (argument == null) { throw new IllegalArgumentException( MessageOutput.format( "Argument is not defined for connector:", new Object[] {name, connector.name()})); } argument.setValue(value); argString = argString.substring(endPosition); // Remove what was just parsed... m = p.matcher(argString); // and parse again on what is left. } if ((!argString.equals(",")) && (argString.length() > 0)) { /* * It is an error if any part of argString is left over, * unless it was empty to begin with. */ throw new IllegalArgumentException( MessageOutput.format("Illegal connector argument", argString)); } return arguments; }
private static List<String> splitStringAtNonEnclosedWhiteSpace(String value) throws IllegalArgumentException { List<String> al = new ArrayList<String>(); char[] arr; int startPosition = 0; int endPosition = 0; final char SPACE = ' '; final char DOUBLEQ = '"'; final char SINGLEQ = '\''; /* * An "open" or "active" enclosing state is where * the first valid start quote qualifier is found, * and there is a search in progress for the * relevant end matching quote * * enclosingTargetChar set to SPACE * is used to signal a non open enclosing state */ char enclosingTargetChar = SPACE; if (value == null) { throw new IllegalArgumentException(MessageOutput.format("value string is null")); } // split parameter string into individual chars arr = value.toCharArray(); for (int i = 0; i < arr.length; i++) { switch (arr[i]) { case SPACE: { // do nothing for spaces // unless last in array if (isLastChar(arr, i)) { endPosition = i; // break for substring creation break; } continue; } case DOUBLEQ: case SINGLEQ: { if (enclosingTargetChar == arr[i]) { // potential match to close open enclosing if (isNextCharWhitespace(arr, i)) { // if peek next is whitespace // then enclosing is a valid substring endPosition = i; // reset enclosing target char enclosingTargetChar = SPACE; // break for substring creation break; } } if (enclosingTargetChar == SPACE) { // no open enclosing state // handle as normal char if (isPreviousCharWhitespace(arr, i)) { startPosition = i; // peek forward for end candidates if (value.indexOf(arr[i], i + 1) >= 0) { // set open enclosing state by // setting up the target char enclosingTargetChar = arr[i]; } else { // no more target chars left to match // end enclosing, handle as normal char if (isNextCharWhitespace(arr, i)) { endPosition = i; // break for substring creation break; } } } } continue; } default: { // normal non-space, non-" and non-' chars if (enclosingTargetChar == SPACE) { // no open enclosing state if (isPreviousCharWhitespace(arr, i)) { // start of space delim substring startPosition = i; } if (isNextCharWhitespace(arr, i)) { // end of space delim substring endPosition = i; // break for substring creation break; } } continue; } } // break's end up here if (startPosition > endPosition) { throw new IllegalArgumentException(MessageOutput.format("Illegal option values")); } // extract substring and add to List<String> al.add(value.substring(startPosition, ++endPosition)); // set new start position i = startPosition = endPosition; } // for loop return al; }
private ThreadInfo(ThreadReference thread) { this.thread = thread; if (thread == null) { MessageOutput.fatalError("Internal error: null ThreadInfo created"); } }
public static void main(String argv[]) throws MissingResourceException { redirectOutMessage(); String cmdLine = ""; String javaArgs = ""; int traceFlags = VirtualMachine.TRACE_NONE; boolean launchImmediately = false; String connectSpec = null; MessageOutput.textResources = ResourceBundle.getBundle( "com.sun.tools.example.debug.tty.TTYResources", Locale.getDefault()); for (int i = 0; i < argv.length; i++) { String token = argv[i]; if (token.equals("-dbgtrace")) { if ((i == argv.length - 1) || !Character.isDigit(argv[i + 1].charAt(0))) { traceFlags = VirtualMachine.TRACE_ALL; } else { String flagStr = ""; try { flagStr = argv[++i]; traceFlags = Integer.decode(flagStr).intValue(); } catch (NumberFormatException nfe) { usageError("dbgtrace flag value must be an integer:", flagStr); return; } } } else if (token.equals("-X")) { usageError("Use java minus X to see"); return; } else if ( // Standard VM options passed on token.equals("-v") || token.startsWith("-v:") || // -v[:...] token.startsWith("-verbose") || // -verbose[:...] token.startsWith("-D") || // -classpath handled below // NonStandard options passed on token.startsWith("-X") || // Old-style options (These should remain in place as long as // the standard VM accepts them) token.equals("-noasyncgc") || token.equals("-prof") || token.equals("-verify") || token.equals("-noverify") || token.equals("-verifyremote") || token.equals("-verbosegc") || token.startsWith("-ms") || token.startsWith("-mx") || token.startsWith("-ss") || token.startsWith("-oss")) { javaArgs = addArgument(javaArgs, token); } else if (token.equals("-tclassic")) { usageError("Classic VM no longer supported."); return; } else if (token.equals("-tclient")) { // -client must be the first one javaArgs = "-client " + javaArgs; } else if (token.equals("-tserver")) { // -server must be the first one javaArgs = "-server " + javaArgs; } else if (token.equals("-sourcepath")) { if (i == (argv.length - 1)) { usageError("No sourcepath specified."); return; } Env.setSourcePath(argv[++i]); } else if (token.equals("-classpath")) { if (i == (argv.length - 1)) { usageError("No classpath specified."); return; } javaArgs = addArgument(javaArgs, token); javaArgs = addArgument(javaArgs, argv[++i]); } else if (token.equals("-attach")) { if (connectSpec != null) { usageError("cannot redefine existing connection", token); return; } if (i == (argv.length - 1)) { usageError("No attach address specified."); return; } String address = argv[++i]; /* * -attach is shorthand for one of the reference implementation's * attaching connectors. Use the shared memory attach if it's * available; otherwise, use sockets. Build a connect * specification string based on this decision. */ if (supportsSharedMemory()) { connectSpec = "com.sun.jdi.SharedMemoryAttach:name=" + address; } else { String suboptions = addressToSocketArgs(address); connectSpec = "com.sun.jdi.SocketAttach:" + suboptions; } } else if (token.equals("-listen") || token.equals("-listenany")) { if (connectSpec != null) { usageError("cannot redefine existing connection", token); return; } String address = null; if (token.equals("-listen")) { if (i == (argv.length - 1)) { usageError("No attach address specified."); return; } address = argv[++i]; } /* * -listen[any] is shorthand for one of the reference implementation's * listening connectors. Use the shared memory listen if it's * available; otherwise, use sockets. Build a connect * specification string based on this decision. */ if (supportsSharedMemory()) { connectSpec = "com.sun.jdi.SharedMemoryListen:"; if (address != null) { connectSpec += ("name=" + address); } } else { connectSpec = "com.sun.jdi.SocketListen:"; if (address != null) { connectSpec += addressToSocketArgs(address); } } } else if (token.equals("-launch")) { launchImmediately = true; } else if (token.equals("-listconnectors")) { Commands evaluator = new Commands(); evaluator.commandConnectors(Bootstrap.virtualMachineManager()); return; } else if (token.equals("-connect")) { /* * -connect allows the user to pick the connector * used in bringing up the target VM. This allows * use of connectors other than those in the reference * implementation. */ if (connectSpec != null) { usageError("cannot redefine existing connection", token); return; } if (i == (argv.length - 1)) { usageError("No connect specification."); return; } connectSpec = argv[++i]; } else if (token.equals("-help")) { usage(); } else if (token.equals("-version")) { Commands evaluator = new Commands(); evaluator.commandVersion(progname, Bootstrap.virtualMachineManager()); System.exit(0); } else if (token.startsWith("-")) { usageError("invalid option", token); return; } else { // Everything from here is part of the command line cmdLine = addArgument("", token); for (i++; i < argv.length; i++) { cmdLine = addArgument(cmdLine, argv[i]); } break; } } /* * Unless otherwise specified, set the default connect spec. */ /* * Here are examples of jdb command lines and how the options * are interpreted as arguments to the program being debugged. * arg1 arg2 * ---- ---- * jdb hello a b a b * jdb hello "a b" a b * jdb hello a,b a,b * jdb hello a, b a, b * jdb hello "a, b" a, b * jdb -connect "com.sun.jdi.CommandLineLaunch:main=hello a,b" illegal * jdb -connect com.sun.jdi.CommandLineLaunch:main=hello "a,b" illegal * jdb -connect 'com.sun.jdi.CommandLineLaunch:main=hello "a,b"' arg1 = a,b * jdb -connect 'com.sun.jdi.CommandLineLaunch:main=hello "a b"' arg1 = a b * jdb -connect 'com.sun.jdi.CommandLineLaunch:main=hello a b' arg1 = a arg2 = b * jdb -connect 'com.sun.jdi.CommandLineLaunch:main=hello "a," b' arg1 = a, arg2 = b */ if (connectSpec == null) { connectSpec = "com.sun.jdi.CommandLineLaunch:"; } else if (!connectSpec.endsWith(",") && !connectSpec.endsWith(":")) { connectSpec += ","; // (Bug ID 4285874) } cmdLine = cmdLine.trim(); javaArgs = javaArgs.trim(); if (cmdLine.length() > 0) { if (!connectSpec.startsWith("com.sun.jdi.CommandLineLaunch:")) { usageError("Cannot specify command line with connector:", connectSpec); return; } connectSpec += "main=" + cmdLine + ","; } if (javaArgs.length() > 0) { if (!connectSpec.startsWith("com.sun.jdi.CommandLineLaunch:")) { usageError("Cannot specify target vm arguments with connector:", connectSpec); return; } connectSpec += "options=" + javaArgs + ","; } try { if (!connectSpec.endsWith(",")) { connectSpec += ","; // (Bug ID 4285874) } Env.init(connectSpec, launchImmediately, traceFlags); new ThreadDumper(); } catch (Exception e) { MessageOutput.printException("Internal exception:", e); } }
private static void usage() { MessageOutput.println("zz usage text", new Object[] {progname, File.pathSeparator}); System.exit(1); }
public void vmInterrupted() { super.vmInterrupted(); MessageOutput.printDirectln("Jacky's vmInterrupted"); StringTokenizer t = new StringTokenizer("where"); executeCommand(t); }