252 lines · 8.9 KB · Java
RawDownload
/* * Copyright (c) 1998, 2004, Oracle and/or its affiliates. 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.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.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<String,? extends Connector.Argument> 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");     }}