8059038: Create new launcher for SA tools
authordsamersoff
Thu, 23 Jul 2015 18:17:09 +0300
changeset 31978 0f5334c83857
parent 31974 869b4f9cbb40
child 31979 fb7be4e8a187
8059038: Create new launcher for SA tools Summary: Proivide jhsdb command to launch sa based tools Reviewed-by: sspitsyn, jbachorik
hotspot/agent/src/share/classes/sun/jvm/hotspot/SAGetopt.java
hotspot/agent/src/share/classes/sun/jvm/hotspot/SALauncher.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/SAGetopt.java	Thu Jul 23 18:17:09 2015 +0300
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ * 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 sun.jvm.hotspot;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class SAGetopt {
+
+    private String[] _argv;
+
+    private int _optind;    // index in arguments array
+    private int _optopt;    // index within an argument
+    private String _optarg; // last option argument
+    private boolean _optreset; // special handling of first call
+
+    public SAGetopt(String[] args) {
+        _argv  = args;
+        _optind   = 0;
+        _optopt   = 1;
+        _optarg   = null;
+        _optreset = true;
+    }
+
+    public String getOptarg() {
+        return _optarg;
+    }
+
+    public int getOptind() {
+        return _optind;
+    }
+
+    private void extractOptarg(String opt) {
+        // Argument expected
+        if (_optind > _argv.length) {
+            throw new RuntimeException("Not enough arguments for '" + opt + "'");
+        }
+
+        if (! _argv[_optind].isEmpty() && _argv[_optind].charAt(0) == '-') {
+            throw new RuntimeException("Argument is expected for '" + opt + "'");
+        }
+
+        _optarg = _argv[_optind];
+        _optind += 1;
+    }
+
+    private String processLongOptions(String carg, String[] longOptStr) {
+        List<String> los = Arrays.asList(longOptStr);
+        String[] ca = carg.split("=", 2);
+
+        if (los.contains(ca[0])) {
+            if (ca.length > 1) {
+                throw new RuntimeException("Argument is not expected for '" + ca[0] + "'");
+            }
+            return carg;
+        }
+
+        if (los.contains(ca[0] + "=")) {
+            if (ca.length > 1) {
+                // GNU style options --file=name
+                _optarg = ca[1];
+            }
+            else {
+                // Mixed style options --file name
+                extractOptarg(ca[0]);
+            }
+
+            return ca[0];
+        }
+
+        throw new RuntimeException("Invalid option '" + ca[0] + "'");
+    }
+
+    public String next(String optStr, String[] longOptStr) {
+
+        if (_optind >= _argv.length || _argv[_optind] == null) {
+            // All arguments processed
+            return null;
+        }
+
+        String carg = _argv[_optind];
+        _optarg = null;
+
+        if (_optreset) {
+            // End of option batch like '-abc' reached, expect option to start from '-'
+
+            if (carg.isEmpty() || carg.charAt(0) != '-' || carg.equals("--")) {
+                // Stop processing on -- or first non-option argument;
+                return null;
+            }
+
+            if (carg.startsWith("--")) {
+                // Handle long options, it can't be combined so it's simple
+                if (longOptStr == null || longOptStr.length == 0) {
+                    // No long options expected, stop options processing
+                    return null;
+                }
+                ++ _optind;
+
+                // at this point carg contains at least one character besides --
+                carg = carg.substring(2);
+                return processLongOptions(carg, longOptStr);
+            }
+
+            if (optStr == null || optStr.length() == 0) {
+                // No short options
+                return null;
+            }
+
+            // At this point carg[0] contains '-'
+            _optreset = false;
+            _optopt = 1;
+        }
+
+        char ch = carg.charAt(_optopt);
+
+        // adjust pointer to next character
+        _optopt += 1;
+
+        // Okay, ready to process options like
+        // -abc -d bla -ef
+
+        int chIndex = optStr.indexOf(ch);
+        if (chIndex == -1) {
+            throw new RuntimeException("Invalid option '" + ch + "'");
+        }
+
+        if (_optopt >= carg.length()) {
+            _optind += 1;
+            _optreset = true;
+        }
+
+        if (chIndex < optStr.length()-1 && optStr.charAt(chIndex+1) == ':') {
+            // Argument expected
+            extractOptarg(String.valueOf(ch));
+        }
+
+        return String.valueOf(ch);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/SALauncher.java	Thu Jul 23 18:17:09 2015 +0300
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ * 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 sun.jvm.hotspot;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import sun.jvm.hotspot.tools.JStack;
+import sun.jvm.hotspot.tools.JMap;
+import sun.jvm.hotspot.tools.JInfo;
+
+public class SALauncher {
+
+    private static boolean launcherHelp() {
+        System.out.println("    clhsdb       \tcommand line debugger");
+        System.out.println("    hsdb         \tui debugger");
+        System.out.println("    jstack --help\tto get more information");
+        System.out.println("    jmap   --help\tto get more information");
+        System.out.println("    jinfo  --help\tto get more information");
+        return false;
+    }
+
+    private static boolean commonHelp() {
+        // --pid <pid>
+        // --exe <exe>
+        // --core <core>
+        System.out.println("    --exe\texecutable image name");
+        System.out.println("    --core\tpath to coredump");
+        System.out.println("    --pid\tpid of process to attach");
+        return false;
+    }
+
+    private static boolean jinfoHelp() {
+        // --flags -> -flags
+        // --sysprops -> -sysprops
+        System.out.println("    --flags\tto print VM flags");
+        System.out.println("    --sysprops\tto print Java System properties");
+        System.out.println("    <no option>\tto print both of the above");
+        return commonHelp();
+    }
+
+    private static boolean jmapHelp() {
+        // --heap -> -heap
+        // --binaryheap -> -heap:format=b
+        // --histo -> -histo
+        // --clstats -> -clstats
+        // --finalizerinfo -> -finalizerinfo
+
+        System.out.println("    <no option>\tto print same info as Solaris pmap");
+        System.out.println("    --heap\tto print java heap summary");
+        System.out.println("    --binaryheap\tto dump java heap in hprof binary format");
+        System.out.println("    --histo\tto print histogram of java object heap");
+        System.out.println("    --clstats\tto print class loader statistics");
+        System.out.println("    --finalizerinfo\tto print information on objects awaiting finalization");
+        return commonHelp();
+    }
+
+    private static boolean jstackHelp() {
+        // --locks -> -l
+        // --mixed -> -m
+        System.out.println("    --locks\tto print java.util.concurrent locks");
+        System.out.println("    --mixed\tto print both java and native frames (mixed mode)");
+        return commonHelp();
+    }
+
+    private static boolean toolHelp(String toolName) {
+        if (toolName.equals("jstack")) {
+            return jstackHelp();
+        }
+        if (toolName.equals("jinfo")) {
+            return jinfoHelp();
+        }
+        if (toolName.equals("jmap")) {
+            return jmapHelp();
+        }
+        if (toolName.equals("hsdb") || toolName.equals("clhsdb")) {
+            return commonHelp();
+        }
+        return launcherHelp();
+    }
+
+    private static void runCLHSDB(String[] oldArgs) {
+        SAGetopt sg = new SAGetopt(oldArgs);
+        String[] longOpts = {"exe=", "core=", "pid="};
+
+        ArrayList<String> newArgs = new ArrayList();
+        String exeORpid = null;
+        String core = null;
+        String s = null;
+
+        while((s = sg.next(null, longOpts)) != null) {
+            if (s.equals("exe")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("core")) {
+                core = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("pid")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+        }
+
+        if (exeORpid != null) {
+            newArgs.add(exeORpid);
+            if (core != null) {
+                newArgs.add(core);
+            }
+        }
+        CLHSDB.main(newArgs.toArray(new String[newArgs.size()]));
+    }
+
+    private static void runHSDB(String[] oldArgs) {
+        SAGetopt sg = new SAGetopt(oldArgs);
+        String[] longOpts = {"exe=", "core=", "pid="};
+
+        ArrayList<String> newArgs = new ArrayList();
+        String exeORpid = null;
+        String core = null;
+        String s = null;
+
+        while((s = sg.next(null, longOpts)) != null) {
+            if (s.equals("exe")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("core")) {
+                core = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("pid")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+        }
+
+        if (exeORpid != null) {
+            newArgs.add(exeORpid);
+            if (core != null) {
+                newArgs.add(core);
+            }
+        }
+        HSDB.main(newArgs.toArray(new String[newArgs.size()]));
+    }
+
+    private static void runJSTACK(String[] oldArgs) {
+        SAGetopt sg = new SAGetopt(oldArgs);
+        String[] longOpts = {"exe=", "core=", "pid=",
+                                 "mixed", "locks"};
+
+        ArrayList<String> newArgs = new ArrayList();
+        String exeORpid = null;
+        String core = null;
+        String s = null;
+
+        while((s = sg.next(null, longOpts)) != null) {
+            if (s.equals("exe")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("core")) {
+                core = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("pid")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("mixed")) {
+                newArgs.add("-m");
+                continue;
+            }
+            if (s.equals("locks")) {
+                newArgs.add("-l");
+                continue;
+            }
+        }
+
+        if (exeORpid != null) {
+            newArgs.add(exeORpid);
+            if (core != null) {
+                newArgs.add(core);
+            }
+        }
+
+        JStack.main(newArgs.toArray(new String[newArgs.size()]));
+    }
+
+    private static void runJMAP(String[] oldArgs) {
+        SAGetopt sg = new SAGetopt(oldArgs);
+        String[] longOpts = {"exe=", "core=", "pid=",
+              "heap", "binaryheap", "histo", "clstats", "finalizerinfo"};
+
+        ArrayList<String> newArgs = new ArrayList();
+        String exeORpid = null;
+        String core = null;
+        String s = null;
+
+        while((s = sg.next(null, longOpts)) != null) {
+            if (s.equals("exe")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("core")) {
+                core = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("pid")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("heap")) {
+                newArgs.add("-heap");
+                continue;
+            }
+            if (s.equals("binaryheap")) {
+                newArgs.add("-heap:format=b");
+                continue;
+            }
+            if (s.equals("histo")) {
+                newArgs.add("-histo");
+                continue;
+            }
+            if (s.equals("clstats")) {
+                newArgs.add("-clstats");
+                continue;
+            }
+            if (s.equals("finalizerinfo")) {
+                newArgs.add("-finalizerinfo");
+                continue;
+            }
+        }
+
+        if (exeORpid != null) {
+            newArgs.add(exeORpid);
+            if (core != null) {
+                newArgs.add(core);
+            }
+        }
+
+        JMap.main(newArgs.toArray(new String[newArgs.size()]));
+    }
+
+    private static void runJINFO(String[] oldArgs) {
+        SAGetopt sg = new SAGetopt(oldArgs);
+        String[] longOpts = {"exe=", "core=", "pid=",
+                                     "flags", "sysprops"};
+
+        ArrayList<String> newArgs = new ArrayList();
+        String exeORpid = null;
+        String core = null;
+        String s = null;
+
+        while((s = sg.next(null, longOpts)) != null) {
+            if (s.equals("exe")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("core")) {
+                core = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("pid")) {
+                exeORpid = sg.getOptarg();
+                continue;
+            }
+            if (s.equals("flags")) {
+                newArgs.add("-flags");
+                continue;
+            }
+            if (s.equals("sysprops")) {
+                newArgs.add("-sysprops");
+                continue;
+            }
+        }
+
+        if (exeORpid != null) {
+            newArgs.add(exeORpid);
+            if (core != null) {
+                newArgs.add(core);
+            }
+        }
+
+        JInfo.main(newArgs.toArray(new String[newArgs.size()]));
+    }
+
+    public static void main(String[] args) {
+        // Provide a help
+        if (args.length == 0) {
+            launcherHelp();
+            return;
+        }
+        // No arguments imply help for jstack, jmap, jinfo but launch clhsdb and hsdb
+        if (args.length == 1 && !args[0].equals("clhsdb") && !args[0].equals("hsdb")) {
+            toolHelp(args[0]);
+            return;
+        }
+
+        for (String arg : args) {
+            if (arg.equals("-h") || arg.equals("-help") || arg.equals("--help")) {
+                toolHelp(args[0]);
+                return;
+            }
+        }
+
+        String[] oldArgs = Arrays.copyOfRange(args, 1, args.length);
+
+        // Run SA interactive mode
+        if (args[0].equals("clhsdb")) {
+            runCLHSDB(oldArgs);
+            return;
+        }
+
+        if (args[0].equals("hsdb")) {
+            runHSDB(oldArgs);
+            return;
+        }
+
+        // Run SA tmtools mode
+        if (args[0].equals("jstack")) {
+            runJSTACK(oldArgs);
+            return;
+        }
+
+        if (args[0].equals("jmap")) {
+            runJMAP(oldArgs);
+            return;
+        }
+
+        if (args[0].equals("jinfo")) {
+            runJINFO(oldArgs);
+            return;
+        }
+    }
+}