diff -r fd16c54261b3 -r 90ce3da70b43 jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,252 @@ +/* + * Copyright 1998-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tools.jdi; + +import com.sun.tools.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import com.sun.jdi.VirtualMachine; +import java.util.Map; +import java.util.HashMap; +import java.util.Random; +import java.io.IOException; +import java.io.File; + +public class SunCommandLineLauncher extends AbstractLauncher implements LaunchingConnector { + + static private final String ARG_HOME = "home"; + static private final String ARG_OPTIONS = "options"; + static private final String ARG_MAIN = "main"; + static private final String ARG_INIT_SUSPEND = "suspend"; + static private final String ARG_QUOTE = "quote"; + static private final String ARG_VM_EXEC = "vmexec"; + + TransportService transportService; + Transport transport; + boolean usingSharedMemory = false; + + TransportService transportService() { + return transportService; + } + + public Transport transport() { + return transport; + } + + public SunCommandLineLauncher() { + super(); + + /** + * By default this connector uses either the shared memory + * transport or the socket transport + */ + try { + Class c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService"); + transportService = (TransportService)c.newInstance(); + transport = new Transport() { + public String name() { + return "dt_shmem"; + } + }; + usingSharedMemory = true; + } catch (ClassNotFoundException x) { + } catch (UnsatisfiedLinkError x) { + } catch (InstantiationException x) { + } catch (IllegalAccessException x) { + }; + if (transportService == null) { + transportService = new SocketTransportService(); + transport = new Transport() { + public String name() { + return "dt_socket"; + } + }; + } + + addStringArgument( + ARG_HOME, + getString("sun.home.label"), + getString("sun.home"), + System.getProperty("java.home"), + false); + addStringArgument( + ARG_OPTIONS, + getString("sun.options.label"), + getString("sun.options"), + "", + false); + addStringArgument( + ARG_MAIN, + getString("sun.main.label"), + getString("sun.main"), + "", + true); + + addBooleanArgument( + ARG_INIT_SUSPEND, + getString("sun.init_suspend.label"), + getString("sun.init_suspend"), + true, + false); + + addStringArgument( + ARG_QUOTE, + getString("sun.quote.label"), + getString("sun.quote"), + "\"", + true); + addStringArgument( + ARG_VM_EXEC, + getString("sun.vm_exec.label"), + getString("sun.vm_exec"), + "java", + true); + } + + static boolean hasWhitespace(String string) { + int length = string.length(); + for (int i = 0; i < length; i++) { + if (Character.isWhitespace(string.charAt(i))) { + return true; + } + } + return false; + } + + public VirtualMachine + launch(Map arguments) + throws IOException, IllegalConnectorArgumentsException, + VMStartException + { + VirtualMachine vm; + + String home = argument(ARG_HOME, arguments).value(); + String options = argument(ARG_OPTIONS, arguments).value(); + String mainClassAndArgs = argument(ARG_MAIN, arguments).value(); + boolean wait = ((BooleanArgumentImpl)argument(ARG_INIT_SUSPEND, + arguments)).booleanValue(); + String quote = argument(ARG_QUOTE, arguments).value(); + String exe = argument(ARG_VM_EXEC, arguments).value(); + String exePath = null; + + if (quote.length() > 1) { + throw new IllegalConnectorArgumentsException("Invalid length", + ARG_QUOTE); + } + + if ((options.indexOf("-Djava.compiler=") != -1) && + (options.toLowerCase().indexOf("-djava.compiler=none") == -1)) { + throw new IllegalConnectorArgumentsException("Cannot debug with a JIT compiler", + ARG_OPTIONS); + } + + /* + * Start listening. + * If we're using the shared memory transport then we pick a + * random address rather than using the (fixed) default. + * Random() uses System.currentTimeMillis() as the seed + * which can be a problem on windows (many calls to + * currentTimeMillis can return the same value), so + * we do a few retries if we get an IOException (we + * assume the IOException is the filename is already in use.) + */ + TransportService.ListenKey listenKey; + if (usingSharedMemory) { + Random rr = new Random(); + int failCount = 0; + while(true) { + try { + String address = "javadebug" + + String.valueOf(rr.nextInt(100000)); + listenKey = transportService().startListening(address); + break; + } catch (IOException ioe) { + if (++failCount > 5) { + throw ioe; + } + } + } + } else { + listenKey = transportService().startListening(); + } + String address = listenKey.address(); + + try { + if (home.length() > 0) { + /* + * A wrinkle in the environment: + * 64-bit executables are stored under $JAVA_HOME/bin/os_arch + * 32-bit executables are stored under $JAVA_HOME/bin + */ + String os_arch = System.getProperty("os.arch"); + if ("SunOS".equals(System.getProperty("os.name")) && + ("sparcv9".equals(os_arch) || "amd64".equals(os_arch))) { + exePath = home + File.separator + "bin" + File.separator + + os_arch + File.separator + exe; + } else { + exePath = home + File.separator + "bin" + File.separator + exe; + } + } else { + exePath = exe; + } + // Quote only if necessary in case the quote arg value is bogus + if (hasWhitespace(exe)) { + exePath = quote + exePath + quote; + } + + String xrun = "transport=" + transport().name() + + ",address=" + address + + ",suspend=" + (wait? 'y' : 'n'); + // Quote only if necessary in case the quote arg value is bogus + if (hasWhitespace(xrun)) { + xrun = quote + xrun + quote; + } + + String command = exePath + ' ' + + options + ' ' + + "-Xdebug " + + "-Xrunjdwp:" + xrun + ' ' + + mainClassAndArgs; + + // System.err.println("Command: \"" + command + '"'); + vm = launch(tokenizeCommand(command, quote.charAt(0)), address, listenKey, + transportService()); + } finally { + transportService().stopListening(listenKey); + } + + return vm; + } + + public String name() { + return "com.sun.jdi.CommandLineLaunch"; + } + + public String description() { + return getString("sun.description"); + + } +}