hotspot/test/serviceability/tmtools/jstack/utils/DefaultFormat.java
changeset 35493 863fb33f9940
child 35874 6c93eabea7c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/tmtools/jstack/utils/DefaultFormat.java	Thu Jan 14 15:35:21 2016 +0300
@@ -0,0 +1,266 @@
+/*
+ * 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 utils;
+
+import java.util.Map;
+import java.util.Scanner;
+import java.util.regex.MatchResult;
+
+/**
+ *
+ * jstack default format 2008-03-05 18:36:26 Full thread dump Java HotSpot(TM)
+ * Client VM (11.0-b11 mixed mode):
+ *
+ * "Thread-16" #10 daemon prio=3 os_prio=0 tid=0x0814d800 nid=0x1d runnable
+ * [0xf394d000..0xf394d9f0] java.lang.Thread.State: RUNNABLE at
+ * java.net.SocketInputStream.socketRead0(Native Method) at
+ * java.net.SocketInputStream.read(SocketInputStream.java:129) at
+ * java.net.SocketInputStream.read(SocketInputStream.java:182) at
+ * java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2249)
+ * at
+ * java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInputStream.java:2542)
+ * at
+ * java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2552)
+ * at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1297) at
+ * java.io.ObjectInputStream.readObject(ObjectInputStream.java:351) at
+ * tmtools.share.debuggee.DebuggeeProtocolHandler.run(DebuggeeProtocolHandler.java:32)
+ *
+ * Locked ownable synchronizers: - None ....
+ *
+ * Note that os_prio field is optional and will be printed only if JVM was able
+ * to get native thread priority.
+ */
+public class DefaultFormat implements Format {
+
+    protected String threadInfoPattern() {
+        return "^\"(.*)\"\\s(#\\d+\\s|)(daemon\\s|)prio=(.+)\\s(os_prio=(.+)\\s|)tid=(.+)\\snid=(.+)\\s("
+                + Consts.UNKNOWN
+                + "|runnable|waiting\\son\\scondition|in\\sObject\\.wait\\(\\)|waiting\\sfor\\smonitor\\sentry)((.*))$";
+    }
+
+    protected String methodInfoPattern() {
+        return "^\\s+at\\s(.+)\\((.*?)(\\:|\\))((.*?))\\)?$";
+    }
+
+    protected String extendedStatusPattern() {
+        return "\\s+java\\.lang\\.Thread\\.State\\:\\s((.+))$";
+    }
+
+    protected String jniGlobalRefInfoPattern() {
+        return "^JNI\\sglobal\\sreferences:\\s((.+))$";
+    }
+
+    protected String monitorInfoPattern() {
+        return "^\\s+\\-\\s(locked|waiting\\son|waiting\\sto\\slock)\\s\\<(.*)\\>\\s\\(((.*))\\)$";
+    }
+
+    protected String vmVersionInfoPattern() {
+        return "Full\\sthread\\sdump\\s.*";
+    }
+
+    protected String ownableSynchronizersPattern() {
+        return "^\\s+\\-\\s(\\<.*\\>\\s\\(((.*))\\)|None)$";
+    }
+
+    public JStack parse(String stack) {
+        JStack result = new JStack();
+        Scanner scanner = new Scanner(stack);
+
+        // parsing thread stacks
+        ThreadStack currentThreadStack = null;
+        MethodInfo currentMethodInfo = null;
+
+        try {
+            while (scanner.hasNextLine()) {
+                String line = scanner.nextLine();
+                if (line.matches(threadInfoPattern())) {
+                    currentThreadStack = parseThreadInfo(line);
+                    result.addThreadStack(currentThreadStack.getThreadName(), currentThreadStack);
+                } else if (line.matches(methodInfoPattern())) {
+                    currentMethodInfo = parseMethodInfo(line);
+                    currentThreadStack.addMethod(currentMethodInfo);
+                } else if (line.matches(monitorInfoPattern())) {
+                    MonitorInfo mi = parseMonitorInfo(line);
+                    currentMethodInfo.getLocks().add(mi);
+                } else if (line.matches(extendedStatusPattern())) {
+                    currentThreadStack.setExtendedStatus(parseExtendedStatus(line));
+                } else if (line.matches(vmVersionInfoPattern())) {
+                    result.setVmVersion(line);
+                } else if (line.matches(ownableSynchronizersPattern())) {
+                    currentThreadStack.getLockOSList().add(parseLockInfo(line));
+                } else if (line.matches(jniGlobalRefInfoPattern())) {
+                    result.setJniGlobalReferences(parseJNIGlobalRefs(line));
+                } else if (line.length() != 0) {
+                    System.err.println("[Warning] Unknown string: " + line);
+                }
+            }
+
+            scanner.close();
+
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            throw new RuntimeException("Unexpected format in jstack output");
+        }
+
+        return result;
+    }
+
+    private MonitorInfo parseMonitorInfo(String line) {
+        Scanner s = new Scanner(line);
+        s.findInLine(monitorInfoPattern());
+        MonitorInfo mi = new MonitorInfo();
+        MatchResult res = s.match();
+
+        mi.setType(res.group(1));
+        mi.setMonitorAddress(res.group(2));
+        mi.setMonitorClass(res.group(3));
+
+        return mi;
+    }
+
+    protected String parseExtendedStatus(String line) {
+        Scanner s = new Scanner(line);
+        s.findInLine(extendedStatusPattern());
+        String result = s.match().group(1);
+        s.close();
+        return result;
+    }
+
+    protected String parseJNIGlobalRefs(String line) {
+        Scanner s = new Scanner(line);
+        s.findInLine(jniGlobalRefInfoPattern());
+        String result = s.match().group(1);
+        s.close();
+        return result;
+    }
+
+    protected ThreadStack parseThreadInfo(String threadInfo) {
+        Scanner s = new Scanner(threadInfo);
+        ThreadStack result = new ThreadStack();
+
+        // parsing thread info
+        s.findInLine(threadInfoPattern());
+        MatchResult res = s.match();
+
+        result.setThreadName(res.group(1));
+
+        result.setType(res.group(3));
+
+        result.setPriority(res.group(4));
+        result.setTid(res.group(7));
+        result.setNid(res.group(8));
+        result.setStatus(res.group(9));
+
+        s.close();
+        return result;
+    }
+
+    protected MethodInfo parseMethodInfo(String line) {
+
+        MethodInfo result = new MethodInfo();
+        Scanner s = new Scanner(line);
+
+        s.findInLine(methodInfoPattern());
+        MatchResult rexp = s.match();
+        if (rexp.group(4) != null && rexp.group(4).length() > 0) {
+            // line "  at tmtools.jstack.share.utils.Utils.sleep(Utils.java:29)"
+            result.setName(rexp.group(1));
+            result.setCompilationUnit(rexp.group(2));
+            result.setLine(rexp.group(4));
+
+        } else {
+            // line "  at java.lang.Thread.sleep(Native Method)"
+            result.setName(rexp.group(1));
+        }
+
+        s.close();
+        return result;
+    }
+
+    public String dumpStackTraces() {
+        StringBuffer result = new StringBuffer();
+        Map<Thread, StackTraceElement[]> stacks = Thread.getAllStackTraces();
+
+        // adding data and vm version
+        result.append(Consts.UNKNOWN + "\n");
+        result.append(Consts.UNKNOWN + "\n\n");
+
+        for (Thread t : stacks.keySet()) {
+
+            result.append("\"" + t.getName() + "\"");
+            result.append(Consts.SEPARATOR);
+
+            // status
+            if (t.isDaemon()) {
+                result.append("daemon");
+                result.append(Consts.SEPARATOR);
+            }
+
+            // priority
+            result.append("prio=" + t.getPriority());
+            result.append(Consts.SEPARATOR);
+
+            // tid
+            result.append("tid=" + Consts.UNKNOWN);
+            result.append(Consts.SEPARATOR);
+
+            // nid
+            result.append("nid=" + Consts.UNKNOWN);
+            result.append(Consts.SEPARATOR);
+
+            // status
+            result.append(Consts.UNKNOWN);
+            result.append(Consts.SEPARATOR);
+
+            result.append("\n");
+
+            // extended status
+            result.append("   java.lang.Thread.State: "
+                    + String.valueOf(Thread.currentThread().getState()));
+            result.append(Consts.SEPARATOR);
+            result.append("\n");
+
+            for (StackTraceElement st : stacks.get(t)) {
+                result.append("  at " + st.toString() + "\n");
+            }
+            result.append("\n");
+        }
+
+        result.append(Consts.JNI_GLOBAL_REF + Consts.UNKNOWN + "\n");
+        return result.toString();
+    }
+
+    protected LockInfo parseLockInfo(String line) {
+        LockInfo res = new LockInfo();
+
+        Scanner s = new Scanner(line);
+        s.findInLine(ownableSynchronizersPattern());
+
+        MatchResult matchRes = s.match();
+        String lock = matchRes.group(1).equals("None") ? matchRes.group(1) : matchRes.group(2);
+        res.setLock(lock);
+
+        return res;
+    }
+
+}