[10] RFR 8181647: jhsdb jstack could not output thread name

chihiro ito chihiro.ito at oracle.com
Mon Jul 3 15:32:29 UTC 2017


Hi Yasumasa,

Thank you for review, again.

> According to JavaThread::print_on() in thread.cpp , stack address in 
> thread dump shows top of page address.
> If so, can we calculate it as below?
>
>   this.getLastJavaSP().andWithMask(~0xFFF) 

Yes, It is also correct. I modified source code to your simple one.

> Are these regex correct?
> Regex for SP "\\[0x[0-9a-f]+]" should be "\\[0x[0-9a-f]+\\]"
> (Last backslash is missing.) 

] that is not paired with [ does not need to be escaped.

following 2 case it print true.
System.out.println("]".matches("]"));
System.out.println("]".matches("\\]"));

The source code which modified the logical operation is as follows.

Regards,
Chihiro


diff --git 
a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java
--- 
a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java
+++ 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java
@@ -1,5 +1,5 @@
  /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights 
reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -59,20 +59,20 @@
    // parkBlocker field is new since 1.6
    private static OopField threadParkBlockerField;

+  private static IntField threadPriorityField;
+  private static BooleanField threadDaemonField;
+
    // possible values of java_lang_Thread::ThreadStatus
    private static int THREAD_STATUS_NEW;
-  /*
-    Other enum constants are not needed as of now. Uncomment these as 
and when needed.

-    private static int THREAD_STATUS_RUNNABLE;
-    private static int THREAD_STATUS_SLEEPING;
-    private static int THREAD_STATUS_IN_OBJECT_WAIT;
-    private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED;
-    private static int THREAD_STATUS_PARKED;
-    private static int THREAD_STATUS_PARKED_TIMED;
-    private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER;
-    private static int THREAD_STATUS_TERMINATED;
-  */
+  private static int THREAD_STATUS_RUNNABLE;
+  private static int THREAD_STATUS_SLEEPING;
+  private static int THREAD_STATUS_IN_OBJECT_WAIT;
+  private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED;
+  private static int THREAD_STATUS_PARKED;
+  private static int THREAD_STATUS_PARKED_TIMED;
+  private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER;
+  private static int THREAD_STATUS_TERMINATED;

    // java.util.concurrent.locks.AbstractOwnableSynchronizer fields
    private static OopField absOwnSyncOwnerThreadField;
@@ -229,20 +229,19 @@
        threadStatusField = (IntField) k.findField("threadStatus", "I");
        threadParkBlockerField = (OopField) k.findField("parkBlocker",
                                       "Ljava/lang/Object;");
+      threadPriorityField = (IntField) k.findField("priority", "I");
+      threadDaemonField = (BooleanField) k.findField("daemon", "Z");
        TypeDataBase db = VM.getVM().getTypeDataBase();
        THREAD_STATUS_NEW = 
db.lookupIntConstant("java_lang_Thread::NEW").intValue();
-      /*
-        Other enum constants are not needed as of now. Uncomment these 
as and when needed.

-        THREAD_STATUS_RUNNABLE = 
db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue();
-        THREAD_STATUS_SLEEPING = 
db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue();
-        THREAD_STATUS_IN_OBJECT_WAIT = 
db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue();
-        THREAD_STATUS_IN_OBJECT_WAIT_TIMED = 
db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue();
-        THREAD_STATUS_PARKED = 
db.lookupIntConstant("java_lang_Thread::PARKED").intValue();
-        THREAD_STATUS_PARKED_TIMED = 
db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue();
-        THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = 
db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue();
-        THREAD_STATUS_TERMINATED = 
db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue();
-      */
+      THREAD_STATUS_RUNNABLE = 
db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue();
+      THREAD_STATUS_SLEEPING = 
db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue();
+      THREAD_STATUS_IN_OBJECT_WAIT = 
db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue();
+      THREAD_STATUS_IN_OBJECT_WAIT_TIMED = 
db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue();
+      THREAD_STATUS_PARKED = 
db.lookupIntConstant("java_lang_Thread::PARKED").intValue();
+      THREAD_STATUS_PARKED_TIMED = 
db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue();
+      THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = 
db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue();
+      THREAD_STATUS_TERMINATED = 
db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue();

        if (Assert.ASSERTS_ENABLED) {
          // it is okay to miss threadStatusField, because this was
@@ -331,4 +330,46 @@
        return absOwnSyncOwnerThreadField.getValue(oop);
      }
    }
+
+  public static int threadOopGetPriority(Oop threadOop) {
+    initThreadFields();
+    if (threadPriorityField != null) {
+      return threadPriorityField.getValue(threadOop);
+    } else {
+      return 0;
+    }
+  }
+
+  public static boolean threadOopGetDaemon(Oop threadOop) {
+    initThreadFields();
+    if (threadDaemonField != null) {
+      return threadDaemonField.getValue(threadOop);
+    } else {
+      return false;
+    }
+  }
+
+  public static String threadOopGetThreadStatusName(Oop threadOop) {
+    int status = OopUtilities.threadOopGetThreadStatus(threadOop);
+    if( status == THREAD_STATUS_NEW ){
+      return "NEW";
+    }else if(status == THREAD_STATUS_RUNNABLE ){
+      return "RUNNABLE";
+    }else if(status == THREAD_STATUS_SLEEPING ){
+      return "TIMED_WAITING (sleeping)";
+    }else if(status == THREAD_STATUS_IN_OBJECT_WAIT ){
+      return "WAITING (on object monitor)";
+    }else if(status == THREAD_STATUS_IN_OBJECT_WAIT_TIMED ){
+      return "TIMED_WAITING (on object monitor)";
+    }else if(status == THREAD_STATUS_PARKED ){
+      return "WAITING (parking)";
+    }else if(status == THREAD_STATUS_PARKED_TIMED ){
+      return "TIMED_WAITING (parking)";
+    }else if(status == THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER ){
+      return "BLOCKED (on object monitor)";
+    }else if(status == THREAD_STATUS_TERMINATED ){
+      return "TERMINATED";
+    }
+    return "UNKNOWN";
+  }
  }
diff --git 
a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
--- 
a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
+++ 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
@@ -475,4 +475,35 @@
      return access.getLastSP(addr);
    }

+
+  public void printThreadInfoOn(PrintStream out){
+
+    Oop threadOop = this.getThreadObj();
+
+    out.print("\"");
+    out.print(this.getThreadName());
+    out.print("\" #");
+    out.print(OopUtilities.threadOopGetTID(threadOop));
+    if( OopUtilities.threadOopGetDaemon(threadOop) ){
+      out.print(" daemon");
+    }
+    out.print(" prio=");
+    out.print(OopUtilities.threadOopGetPriority(threadOop));
+    out.print(" tid=");
+ out.print(String.format("0x%016x",this.getAddress().asLongValue()));
+    out.print(" nid=");
+    out.print(String.format("0x%x ",this.getOSThread().threadId()));
+    out.print(getOSThread().getThreadState().getPrintVal());
+    out.print(" [");
+    if( this.getLastJavaSP() == null){
+      out.print(String.format("0x%016x",0L));
+    } else {
+      out.print(this.getLastJavaSP().andWithMask(~0xFFF));
+    }
+    out.println("]");
+    out.print("   java.lang.Thread.State: ");
+ out.println(OopUtilities.threadOopGetThreadStatusName(threadOop));
+    out.print("   JavaThread state: _thread_");
+    out.println(this.getThreadState().toString().toLowerCase());
+  }
  }
diff --git 
a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java
--- 
a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java
+++ 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java
@@ -1,5 +1,5 @@
  /*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights 
reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -33,6 +33,19 @@
  public class OSThread extends VMObject {
      private static JIntField interruptedField;
      private static Field threadIdField;
+    private static CIntegerField threadStateField;
+
+    // ThreadStates read from underlying process
+    private static int ALLOCATED;
+    private static int INITIALIZED;
+    private static int RUNNABLE;
+    private static int MONITOR_WAIT;
+    private static int CONDVAR_WAIT;
+    private static int OBJECT_WAIT;
+    private static int BREAKPOINTED;
+    private static int SLEEPING;
+    private static int ZOMBIE;
+
      static {
          VM.registerVMInitializedObserver(new Observer() {
              public void update(Observable o, Object data) {
@@ -45,6 +58,17 @@
          Type type = db.lookupType("OSThread");
          interruptedField = type.getJIntField("_interrupted");
          threadIdField = type.getField("_thread_id");
+        threadStateField = type.getCIntegerField("_state");
+
+        ALLOCATED = db.lookupIntConstant("ALLOCATED").intValue();
+        INITIALIZED = db.lookupIntConstant("INITIALIZED").intValue();
+        RUNNABLE = db.lookupIntConstant("RUNNABLE").intValue();
+        MONITOR_WAIT = db.lookupIntConstant("MONITOR_WAIT").intValue();
+        CONDVAR_WAIT = db.lookupIntConstant("CONDVAR_WAIT").intValue();
+        OBJECT_WAIT = db.lookupIntConstant("OBJECT_WAIT").intValue();
+        BREAKPOINTED = db.lookupIntConstant("BREAKPOINTED").intValue();
+        SLEEPING = db.lookupIntConstant("SLEEPING").intValue();
+        ZOMBIE = db.lookupIntConstant("ZOMBIE").intValue();
      }

      public OSThread(Address addr) {
@@ -59,4 +83,28 @@
          return threadIdField.getJInt(addr);
      }

+    public ThreadState getThreadState() {
+        int val = (int)threadStateField.getValue(addr);
+        if (val ==  ALLOCATED) {
+            return ThreadState.ALLOCATED;
+        } else if (val ==  INITIALIZED) {
+            return ThreadState.INITIALIZED;
+        } else if (val ==  RUNNABLE) {
+            return ThreadState.RUNNABLE;
+        } else if (val ==  MONITOR_WAIT) {
+            return ThreadState.MONITOR_WAIT;
+        } else if (val ==  CONDVAR_WAIT) {
+            return ThreadState.CONDVAR_WAIT;
+        } else if (val ==  OBJECT_WAIT) {
+            return ThreadState.OBJECT_WAIT;
+        } else if (val ==  BREAKPOINTED) {
+            return ThreadState.BREAKPOINTED;
+        } else if (val ==  SLEEPING) {
+            return ThreadState.SLEEPING;
+        } else if (val ==  ZOMBIE) {
+            return ThreadState.ZOMBIE;
+        } else {
+            throw new RuntimeException("Illegal thread state " + val);
+        }
+    }
  }
diff --git 
a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java
new file mode 100644
--- /dev/null
+++ 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, 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.runtime;
+
+/** This is a type-safe enum mirroring the ThreadState enum in
+ osThread.hpp. The conversion between the underlying ints
+ and these values is done in OSThread. */
+
+public class ThreadState {
+
+    private String printVal;
+
+    /** Memory has been allocated but not initialized */
+    public static final ThreadState ALLOCATED = new 
ThreadState("allocated");
+    /** The thread has been initialized but yet started */
+    public static final ThreadState INITIALIZED = new 
ThreadState("initialized");
+    /** Has been started and is runnable, but not necessarily running */
+    public static final ThreadState RUNNABLE = new ThreadState("runnable");
+    /** Waiting on a contended monitor lock */
+    public static final ThreadState MONITOR_WAIT = new 
ThreadState("waiting for monitor entry");
+    /** Waiting on a condition variable */
+    public static final ThreadState CONDVAR_WAIT = new 
ThreadState("waiting on condition");
+    /** Waiting on an Object.wait() call */
+    public static final ThreadState OBJECT_WAIT = new ThreadState("in 
Object.wait()");
+    /** Suspended at breakpoint */
+    public static final ThreadState BREAKPOINTED = new ThreadState("at 
breakpoint");
+    /** Thread.sleep() */
+    public static final ThreadState SLEEPING = new ThreadState("sleeping");
+    /** All done, but not reclaimed yet */
+    public static final ThreadState ZOMBIE = new ThreadState("zombie");
+
+    private ThreadState(String printVal){
+        this.printVal = printVal;
+    }
+
+    public String getPrintVal() {
+        return printVal;
+    }
+}
diff --git 
a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
@@ -1,5 +1,5 @@
  /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights 
reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -88,6 +88,10 @@
                 out.print("----------------- ");
                 out.print(th);
                 out.println(" -----------------");
+               JavaThread jthread = (JavaThread) proxyToThread.get(th);
+               if (jthread != null) {
+                  jthread.printThreadInfoOn(out);
+               }
                 while (f != null) {
                    ClosestSymbol sym = f.closestSymbolToPC();
                    Address pc = f.pc();
diff --git 
a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
--- 
a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
+++ 
b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
@@ -1,5 +1,5 @@
  /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights 
reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -74,14 +74,7 @@
              int i = 1;
              for (JavaThread cur = threads.first(); cur != null; cur = 
cur.next(), i++) {
                  if (cur.isJavaThread()) {
-                    Address sp = cur.getLastJavaSP();
-                    tty.print("Thread ");
-                    cur.printThreadIDOn(tty);
-                    tty.print(": (state = " + cur.getThreadState());
-                    if (verbose) {
-                        tty.println(", current Java SP = " + sp);
-                    }
-                    tty.println(')');
+                    cur.printThreadInfoOn(tty);
                      try {
                          for (JavaVFrame vf = 
cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
                              Method method = vf.getMethod();
diff --git a/src/share/vm/runtime/vmStructs.cpp 
b/src/share/vm/runtime/vmStructs.cpp
--- a/src/share/vm/runtime/vmStructs.cpp
+++ b/src/share/vm/runtime/vmStructs.cpp
@@ -981,6 +981,7 @@
/************/ \
\
    volatile_nonstatic_field(OSThread, _interrupted, 
jint)                                  \
+  volatile_nonstatic_field(OSThread, _state, 
ThreadState)                                 \
\
/************************/ \
    /* OopMap and OopMapSet */ \
@@ -2186,6 +2187,7 @@
declare_integer_type(Generation::Name) \
declare_integer_type(InstanceKlass::ClassState) \
declare_integer_type(JavaThreadState) \
+ declare_integer_type(ThreadState) \
declare_integer_type(Location::Type) \
declare_integer_type(Location::Where) \
declare_integer_type(Flag::Flags) \
@@ -2443,6 +2445,20 @@
declare_constant(JavaThread::_not_terminated) \
declare_constant(JavaThread::_thread_exiting) \
\
+ /*******************/ \
+  /* JavaThreadState */                                                   \
+ /*******************/ \
+ \
+ declare_constant(ALLOCATED) \
+ declare_constant(INITIALIZED) \
+ declare_constant(RUNNABLE) \
+ declare_constant(MONITOR_WAIT) \
+ declare_constant(CONDVAR_WAIT) \
+ declare_constant(OBJECT_WAIT) \
+ declare_constant(BREAKPOINTED) \
+ declare_constant(SLEEPING) \
+ declare_constant(ZOMBIE) \
+ \
/******************************/ \
    /* Klass misc. enum constants 
*/                                        \
/******************************/ \
diff --git a/test/serviceability/sa/JhsdbThreadInfoTest.java 
b/test/serviceability/sa/JhsdbThreadInfoTest.java
new file mode 100644
--- /dev/null
+++ b/test/serviceability/sa/JhsdbThreadInfoTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.Utils;
+
+/*
+ * @test
+ * @library /test/lib
+ * @run main JhsdbThreadInfoTest
+ */
+public class JhsdbThreadInfoTest {
+
+    public static void main(String[] args) throws Exception {
+
+        if (!Platform.shouldSAAttach()) {
+            System.out.println("SA attach not expected to work - test 
skipped.");
+            return;
+        }
+
+        LingeredApp app = null;
+
+        try {
+            app = LingeredApp.startApp(Utils.getVmOptions());
+            System.out.println("Started LingeredApp with pid " + 
app.getPid());
+
+            JDKToolLauncher jhsdbLauncher = 
JDKToolLauncher.createUsingTestJDK("jhsdb");
+
+            jhsdbLauncher.addToolArg("jstack");
+            jhsdbLauncher.addToolArg("--pid");
+            jhsdbLauncher.addToolArg(Long.toString(app.getPid()));
+
+            ProcessBuilder pb = new ProcessBuilder();
+            pb.command(jhsdbLauncher.getCommand());
+            Process jhsdb = pb.start();
+
+            jhsdb.waitFor();
+
+            OutputAnalyzer out = new OutputAnalyzer(jhsdb);
+
+            System.out.println(out.getStdout());
+            System.err.println(out.getStderr());
+
+            out.shouldMatch("\".+\" #\\d+ daemon prio=\\d+ 
tid=0x[0-9a-f]+ nid=0x[0-9a-f]+ .+ \\[0x[0-9a-f]+]");
+            out.shouldMatch("\"main\" #\\d+ prio=\\d+ tid=0x[0-9a-f]+ 
nid=0x[0-9a-f]+ .+ \\[0x[0-9a-f]+]");
+            out.shouldMatch("   java.lang.Thread.State: .+");
+            out.shouldMatch("   JavaThread state: _thread_.+");
+
+            out.shouldNotContain("   java.lang.Thread.State: UNKNOWN");
+            out.stderrShouldBeEmpty();
+
+            System.out.println("Test Completed");
+
+
+        } catch (InterruptedException ie) {
+            throw new Error("Problem awaiting the child process: " + 
ie, ie);
+        } catch (Exception attachE) {
+            throw new Error("Couldn't start jhsdb, attach to 
LingeredApp or match ThreadName: " + attachE);
+
+        } finally {
+            LingeredApp.stopApp(app);
+        }
+    }
+}




On 2017/07/02 21:44, Yasumasa Suenaga wrote:
> Hi Chihiro,
>
>
> printThreadInfoOn() in JavaThread.java:
>> +      Address maskAddress = this.getLastJavaSP().andWithMask(0xFFF);
>> + 
>> out.print(this.getLastJavaSP().xorWithMask(maskAddress.asLongValue()));
>
> IMHO it is complex a bit.
> According to JavaThread::print_on() in thread.cpp , stack address in 
> thread dump shows top of page address.
> If so, can we calculate it as below?
>
>   this.getLastJavaSP().andWithMask(~0xFFF)
>
>
> JhsdbThreadInfoTest.java:
>> +            out.shouldMatch("\".+\" #\\d+ daemon prio=\\d+ 
>> tid=0x[0-9a-f]+ nid=0x[0-9a-f]+ .+ \\[0x[0-9a-f]+]");
>> +            out.shouldMatch("\"main\" #\\d+ prio=\\d+ 
>> tid=0x[0-9a-f]+ nid=0x[0-9a-f]+ .+ \\[0x[0-9a-f]+]");
>
> Are these regex correct?
> Regex for SP "\\[0x[0-9a-f]+]" should be "\\[0x[0-9a-f]+\\]"
> (Last backslash is missing.)
>
>
> Thanks,
>
> Yasumasa
>
>
> On 2017/07/02 16:43, chihiro ito wrote:
>> Hi Yasumasa,
>>
>> Thank you for your review. I modified source code following your advice.
>> I applied this to latest source code and passed jtreg.
>>
>> Could somebody possibly be sponsor and commit this as cito ?
>>
>> Regards,
>> Chihiro
>>
>> diff --git 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java 
>>
>> --- 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java
>> +++ 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java
>> @@ -1,5 +1,5 @@
>>   /*
>> - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All 
>> rights reserved.
>> + * Copyright (c) 2000, 2017, 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
>> @@ -59,20 +59,20 @@
>>     // parkBlocker field is new since 1.6
>>     private static OopField threadParkBlockerField;
>>
>> +  private static IntField threadPriorityField;
>> +  private static BooleanField threadDaemonField;
>> +
>>     // possible values of java_lang_Thread::ThreadStatus
>>     private static int THREAD_STATUS_NEW;
>> -  /*
>> -    Other enum constants are not needed as of now. Uncomment these 
>> as and when needed.
>>
>> -    private static int THREAD_STATUS_RUNNABLE;
>> -    private static int THREAD_STATUS_SLEEPING;
>> -    private static int THREAD_STATUS_IN_OBJECT_WAIT;
>> -    private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED;
>> -    private static int THREAD_STATUS_PARKED;
>> -    private static int THREAD_STATUS_PARKED_TIMED;
>> -    private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER;
>> -    private static int THREAD_STATUS_TERMINATED;
>> -  */
>> +  private static int THREAD_STATUS_RUNNABLE;
>> +  private static int THREAD_STATUS_SLEEPING;
>> +  private static int THREAD_STATUS_IN_OBJECT_WAIT;
>> +  private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED;
>> +  private static int THREAD_STATUS_PARKED;
>> +  private static int THREAD_STATUS_PARKED_TIMED;
>> +  private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER;
>> +  private static int THREAD_STATUS_TERMINATED;
>>
>>     // java.util.concurrent.locks.AbstractOwnableSynchronizer fields
>>     private static OopField absOwnSyncOwnerThreadField;
>> @@ -229,20 +229,19 @@
>>         threadStatusField = (IntField) k.findField("threadStatus", "I");
>>         threadParkBlockerField = (OopField) k.findField("parkBlocker",
>>                                        "Ljava/lang/Object;");
>> +      threadPriorityField = (IntField) k.findField("priority", "I");
>> +      threadDaemonField = (BooleanField) k.findField("daemon", "Z");
>>         TypeDataBase db = VM.getVM().getTypeDataBase();
>>         THREAD_STATUS_NEW = 
>> db.lookupIntConstant("java_lang_Thread::NEW").intValue();
>> -      /*
>> -        Other enum constants are not needed as of now. Uncomment 
>> these as and when needed.
>>
>> -        THREAD_STATUS_RUNNABLE = 
>> db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue();
>> -        THREAD_STATUS_SLEEPING = 
>> db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue();
>> -        THREAD_STATUS_IN_OBJECT_WAIT = 
>> db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue();
>> -        THREAD_STATUS_IN_OBJECT_WAIT_TIMED = 
>> db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue();
>> -        THREAD_STATUS_PARKED = 
>> db.lookupIntConstant("java_lang_Thread::PARKED").intValue();
>> -        THREAD_STATUS_PARKED_TIMED = 
>> db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue();
>> -        THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = 
>> db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue();
>> -        THREAD_STATUS_TERMINATED = 
>> db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue();
>> -      */
>> +      THREAD_STATUS_RUNNABLE = 
>> db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue();
>> +      THREAD_STATUS_SLEEPING = 
>> db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue();
>> +      THREAD_STATUS_IN_OBJECT_WAIT = 
>> db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue();
>> +      THREAD_STATUS_IN_OBJECT_WAIT_TIMED = 
>> db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue();
>> +      THREAD_STATUS_PARKED = 
>> db.lookupIntConstant("java_lang_Thread::PARKED").intValue();
>> +      THREAD_STATUS_PARKED_TIMED = 
>> db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue();
>> +      THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = 
>> db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue();
>> +      THREAD_STATUS_TERMINATED = 
>> db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue();
>>
>>         if (Assert.ASSERTS_ENABLED) {
>>           // it is okay to miss threadStatusField, because this was
>> @@ -331,4 +330,46 @@
>>         return absOwnSyncOwnerThreadField.getValue(oop);
>>       }
>>     }
>> +
>> +  public static int threadOopGetPriority(Oop threadOop) {
>> +    initThreadFields();
>> +    if (threadPriorityField != null) {
>> +      return threadPriorityField.getValue(threadOop);
>> +    } else {
>> +      return 0;
>> +    }
>> +  }
>> +
>> +  public static boolean threadOopGetDaemon(Oop threadOop) {
>> +    initThreadFields();
>> +    if (threadDaemonField != null) {
>> +      return threadDaemonField.getValue(threadOop);
>> +    } else {
>> +      return false;
>> +    }
>> +  }
>> +
>> +  public static String threadOopGetThreadStatusName(Oop threadOop) {
>> +    int status = OopUtilities.threadOopGetThreadStatus(threadOop);
>> +    if( status == THREAD_STATUS_NEW ){
>> +      return "NEW";
>> +    }else if(status == THREAD_STATUS_RUNNABLE ){
>> +      return "RUNNABLE";
>> +    }else if(status == THREAD_STATUS_SLEEPING ){
>> +      return "TIMED_WAITING (sleeping)";
>> +    }else if(status == THREAD_STATUS_IN_OBJECT_WAIT ){
>> +      return "WAITING (on object monitor)";
>> +    }else if(status == THREAD_STATUS_IN_OBJECT_WAIT_TIMED ){
>> +      return "TIMED_WAITING (on object monitor)";
>> +    }else if(status == THREAD_STATUS_PARKED ){
>> +      return "WAITING (parking)";
>> +    }else if(status == THREAD_STATUS_PARKED_TIMED ){
>> +      return "TIMED_WAITING (parking)";
>> +    }else if(status == THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER ){
>> +      return "BLOCKED (on object monitor)";
>> +    }else if(status == THREAD_STATUS_TERMINATED ){
>> +      return "TERMINATED";
>> +    }
>> +    return "UNKNOWN";
>> +  }
>>   }
>> diff --git 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java 
>>
>> --- 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
>> +++ 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
>> @@ -475,4 +475,36 @@
>>       return access.getLastSP(addr);
>>     }
>>
>> +
>> +  public void printThreadInfoOn(PrintStream out){
>> +
>> +    Oop threadOop = this.getThreadObj();
>> +
>> +    out.print("\"");
>> +    out.print(this.getThreadName());
>> +    out.print("\" #");
>> +    out.print(OopUtilities.threadOopGetTID(threadOop));
>> +    if( OopUtilities.threadOopGetDaemon(threadOop) ){
>> +      out.print(" daemon");
>> +    }
>> +    out.print(" prio=");
>> +    out.print(OopUtilities.threadOopGetPriority(threadOop));
>> +    out.print(" tid=");
>> + out.print(String.format("0x%016x",this.getAddress().asLongValue()));
>> +    out.print(" nid=");
>> +    out.print(String.format("0x%x ",this.getOSThread().threadId()));
>> +    out.print(getOSThread().getThreadState().getPrintVal());
>> +    out.print(" [");
>> +    if( this.getLastJavaSP() == null){
>> +      out.print(String.format("0x%016x",0L));
>> +    } else {
>> +      Address maskAddress = this.getLastJavaSP().andWithMask(0xFFF);
>> + 
>> out.print(this.getLastJavaSP().xorWithMask(maskAddress.asLongValue()));
>> +    }
>> +    out.println("]");
>> +    out.print("   java.lang.Thread.State: ");
>> + out.println(OopUtilities.threadOopGetThreadStatusName(threadOop));
>> +    out.print("   JavaThread state: _thread_");
>> + out.println(this.getThreadState().toString().toLowerCase());
>> +  }
>>   }
>> diff --git 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java 
>>
>> --- 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java
>> +++ 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java
>> @@ -1,5 +1,5 @@
>>   /*
>> - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All 
>> rights reserved.
>> + * Copyright (c) 2004, 2017, 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
>> @@ -33,6 +33,19 @@
>>   public class OSThread extends VMObject {
>>       private static JIntField interruptedField;
>>       private static Field threadIdField;
>> +    private static CIntegerField threadStateField;
>> +
>> +    // ThreadStates read from underlying process
>> +    private static int ALLOCATED;
>> +    private static int INITIALIZED;
>> +    private static int RUNNABLE;
>> +    private static int MONITOR_WAIT;
>> +    private static int CONDVAR_WAIT;
>> +    private static int OBJECT_WAIT;
>> +    private static int BREAKPOINTED;
>> +    private static int SLEEPING;
>> +    private static int ZOMBIE;
>> +
>>       static {
>>           VM.registerVMInitializedObserver(new Observer() {
>>               public void update(Observable o, Object data) {
>> @@ -45,6 +58,17 @@
>>           Type type = db.lookupType("OSThread");
>>           interruptedField = type.getJIntField("_interrupted");
>>           threadIdField = type.getField("_thread_id");
>> +        threadStateField = type.getCIntegerField("_state");
>> +
>> +        ALLOCATED = db.lookupIntConstant("ALLOCATED").intValue();
>> +        INITIALIZED = db.lookupIntConstant("INITIALIZED").intValue();
>> +        RUNNABLE = db.lookupIntConstant("RUNNABLE").intValue();
>> +        MONITOR_WAIT = db.lookupIntConstant("MONITOR_WAIT").intValue();
>> +        CONDVAR_WAIT = db.lookupIntConstant("CONDVAR_WAIT").intValue();
>> +        OBJECT_WAIT = db.lookupIntConstant("OBJECT_WAIT").intValue();
>> +        BREAKPOINTED = db.lookupIntConstant("BREAKPOINTED").intValue();
>> +        SLEEPING = db.lookupIntConstant("SLEEPING").intValue();
>> +        ZOMBIE = db.lookupIntConstant("ZOMBIE").intValue();
>>       }
>>
>>       public OSThread(Address addr) {
>> @@ -59,4 +83,28 @@
>>           return threadIdField.getJInt(addr);
>>       }
>>
>> +    public ThreadState getThreadState() {
>> +        int val = (int)threadStateField.getValue(addr);
>> +        if (val ==  ALLOCATED) {
>> +            return ThreadState.ALLOCATED;
>> +        } else if (val ==  INITIALIZED) {
>> +            return ThreadState.INITIALIZED;
>> +        } else if (val ==  RUNNABLE) {
>> +            return ThreadState.RUNNABLE;
>> +        } else if (val ==  MONITOR_WAIT) {
>> +            return ThreadState.MONITOR_WAIT;
>> +        } else if (val ==  CONDVAR_WAIT) {
>> +            return ThreadState.CONDVAR_WAIT;
>> +        } else if (val ==  OBJECT_WAIT) {
>> +            return ThreadState.OBJECT_WAIT;
>> +        } else if (val ==  BREAKPOINTED) {
>> +            return ThreadState.BREAKPOINTED;
>> +        } else if (val ==  SLEEPING) {
>> +            return ThreadState.SLEEPING;
>> +        } else if (val ==  ZOMBIE) {
>> +            return ThreadState.ZOMBIE;
>> +        } else {
>> +            throw new RuntimeException("Illegal thread state " + val);
>> +        }
>> +    }
>>   }
>> diff --git 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java 
>>
>> new file mode 100644
>> --- /dev/null
>> +++ 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java
>> @@ -0,0 +1,60 @@
>> +/*
>> + * Copyright (c) 2017, 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.runtime;
>> +
>> +/** This is a type-safe enum mirroring the ThreadState enum in
>> + osThread.hpp. The conversion between the underlying ints
>> + and these values is done in OSThread. */
>> +
>> +public class ThreadState {
>> +
>> +    private String printVal;
>> +
>> +    /** Memory has been allocated but not initialized */
>> +    public static final ThreadState ALLOCATED = new 
>> ThreadState("allocated");
>> +    /** The thread has been initialized but yet started */
>> +    public static final ThreadState INITIALIZED = new 
>> ThreadState("initialized");
>> +    /** Has been started and is runnable, but not necessarily 
>> running */
>> +    public static final ThreadState RUNNABLE = new 
>> ThreadState("runnable");
>> +    /** Waiting on a contended monitor lock */
>> +    public static final ThreadState MONITOR_WAIT = new 
>> ThreadState("waiting for monitor entry");
>> +    /** Waiting on a condition variable */
>> +    public static final ThreadState CONDVAR_WAIT = new 
>> ThreadState("waiting on condition");
>> +    /** Waiting on an Object.wait() call */
>> +    public static final ThreadState OBJECT_WAIT = new 
>> ThreadState("in Object.wait()");
>> +    /** Suspended at breakpoint */
>> +    public static final ThreadState BREAKPOINTED = new 
>> ThreadState("at breakpoint");
>> +    /** Thread.sleep() */
>> +    public static final ThreadState SLEEPING = new 
>> ThreadState("sleeping");
>> +    /** All done, but not reclaimed yet */
>> +    public static final ThreadState ZOMBIE = new ThreadState("zombie");
>> +
>> +    private ThreadState(String printVal){
>> +        this.printVal = printVal;
>> +    }
>> +
>> +    public String getPrintVal() {
>> +        return printVal;
>> +    }
>> +}
>> diff --git 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
>> --- 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
>> +++ 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
>> @@ -1,5 +1,5 @@
>>   /*
>> - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All 
>> rights reserved.
>> + * Copyright (c) 2003, 2017, 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
>> @@ -88,6 +88,10 @@
>>                  out.print("----------------- ");
>>                  out.print(th);
>>                  out.println(" -----------------");
>> +               JavaThread jthread = (JavaThread) proxyToThread.get(th);
>> +               if (jthread != null) {
>> +                  jthread.printThreadInfoOn(out);
>> +               }
>>                  while (f != null) {
>>                     ClosestSymbol sym = f.closestSymbolToPC();
>>                     Address pc = f.pc();
>> diff --git 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java 
>>
>> --- 
>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
>> +++ 
>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
>> @@ -1,5 +1,5 @@
>>   /*
>> - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All 
>> rights reserved.
>> + * Copyright (c) 2002, 2017, 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
>> @@ -74,14 +74,7 @@
>>               int i = 1;
>>               for (JavaThread cur = threads.first(); cur != null; cur 
>> = cur.next(), i++) {
>>                   if (cur.isJavaThread()) {
>> -                    Address sp = cur.getLastJavaSP();
>> -                    tty.print("Thread ");
>> -                    cur.printThreadIDOn(tty);
>> -                    tty.print(": (state = " + cur.getThreadState());
>> -                    if (verbose) {
>> -                        tty.println(", current Java SP = " + sp);
>> -                    }
>> -                    tty.println(')');
>> +                    cur.printThreadInfoOn(tty);
>>                       try {
>>                           for (JavaVFrame vf = 
>> cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
>>                               Method method = vf.getMethod();
>> diff --git a/src/share/vm/runtime/vmStructs.cpp 
>> b/src/share/vm/runtime/vmStructs.cpp
>> --- a/src/share/vm/runtime/vmStructs.cpp
>> +++ b/src/share/vm/runtime/vmStructs.cpp
>> @@ -981,6 +981,7 @@
>> /************/ \
>> \
>>     volatile_nonstatic_field(OSThread, _interrupted, 
>> jint)                                  \
>> +  volatile_nonstatic_field(OSThread, _state, 
>> ThreadState)                                 \
>> \
>> /************************/ \
>>     /* OopMap and OopMapSet */ \
>> @@ -2186,6 +2187,7 @@
>> declare_integer_type(Generation::Name) \
>> declare_integer_type(InstanceKlass::ClassState) \
>> declare_integer_type(JavaThreadState) \
>> + declare_integer_type(ThreadState) \
>> declare_integer_type(Location::Type) \
>> declare_integer_type(Location::Where) \
>> declare_integer_type(Flag::Flags) \
>> @@ -2443,6 +2445,20 @@
>> declare_constant(JavaThread::_not_terminated) \
>> declare_constant(JavaThread::_thread_exiting) \
>> \
>> + /*******************/ \
>> +  /* JavaThreadState 
>> */                                                   \
>> + /*******************/ \
>> + \
>> + declare_constant(ALLOCATED) \
>> + declare_constant(INITIALIZED) \
>> + declare_constant(RUNNABLE) \
>> + declare_constant(MONITOR_WAIT) \
>> + declare_constant(CONDVAR_WAIT) \
>> + declare_constant(OBJECT_WAIT) \
>> + declare_constant(BREAKPOINTED) \
>> + declare_constant(SLEEPING) \
>> + declare_constant(ZOMBIE) \
>> + \
>> /******************************/ \
>>     /* Klass misc. enum constants 
>> */                                        \
>> /******************************/ \
>> diff --git a/test/serviceability/sa/JhsdbThreadInfoTest.java 
>> b/test/serviceability/sa/JhsdbThreadInfoTest.java
>> new file mode 100644
>> --- /dev/null
>> +++ b/test/serviceability/sa/JhsdbThreadInfoTest.java
>> @@ -0,0 +1,87 @@
>> +/*
>> + * Copyright (c) 2017, 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.
>> + */
>> +
>> +import jdk.test.lib.apps.LingeredApp;
>> +import jdk.test.lib.JDKToolLauncher;
>> +import jdk.test.lib.Platform;
>> +import jdk.test.lib.process.OutputAnalyzer;
>> +import jdk.test.lib.Utils;
>> +
>> +/*
>> + * @test
>> + * @library /test/lib
>> + * @run main JhsdbThreadInfoTest
>> + */
>> +public class JhsdbThreadInfoTest {
>> +
>> +    public static void main(String[] args) throws Exception {
>> +
>> +        if (!Platform.shouldSAAttach()) {
>> +            System.out.println("SA attach not expected to work - 
>> test skipped.");
>> +            return;
>> +        }
>> +
>> +        LingeredApp app = null;
>> +
>> +        try {
>> +            app = LingeredApp.startApp(Utils.getVmOptions());
>> +            System.out.println("Started LingeredApp with pid " + 
>> app.getPid());
>> +
>> +            JDKToolLauncher jhsdbLauncher = 
>> JDKToolLauncher.createUsingTestJDK("jhsdb");
>> +
>> +            jhsdbLauncher.addToolArg("jstack");
>> +            jhsdbLauncher.addToolArg("--pid");
>> + jhsdbLauncher.addToolArg(Long.toString(app.getPid()));
>> +
>> +            ProcessBuilder pb = new ProcessBuilder();
>> +            pb.command(jhsdbLauncher.getCommand());
>> +            Process jhsdb = pb.start();
>> +
>> +            jhsdb.waitFor();
>> +
>> +            OutputAnalyzer out = new OutputAnalyzer(jhsdb);
>> +
>> +            System.out.println(out.getStdout());
>> +            System.err.println(out.getStderr());
>> +
>> +            out.shouldMatch("\".+\" #\\d+ daemon prio=\\d+ 
>> tid=0x[0-9a-f]+ nid=0x[0-9a-f]+ .+ \\[0x[0-9a-f]+]");
>> +            out.shouldMatch("\"main\" #\\d+ prio=\\d+ 
>> tid=0x[0-9a-f]+ nid=0x[0-9a-f]+ .+ \\[0x[0-9a-f]+]");
>> +            out.shouldMatch("   java.lang.Thread.State: .+");
>> +            out.shouldMatch("   JavaThread state: _thread_.+");
>> +
>> +            out.shouldNotContain("   java.lang.Thread.State: UNKNOWN");
>> +            out.stderrShouldBeEmpty();
>> +
>> +            System.out.println("Test Completed");
>> +
>> +
>> +        } catch (InterruptedException ie) {
>> +            throw new Error("Problem awaiting the child process: " + 
>> ie, ie);
>> +        } catch (Exception attachE) {
>> +            throw new Error("Couldn't start jhsdb, attach to 
>> LingeredApp or match ThreadName: " + attachE);
>> +
>> +        } finally {
>> +            LingeredApp.stopApp(app);
>> +        }
>> +    }
>> +}
>>
>>
>>
>>
>> On 2017/06/29 7:40, Yasumasa Suenaga wrote:
>>> Hi chihiro,
>>>
>>> getThreadState() in OSThread.java:
>>>
>>>>> +        } else if (val == BREAKPOINTED) {
>>>>> +            return ThreadState.BREAKPOINTED;
>>>>> +        } else if (val ==  BREAKPOINTED) {
>>>>> +            return ThreadState.BREAKPOINTED;
>>>
>>> These conditions are duplicated.
>>>
>>>
>>> Please upload webrev if you can :-)
>>>
>>>
>>> Yasumasa
>>>
>>>
>>> On 2017/06/29 0:02, chihiro ito wrote:
>>>> Hi all,
>>>>
>>>> In last week, I've posted review request [1].
>>>> Could you possibly review for this following small change? If 
>>>> review is ok, please commit this as cito.
>>>>
>>>> [1] 
>>>> http://mail.openjdk.java.net/pipermail/serviceability-dev/2017-June/021430.html
>>>>
>>>> Thanks,
>>>> Chihiro (Contributer)
>>>>
>>>> On 2017/06/18 13:02, chihiro ito wrote:
>>>>> At first I thought to print just each thread name, but I tried to 
>>>>> make it as similar as possible to JStack as following.
>>>>>
>>>>> Mixed mode:
>>>>> ----------------- 26476 -----------------
>>>>> "main" #1 prio=5 tid=0x00007f6894019000 nid=0x676c waiting on 
>>>>> condition [0x00007f689b7ae000]
>>>>>    java.lang.Thread.State: TIMED_WAITING (sleeping)
>>>>>    JavaThread state: _thread_blocked
>>>>> 0x00007f689b185a82    __pthread_cond_timedwait + 0x132
>>>>>
>>>>> No mixed mode:
>>>>> "main" #1 prio=5 tid=0x00007f6894019000 nid=0x676c waiting on 
>>>>> condition [0x00007f689b7ae000]
>>>>>    java.lang.Thread.State: TIMED_WAITING (sleeping)
>>>>>    JavaThread state: _thread_blocked
>>>>>  - java.lang.Thread.sleep(long) @bci=0 (Interpreted frame)
>>>>>
>>>>>
>>>>> This change passed a test by jtreg.
>>>>>
>>>>> SOURCE_HOME=/home/user/repo/jdk10-hs
>>>>> jtreg -dir:${SOURCE_HOME}/hotspot/test 
>>>>> -testjdk:${SOURCE_HOME}/build/linux-x86_64-normal-server-slowdebug/jdk/ 
>>>>> serviceability/sa/JhsdbThreadInfoTest.java
>>>>> Test results: passed: 1
>>>>>
>>>>>
>>>>> Source:
>>>>> diff --git 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java 
>>>>>
>>>>> --- 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java
>>>>> +++ 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java
>>>>> @@ -1,5 +1,5 @@
>>>>>  /*
>>>>> - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All 
>>>>> rights reserved.
>>>>> + * Copyright (c) 2000, 2017, 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
>>>>> @@ -59,20 +59,20 @@
>>>>>    // parkBlocker field is new since 1.6
>>>>>    private static OopField threadParkBlockerField;
>>>>>
>>>>> +  private static IntField threadPriorityField;
>>>>> +  private static BooleanField threadDaemonField;
>>>>> +
>>>>>    // possible values of java_lang_Thread::ThreadStatus
>>>>>    private static int THREAD_STATUS_NEW;
>>>>> -  /*
>>>>> -    Other enum constants are not needed as of now. Uncomment 
>>>>> these as and when needed.
>>>>>
>>>>> -    private static int THREAD_STATUS_RUNNABLE;
>>>>> -    private static int THREAD_STATUS_SLEEPING;
>>>>> -    private static int THREAD_STATUS_IN_OBJECT_WAIT;
>>>>> -    private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED;
>>>>> -    private static int THREAD_STATUS_PARKED;
>>>>> -    private static int THREAD_STATUS_PARKED_TIMED;
>>>>> -    private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER;
>>>>> -    private static int THREAD_STATUS_TERMINATED;
>>>>> -  */
>>>>> +  private static int THREAD_STATUS_RUNNABLE;
>>>>> +  private static int THREAD_STATUS_SLEEPING;
>>>>> +  private static int THREAD_STATUS_IN_OBJECT_WAIT;
>>>>> +  private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED;
>>>>> +  private static int THREAD_STATUS_PARKED;
>>>>> +  private static int THREAD_STATUS_PARKED_TIMED;
>>>>> +  private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER;
>>>>> +  private static int THREAD_STATUS_TERMINATED;
>>>>>
>>>>>    // java.util.concurrent.locks.AbstractOwnableSynchronizer fields
>>>>>    private static OopField absOwnSyncOwnerThreadField;
>>>>> @@ -229,20 +229,19 @@
>>>>>        threadStatusField = (IntField) k.findField("threadStatus", 
>>>>> "I");
>>>>>        threadParkBlockerField = (OopField) k.findField("parkBlocker",
>>>>> "Ljava/lang/Object;");
>>>>> +      threadPriorityField = (IntField) k.findField("priority", "I");
>>>>> +      threadDaemonField = (BooleanField) k.findField("daemon", "Z");
>>>>>        TypeDataBase db = VM.getVM().getTypeDataBase();
>>>>>        THREAD_STATUS_NEW = 
>>>>> db.lookupIntConstant("java_lang_Thread::NEW").intValue();
>>>>> -      /*
>>>>> -        Other enum constants are not needed as of now. Uncomment 
>>>>> these as and when needed.
>>>>>
>>>>> -        THREAD_STATUS_RUNNABLE = 
>>>>> db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue();
>>>>> -        THREAD_STATUS_SLEEPING = 
>>>>> db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue();
>>>>> -        THREAD_STATUS_IN_OBJECT_WAIT = 
>>>>> db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue();
>>>>> -        THREAD_STATUS_IN_OBJECT_WAIT_TIMED = 
>>>>> db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue();
>>>>> -        THREAD_STATUS_PARKED = 
>>>>> db.lookupIntConstant("java_lang_Thread::PARKED").intValue();
>>>>> -        THREAD_STATUS_PARKED_TIMED = 
>>>>> db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue();
>>>>> -        THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = 
>>>>> db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue();
>>>>> -        THREAD_STATUS_TERMINATED = 
>>>>> db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue();
>>>>> -      */
>>>>> +      THREAD_STATUS_RUNNABLE = 
>>>>> db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue();
>>>>> +      THREAD_STATUS_SLEEPING = 
>>>>> db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue();
>>>>> +      THREAD_STATUS_IN_OBJECT_WAIT = 
>>>>> db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue();
>>>>> +      THREAD_STATUS_IN_OBJECT_WAIT_TIMED = 
>>>>> db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue();
>>>>> +      THREAD_STATUS_PARKED = 
>>>>> db.lookupIntConstant("java_lang_Thread::PARKED").intValue();
>>>>> +      THREAD_STATUS_PARKED_TIMED = 
>>>>> db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue();
>>>>> +      THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = 
>>>>> db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue();
>>>>> +      THREAD_STATUS_TERMINATED = 
>>>>> db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue();
>>>>>
>>>>>        if (Assert.ASSERTS_ENABLED) {
>>>>>          // it is okay to miss threadStatusField, because this was
>>>>> @@ -331,4 +330,46 @@
>>>>>        return absOwnSyncOwnerThreadField.getValue(oop);
>>>>>      }
>>>>>    }
>>>>> +
>>>>> +  public static int threadOopGetPriority(Oop threadOop) {
>>>>> +    initThreadFields();
>>>>> +    if (threadPriorityField != null) {
>>>>> +      return threadPriorityField.getValue(threadOop);
>>>>> +    } else {
>>>>> +      return 0;
>>>>> +    }
>>>>> +  }
>>>>> +
>>>>> +  public static boolean threadOopGetDaemon(Oop threadOop) {
>>>>> +    initThreadFields();
>>>>> +    if (threadDaemonField != null) {
>>>>> +      return threadDaemonField.getValue(threadOop);
>>>>> +    } else {
>>>>> +      return false;
>>>>> +    }
>>>>> +  }
>>>>> +
>>>>> +  public static String threadOopGetThreadStatusName(Oop threadOop) {
>>>>> +    int status = OopUtilities.threadOopGetThreadStatus(threadOop);
>>>>> +    if( status == THREAD_STATUS_NEW ){
>>>>> +      return "NEW";
>>>>> +    }else if(status == THREAD_STATUS_RUNNABLE ){
>>>>> +      return "RUNNABLE";
>>>>> +    }else if(status == THREAD_STATUS_SLEEPING ){
>>>>> +      return "TIMED_WAITING (sleeping)";
>>>>> +    }else if(status == THREAD_STATUS_IN_OBJECT_WAIT ){
>>>>> +      return "WAITING (on object monitor)";
>>>>> +    }else if(status == THREAD_STATUS_IN_OBJECT_WAIT_TIMED ){
>>>>> +      return "TIMED_WAITING (on object monitor)";
>>>>> +    }else if(status == THREAD_STATUS_PARKED ){
>>>>> +      return "WAITING (parking)";
>>>>> +    }else if(status == THREAD_STATUS_PARKED_TIMED ){
>>>>> +      return "TIMED_WAITING (parking)";
>>>>> +    }else if(status == THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER ){
>>>>> +      return "BLOCKED (on object monitor)";
>>>>> +    }else if(status == THREAD_STATUS_TERMINATED ){
>>>>> +      return "TERMINATED";
>>>>> +    }
>>>>> +    return "UNKNOWN";
>>>>> +  }
>>>>>  }
>>>>> diff --git 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java 
>>>>>
>>>>> --- 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
>>>>> +++ 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
>>>>> @@ -475,4 +475,36 @@
>>>>>      return access.getLastSP(addr);
>>>>>    }
>>>>>
>>>>> +
>>>>> +  public void printThreadInfoOn(PrintStream out){
>>>>> +
>>>>> +    Oop threadOop = this.getThreadObj();
>>>>> +
>>>>> +    out.print("\"");
>>>>> +    out.print(this.getThreadName());
>>>>> +    out.print("\" #");
>>>>> +    out.print(OopUtilities.threadOopGetTID(threadOop));
>>>>> +    if( OopUtilities.threadOopGetDaemon(threadOop) ){
>>>>> +      out.print(" daemon");
>>>>> +    }
>>>>> +    out.print(" prio=");
>>>>> + out.print(OopUtilities.threadOopGetPriority(threadOop));
>>>>> +    out.print(" tid=");
>>>>> + 
>>>>> out.print(String.format("0x%016x",this.getAddress().asLongValue()));
>>>>> +    out.print(" nid=");
>>>>> +    out.print(String.format("0x%x ",this.getOSThread().threadId()));
>>>>> + out.print(getOSThread().getThreadState().getPrintVal());
>>>>> +    out.print(" [");
>>>>> +    if( this.getLastJavaSP() == null){
>>>>> +      out.print(String.format("0x%016x",0L));
>>>>> +    } else {
>>>>> +      Address maskAddress = this.getLastJavaSP().andWithMask(0xFFF);
>>>>> + 
>>>>> out.print(this.getLastJavaSP().xorWithMask(maskAddress.asLongValue())); 
>>>>>
>>>>> +    }
>>>>> +    out.println("]");
>>>>> +    out.print("   java.lang.Thread.State: ");
>>>>> + out.println(OopUtilities.threadOopGetThreadStatusName(threadOop));
>>>>> +    out.print("   JavaThread state: _thread_");
>>>>> + out.println(this.getThreadState().toString().toLowerCase());
>>>>> +  }
>>>>>  }
>>>>> diff --git 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java 
>>>>>
>>>>> --- 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java
>>>>> +++ 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java
>>>>> @@ -1,5 +1,5 @@
>>>>>  /*
>>>>> - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All 
>>>>> rights reserved.
>>>>> + * Copyright (c) 2004, 2017, 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
>>>>> @@ -33,6 +33,19 @@
>>>>>  public class OSThread extends VMObject {
>>>>>      private static JIntField interruptedField;
>>>>>      private static Field threadIdField;
>>>>> +    private static CIntegerField threadStateField;
>>>>> +
>>>>> +    // ThreadStates read from underlying process
>>>>> +    private static int ALLOCATED;
>>>>> +    private static int INITIALIZED;
>>>>> +    private static int RUNNABLE;
>>>>> +    private static int MONITOR_WAIT;
>>>>> +    private static int CONDVAR_WAIT;
>>>>> +    private static int OBJECT_WAIT;
>>>>> +    private static int BREAKPOINTED;
>>>>> +    private static int SLEEPING;
>>>>> +    private static int ZOMBIE;
>>>>> +
>>>>>      static {
>>>>>          VM.registerVMInitializedObserver(new Observer() {
>>>>>              public void update(Observable o, Object data) {
>>>>> @@ -45,6 +58,17 @@
>>>>>          Type type = db.lookupType("OSThread");
>>>>>          interruptedField = type.getJIntField("_interrupted");
>>>>>          threadIdField = type.getField("_thread_id");
>>>>> +        threadStateField = type.getCIntegerField("_state");
>>>>> +
>>>>> +        ALLOCATED = db.lookupIntConstant("ALLOCATED").intValue();
>>>>> +        INITIALIZED = 
>>>>> db.lookupIntConstant("INITIALIZED").intValue();
>>>>> +        RUNNABLE = db.lookupIntConstant("RUNNABLE").intValue();
>>>>> +        MONITOR_WAIT = 
>>>>> db.lookupIntConstant("MONITOR_WAIT").intValue();
>>>>> +        CONDVAR_WAIT = 
>>>>> db.lookupIntConstant("CONDVAR_WAIT").intValue();
>>>>> +        OBJECT_WAIT = 
>>>>> db.lookupIntConstant("OBJECT_WAIT").intValue();
>>>>> +        BREAKPOINTED = 
>>>>> db.lookupIntConstant("BREAKPOINTED").intValue();
>>>>> +        SLEEPING = db.lookupIntConstant("SLEEPING").intValue();
>>>>> +        ZOMBIE = db.lookupIntConstant("ZOMBIE").intValue();
>>>>>      }
>>>>>
>>>>>      public OSThread(Address addr) {
>>>>> @@ -59,4 +83,30 @@
>>>>>          return threadIdField.getJInt(addr);
>>>>>      }
>>>>>
>>>>> +    public ThreadState getThreadState() {
>>>>> +        int val = (int)threadStateField.getValue(addr);
>>>>> +        if (val ==  ALLOCATED) {
>>>>> +            return ThreadState.ALLOCATED;
>>>>> +        } else if (val ==  INITIALIZED) {
>>>>> +            return ThreadState.INITIALIZED;
>>>>> +        } else if (val ==  RUNNABLE) {
>>>>> +            return ThreadState.RUNNABLE;
>>>>> +        } else if (val ==  MONITOR_WAIT) {
>>>>> +            return ThreadState.MONITOR_WAIT;
>>>>> +        } else if (val ==  CONDVAR_WAIT) {
>>>>> +            return ThreadState.CONDVAR_WAIT;
>>>>> +        } else if (val ==  OBJECT_WAIT) {
>>>>> +            return ThreadState.OBJECT_WAIT;
>>>>> +        } else if (val ==  BREAKPOINTED) {
>>>>> +            return ThreadState.BREAKPOINTED;
>>>>> +        } else if (val ==  BREAKPOINTED) {
>>>>> +            return ThreadState.BREAKPOINTED;
>>>>> +        } else if (val ==  SLEEPING) {
>>>>> +            return ThreadState.SLEEPING;
>>>>> +        } else if (val ==  ZOMBIE) {
>>>>> +            return ThreadState.ZOMBIE;
>>>>> +        } else {
>>>>> +            throw new RuntimeException("Illegal thread state " + 
>>>>> val);
>>>>> +        }
>>>>> +    }
>>>>>  }
>>>>> diff --git 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java 
>>>>>
>>>>> new file mode 100644
>>>>> --- /dev/null
>>>>> +++ 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java
>>>>> @@ -0,0 +1,60 @@
>>>>> +/*
>>>>> + * Copyright (c) 2017, 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.runtime;
>>>>> +
>>>>> +/** This is a type-safe enum mirroring the ThreadState enum in
>>>>> + osThread.hpp. The conversion between the underlying ints
>>>>> + and these values is done in OSThread. */
>>>>> +
>>>>> +public class ThreadState {
>>>>> +
>>>>> +    private String printVal;
>>>>> +
>>>>> +    /** Memory has been allocated but not initialized */
>>>>> +    public static final ThreadState ALLOCATED = new 
>>>>> ThreadState("allocated");
>>>>> +    /** The thread has been initialized but yet started */
>>>>> +    public static final ThreadState INITIALIZED = new 
>>>>> ThreadState("initialized");
>>>>> +    /** Has been started and is runnable, but not necessarily 
>>>>> running */
>>>>> +    public static final ThreadState RUNNABLE = new 
>>>>> ThreadState("runnable");
>>>>> +    /** Waiting on a contended monitor lock */
>>>>> +    public static final ThreadState MONITOR_WAIT = new 
>>>>> ThreadState("waiting for monitor entry");
>>>>> +    /** Waiting on a condition variable */
>>>>> +    public static final ThreadState CONDVAR_WAIT = new 
>>>>> ThreadState("waiting on condition");
>>>>> +    /** Waiting on an Object.wait() call */
>>>>> +    public static final ThreadState OBJECT_WAIT = new 
>>>>> ThreadState("in Object.wait()");
>>>>> +    /** Suspended at breakpoint */
>>>>> +    public static final ThreadState BREAKPOINTED = new 
>>>>> ThreadState("at breakpoint");
>>>>> +    /** Thread.sleep() */
>>>>> +    public static final ThreadState SLEEPING = new 
>>>>> ThreadState("sleeping");
>>>>> +    /** All done, but not reclaimed yet */
>>>>> +    public static final ThreadState ZOMBIE = new 
>>>>> ThreadState("zombie");
>>>>> +
>>>>> +    private ThreadState(String printVal){
>>>>> +        this.printVal = printVal;
>>>>> +    }
>>>>> +
>>>>> +    public String getPrintVal() {
>>>>> +        return printVal;
>>>>> +    }
>>>>> +}
>>>>> diff --git 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>
>>>>> --- 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>
>>>>> +++ 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>
>>>>> @@ -1,5 +1,5 @@
>>>>>  /*
>>>>> - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All 
>>>>> rights reserved.
>>>>> + * Copyright (c) 2003, 2017, 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
>>>>> @@ -88,6 +88,10 @@
>>>>>                 out.print("----------------- ");
>>>>>                 out.print(th);
>>>>>                 out.println(" -----------------");
>>>>> +               JavaThread jthread = (JavaThread) 
>>>>> proxyToThread.get(th);
>>>>> +               if (jthread != null) {
>>>>> +                  jthread.printThreadInfoOn(out);
>>>>> +               }
>>>>>                 while (f != null) {
>>>>>                    ClosestSymbol sym = f.closestSymbolToPC();
>>>>>                    Address pc = f.pc();
>>>>> diff --git 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java 
>>>>>
>>>>> --- 
>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
>>>>> +++ 
>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
>>>>> @@ -1,5 +1,5 @@
>>>>>  /*
>>>>> - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All 
>>>>> rights reserved.
>>>>> + * Copyright (c) 2002, 2017, 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
>>>>> @@ -74,14 +74,7 @@
>>>>>              int i = 1;
>>>>>              for (JavaThread cur = threads.first(); cur != null; 
>>>>> cur = cur.next(), i++) {
>>>>>                  if (cur.isJavaThread()) {
>>>>> -                    Address sp = cur.getLastJavaSP();
>>>>> -                    tty.print("Thread ");
>>>>> -                    cur.printThreadIDOn(tty);
>>>>> -                    tty.print(": (state = " + cur.getThreadState());
>>>>> -                    if (verbose) {
>>>>> -                        tty.println(", current Java SP = " + sp);
>>>>> -                    }
>>>>> -                    tty.println(')');
>>>>> +                    cur.printThreadInfoOn(tty);
>>>>>                      try {
>>>>>                          for (JavaVFrame vf = 
>>>>> cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
>>>>>                              Method method = vf.getMethod();
>>>>> diff --git a/src/share/vm/runtime/vmStructs.cpp 
>>>>> b/src/share/vm/runtime/vmStructs.cpp
>>>>> --- a/src/share/vm/runtime/vmStructs.cpp
>>>>> +++ b/src/share/vm/runtime/vmStructs.cpp
>>>>> @@ -981,6 +981,7 @@
>>>>> /************/ \
>>>>> \
>>>>>    volatile_nonstatic_field(OSThread, _interrupted, 
>>>>> jint)                                  \
>>>>> +  volatile_nonstatic_field(OSThread, _state, 
>>>>> ThreadState)                                 \
>>>>> \
>>>>> /************************/ \
>>>>>    /* OopMap and OopMapSet */ \
>>>>> @@ -2186,6 +2187,7 @@
>>>>> declare_integer_type(Generation::Name) \
>>>>> declare_integer_type(InstanceKlass::ClassState) \
>>>>> declare_integer_type(JavaThreadState) \
>>>>> + declare_integer_type(ThreadState) \
>>>>> declare_integer_type(Location::Type) \
>>>>> declare_integer_type(Location::Where) \
>>>>> declare_integer_type(Flag::Flags) \
>>>>> @@ -2443,6 +2445,20 @@
>>>>> declare_constant(JavaThread::_not_terminated) \
>>>>> declare_constant(JavaThread::_thread_exiting) \
>>>>> \
>>>>> + /*******************/ \
>>>>> +  /* JavaThreadState 
>>>>> */                                                   \
>>>>> + /*******************/ \
>>>>> + \
>>>>> + declare_constant(ALLOCATED) \
>>>>> + declare_constant(INITIALIZED) \
>>>>> + declare_constant(RUNNABLE) \
>>>>> + declare_constant(MONITOR_WAIT) \
>>>>> + declare_constant(CONDVAR_WAIT) \
>>>>> + declare_constant(OBJECT_WAIT) \
>>>>> + declare_constant(BREAKPOINTED) \
>>>>> + declare_constant(SLEEPING) \
>>>>> + declare_constant(ZOMBIE) \
>>>>> + \
>>>>> /******************************/ \
>>>>>    /* Klass misc. enum constants 
>>>>> */                                        \
>>>>> /******************************/ \
>>>>> diff --git a/test/serviceability/sa/JhsdbThreadInfoTest.java 
>>>>> b/test/serviceability/sa/JhsdbThreadInfoTest.java
>>>>> new file mode 100644
>>>>> --- /dev/null
>>>>> +++ b/test/serviceability/sa/JhsdbThreadInfoTest.java
>>>>> @@ -0,0 +1,87 @@
>>>>> +/*
>>>>> + * Copyright (c) 2017, 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.
>>>>> + */
>>>>> +
>>>>> +import jdk.test.lib.apps.LingeredApp;
>>>>> +import jdk.test.lib.JDKToolLauncher;
>>>>> +import jdk.test.lib.Platform;
>>>>> +import jdk.test.lib.process.OutputAnalyzer;
>>>>> +import jdk.test.lib.Utils;
>>>>> +
>>>>> +/*
>>>>> + * @test
>>>>> + * @library /test/lib
>>>>> + * @run main JhsdbThreadInfoTest
>>>>> + */
>>>>> +public class JhsdbThreadInfoTest {
>>>>> +
>>>>> +    public static void main(String[] args) throws Exception {
>>>>> +
>>>>> +        if (!Platform.shouldSAAttach()) {
>>>>> +            System.out.println("SA attach not expected to work - 
>>>>> test skipped.");
>>>>> +            return;
>>>>> +        }
>>>>> +
>>>>> +        LingeredApp app = null;
>>>>> +
>>>>> +        try {
>>>>> +            app = LingeredApp.startApp(Utils.getVmOptions());
>>>>> +            System.out.println("Started LingeredApp with pid " + 
>>>>> app.getPid());
>>>>> +
>>>>> +            JDKToolLauncher jhsdbLauncher = 
>>>>> JDKToolLauncher.createUsingTestJDK("jhsdb");
>>>>> +
>>>>> +            jhsdbLauncher.addToolArg("jstack");
>>>>> +            jhsdbLauncher.addToolArg("--pid");
>>>>> + jhsdbLauncher.addToolArg(Long.toString(app.getPid()));
>>>>> +
>>>>> +            ProcessBuilder pb = new ProcessBuilder();
>>>>> +            pb.command(jhsdbLauncher.getCommand());
>>>>> +            Process jhsdb = pb.start();
>>>>> +
>>>>> +            jhsdb.waitFor();
>>>>> +
>>>>> +            OutputAnalyzer out = new OutputAnalyzer(jhsdb);
>>>>> +
>>>>> +            System.out.println(out.getStdout());
>>>>> +            System.err.println(out.getStderr());
>>>>> +
>>>>> +            out.shouldMatch("\".+\" #\\d+ daemon prio=\\d+ 
>>>>> tid=0x[0-9a-f]+ nid=0x[0-9a-f]+ .+ \\[0x[0-9a-f]+]");
>>>>> +            out.shouldMatch("\"main\" #\\d+ prio=\\d+ 
>>>>> tid=0x[0-9a-f]+ nid=0x[0-9a-f]+ .+ \\[0x[0-9a-f]+]");
>>>>> +            out.shouldMatch("   java.lang.Thread.State: .+");
>>>>> +            out.shouldMatch("   JavaThread state: _thread_.+");
>>>>> +
>>>>> +            out.shouldNotContain(" java.lang.Thread.State: 
>>>>> UNKNOWN");
>>>>> +            out.stderrShouldBeEmpty();
>>>>> +
>>>>> +            System.out.println("Test Completed");
>>>>> +
>>>>> +
>>>>> +        } catch (InterruptedException ie) {
>>>>> +            throw new Error("Problem awaiting the child process: 
>>>>> " + ie, ie);
>>>>> +        } catch (Exception attachE) {
>>>>> +            throw new Error("Couldn't start jhsdb, attach to 
>>>>> LingeredApp or match ThreadName: " + attachE);
>>>>> +
>>>>> +        } finally {
>>>>> +            LingeredApp.stopApp(app);
>>>>> +        }
>>>>> +    }
>>>>> +}
>>>>>
>>>>>
>>>>> Regards,
>>>>> Chihiro
>>>>>
>>>>>
>>>>> On 2017/06/14 16:51, Bernd Eckenfels wrote:
>>>>>> I don't understand why this format is totally different from the 
>>>>>> normal stack traces? At least the header with the stack names 
>>>>>> could be similar?
>>>>>>
>>>>>> Gruss
>>>>>> Bernd
>>>>>> -- 
>>>>>> https://urldefense.proofpoint.com/v2/url?u=http-3A__bernd.eckenfels.net&d=DwICaQ&c=RoP1YumCXCgaWHvlZYR8PQcxBKCX5YTpkKY057SbK10&r=0SCyhNQIV2jPt0aEruqsRB6bzVcIXHTDh1GkXLV1dyY&m=3QRaQqXxp0PcpNUQsiJOAlmzxeN3O9PyZoFxlIPpsUs&s=KMibjgBgQ9DJ0ddSGSJrvH7PZMz4zGnH-CZml-iRTMM&e= 
>>>>>> ------------------------------------------------------------------------ 
>>>>>>
>>>>>> *From:* serviceability-dev 
>>>>>> <serviceability-dev-bounces at openjdk.java.net> on behalf of 
>>>>>> chihiro ito <chihiro.ito at oracle.com>
>>>>>> *Sent:* Wednesday, June 14, 2017 9:17:42 AM
>>>>>> *To:* Jini George; serviceability-dev at openjdk.java.net
>>>>>> *Subject:* Re: [10] RFR 8181647: jhsdb jstack could not output 
>>>>>> thread name
>>>>>> Hi all,
>>>>>>
>>>>>> I added a test case and modified previous patch including fix the
>>>>>> copyright year to 2017.
>>>>>> I changed to output Java thread name next the separator lines in 
>>>>>> "jhsdb
>>>>>> jstack --mixed" case as following.
>>>>>>
>>>>>> ----------------- 32117 -----------------
>>>>>> "main"
>>>>>> 0x00007f6c8feafa82    __pthread_cond_timedwait + 0x132
>>>>>>
>>>>>> Could you possibly review for this following small change? If 
>>>>>> review is
>>>>>> ok, please commit this as cito.
>>>>>>
>>>>>>
>>>>>> Source:
>>>>>> diff --git
>>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>>
>>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>>
>>>>>> --- 
>>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>>
>>>>>> +++ 
>>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>>
>>>>>> @@ -1,5 +1,5 @@
>>>>>>   /*
>>>>>> - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All 
>>>>>> rights
>>>>>> reserved.
>>>>>> + * Copyright (c) 2003, 2017, 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
>>>>>> @@ -88,6 +88,12 @@
>>>>>>                  out.print("----------------- ");
>>>>>>                  out.print(th);
>>>>>>                  out.println(" -----------------");
>>>>>> +               JavaThread jthread = (JavaThread) 
>>>>>> proxyToThread.get(th);
>>>>>> +               if (jthread != null) {
>>>>>> +                   out.print("\"");
>>>>>> +                   out.print(jthread.getThreadName());
>>>>>> +                   out.println("\"");
>>>>>> +               }
>>>>>>                  while (f != null) {
>>>>>>                     ClosestSymbol sym = f.closestSymbolToPC();
>>>>>>                     Address pc = f.pc();
>>>>>> diff --git
>>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java 
>>>>>>
>>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java 
>>>>>>
>>>>>> ---
>>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java 
>>>>>>
>>>>>> +++
>>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java 
>>>>>>
>>>>>> @@ -1,5 +1,5 @@
>>>>>>   /*
>>>>>> - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All 
>>>>>> rights
>>>>>> reserved.
>>>>>> + * Copyright (c) 2002, 2017, 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
>>>>>> @@ -75,7 +75,9 @@
>>>>>>               for (JavaThread cur = threads.first(); cur != null; 
>>>>>> cur =
>>>>>> cur.next(), i++) {
>>>>>>                   if (cur.isJavaThread()) {
>>>>>>                       Address sp = cur.getLastJavaSP();
>>>>>> -                    tty.print("Thread ");
>>>>>> +                    tty.print("\"");
>>>>>> +                    tty.print(cur.getThreadName());
>>>>>> +                    tty.print("\" nid=");
>>>>>>                       cur.printThreadIDOn(tty);
>>>>>>                       tty.print(": (state = " + 
>>>>>> cur.getThreadState());
>>>>>>                       if (verbose) {
>>>>>> diff --git a/test/serviceability/sa/JhsdbThreadNameTest.java
>>>>>> b/test/serviceability/sa/JhsdbThreadNameTest.java
>>>>>> new file mode 100644
>>>>>> --- /dev/null
>>>>>> +++ b/test/serviceability/sa/JhsdbThreadNameTest.java
>>>>>> @@ -0,0 +1,107 @@
>>>>>> +/*
>>>>>> + * Copyright (c) 2017, 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 <http://www.oracle.com> if you need 
>>>>>> additional information or have any
>>>>>> + * questions.
>>>>>> + */
>>>>>> +
>>>>>> +import java.util.ArrayList;
>>>>>> +import java.util.Arrays;
>>>>>> +import java.util.List;
>>>>>> +import java.util.function.Consumer;
>>>>>> +
>>>>>> +import jdk.test.lib.apps.LingeredApp;
>>>>>> +import jdk.test.lib.JDKToolLauncher;
>>>>>> +import jdk.test.lib.Platform;
>>>>>> +import jdk.test.lib.process.OutputAnalyzer;
>>>>>> +import jdk.test.lib.Utils;
>>>>>> +
>>>>>> +/*
>>>>>> + * @test
>>>>>> + * @library /test/lib
>>>>>> + * @run main/othervm JhsdbThreadNameTest
>>>>>> + */
>>>>>> +public class JhsdbThreadNameTest {
>>>>>> +
>>>>>> +    private static String notMixedModeThreadNames[] =
>>>>>> {"Common-Cleaner", "Signal Dispatcher", "Finalizer", "Reference
>>>>>> Handler", "main"};
>>>>>> +    private static String mixedModeThreadNames[] = {"C2
>>>>>> CompilerThread0", "C1 CompilerThread1", "Sweeper thread", 
>>>>>> "Service Thread"};
>>>>>> +
>>>>>> +    private static void startHsdbJstack(boolean mixed) throws 
>>>>>> Exception {
>>>>>> +
>>>>>> +        LingeredApp app = null;
>>>>>> +
>>>>>> +        try {
>>>>>> +            List<String> vmArgs = new ArrayList<String>();
>>>>>> +            vmArgs.add("-Xmx10m");
>>>>>> +            vmArgs.addAll(Utils.getVmOptions());
>>>>>> +
>>>>>> +            app = LingeredApp.startApp(vmArgs);
>>>>>> +            System.out.println("Started LingeredApp with pid " +
>>>>>> app.getPid());
>>>>>> +
>>>>>> +            JDKToolLauncher jhsdbLauncher =
>>>>>> JDKToolLauncher.createUsingTestJDK("jhsdb");
>>>>>> +
>>>>>> +            jhsdbLauncher.addToolArg("jstack");
>>>>>> +            jhsdbLauncher.addToolArg("--pid");
>>>>>> + jhsdbLauncher.addToolArg(Long.toString(app.getPid()));
>>>>>> +
>>>>>> +            if (mixed) {
>>>>>> +                jhsdbLauncher.addToolArg("--mixed");
>>>>>> +            }
>>>>>> +            ProcessBuilder pb = new ProcessBuilder();
>>>>>> +            pb.command(jhsdbLauncher.getCommand());
>>>>>> +            Process jhsdb = pb.start();
>>>>>> +
>>>>>> +            jhsdb.waitFor();
>>>>>> +
>>>>>> +            OutputAnalyzer out = new OutputAnalyzer(jhsdb);
>>>>>> +
>>>>>> +
>>>>>> Arrays.stream(notMixedModeThreadNames).map(JhsdbThreadNameTest::addQuotationMarks).forEach(out::shouldContain); 
>>>>>>
>>>>>> +            Consumer<String> testMethod = null;
>>>>>> +            if (mixed) {
>>>>>> +                testMethod = out::shouldContain;
>>>>>> +            } else {
>>>>>> +                testMethod = out::shouldNotContain;
>>>>>> +            }
>>>>>> +
>>>>>> Arrays.stream(mixedModeThreadNames).map(JhsdbThreadNameTest::addQuotationMarks).forEach(testMethod); 
>>>>>>
>>>>>> +
>>>>>> +        } catch (InterruptedException ie) {
>>>>>> +            throw new Error("Problem awaiting the child process: 
>>>>>> " +
>>>>>> ie, ie);
>>>>>> +        } catch (Exception attachE) {
>>>>>> +            throw new Error("Couldn't start jhsdb, attach to
>>>>>> LingeredApp or match ThreadName: " + attachE);
>>>>>> +
>>>>>> +        } finally {
>>>>>> +            LingeredApp.stopApp(app);
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    private static String addQuotationMarks(String str) {
>>>>>> +        return "\"" + str + "\"";
>>>>>> +    }
>>>>>> +
>>>>>> +    public static void main(String[] args) throws Exception {
>>>>>> +
>>>>>> +        if (!Platform.shouldSAAttach()) {
>>>>>> +            System.out.println("SA attach not expected to work - 
>>>>>> test
>>>>>> skipped.");
>>>>>> +            return;
>>>>>> +        }
>>>>>> +
>>>>>> +        startHsdbJstack(true);
>>>>>> +        startHsdbJstack(false);
>>>>>> +    }
>>>>>> +}
>>>>>>
>>>>>>
>>>>>> Regards,
>>>>>> Chihiro
>>>>>>
>>>>>>
>>>>>> On 2017/06/08 18:04, chihiro ito wrote:
>>>>>> > Hi Jini,
>>>>>> >
>>>>>> > Thank you for your advices. I try to add the test case and 
>>>>>> modify the
>>>>>> > copyright year to 2017.
>>>>>> > Basically, I agree with your idea, but I think that the 
>>>>>> separator line
>>>>>> > should finally be the same as the output of the jstack command. I
>>>>>> > worry which is better way.
>>>>>> >
>>>>>> > Thanks,
>>>>>> > Chihiro
>>>>>> >
>>>>>> > On 2017/06/08 16:42, Jini George wrote:
>>>>>> >> Hi Chihiro,
>>>>>> >>
>>>>>> >> Thank you for making this useful change. Your changes look good.
>>>>>> >>
>>>>>> >> It would be great though if you could add a test case for 
>>>>>> this. Could
>>>>>> >> you also modify the copyright year to 2017 ? One additional
>>>>>> >> suggestion: The addition of the thread name makes the 
>>>>>> separator lines
>>>>>> >> unaligned in the pstack/jstack --mixed cases. Like:
>>>>>> >>
>>>>>> >> ----------------- "Service Thread" nid=16051 -----------------
>>>>>> >> and
>>>>>> >> ----------------- nid=16052 -----------------
>>>>>> >>
>>>>>> >> So I am wondering if it would make sense to have the name 
>>>>>> printed out
>>>>>> >> on a separate line to keep the separator lines aligned. But 
>>>>>> this is a
>>>>>> >> nit, and I would leave it to you to decide on this.
>>>>>> >>
>>>>>> >> Thanks,
>>>>>> >> Jini (Not a (R)eviewer)
>>>>>> >>
>>>>>> >> On 6/7/2017 3:16 PM, chihiro ito wrote:
>>>>>> >>> Hi all,
>>>>>> >>>
>>>>>> >>> I changed to output Java thread name in jhsdb jstack as 
>>>>>> following.
>>>>>> >>>
>>>>>> >>> jhsdb jstack --pid 25879
>>>>>> >>> "main" nid=25884: (state = BLOCKED)
>>>>>> >>>
>>>>>> >>> jhsdb jstack --mixed --pid 25879
>>>>>> >>> ----------------- "main" nid=25884 -----------------
>>>>>> >>>
>>>>>> >>> Could you possibly review for this following small change? If 
>>>>>> review
>>>>>> >>> is ok, please commit this as cito.
>>>>>> >>>
>>>>>> >>> Source:
>>>>>> >>> diff --git
>>>>>> >>> 
>>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>>
>>>>>> >>> 
>>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>>
>>>>>> >>> ---
>>>>>> >>> 
>>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>>
>>>>>> >>> +++
>>>>>> >>> 
>>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java 
>>>>>>
>>>>>> >>> @@ -86,6 +86,13 @@
>>>>>> >>>              try {
>>>>>> >>>                 CFrame f = cdbg.topFrameForThread(th);
>>>>>> >>> out.print("----------------- ");
>>>>>> >>> +               JavaThread jthread = (JavaThread)
>>>>>> >>> proxyToThread.get(th);
>>>>>> >>> +               if (jthread != null) {
>>>>>> >>> +                   out.print("\"");
>>>>>> >>> + out.print(jthread.getThreadName());
>>>>>> >>> +                   out.print("\" ");
>>>>>> >>> +               }
>>>>>> >>> +               out.print("nid=");
>>>>>> >>>                 out.print(th);
>>>>>> >>>                 out.println(" -----------------");
>>>>>> >>>                 while (f != null) {
>>>>>> >>> diff --git
>>>>>> >>> 
>>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
>>>>>> >>> 
>>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
>>>>>> >>>
>>>>>> >>> ---
>>>>>> >>> 
>>>>>> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
>>>>>> >>> +++
>>>>>> >>> 
>>>>>> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java
>>>>>> >>> @@ -75,7 +75,9 @@
>>>>>> >>>              for (JavaThread cur = threads.first(); cur != 
>>>>>> null; cur
>>>>>> >>> = cur.next(), i++) {
>>>>>> >>>                  if (cur.isJavaThread()) {
>>>>>> >>>                      Address sp = cur.getLastJavaSP();
>>>>>> >>> -                    tty.print("Thread ");
>>>>>> >>> +                    tty.print("\"");
>>>>>> >>> + tty.print(cur.getThreadName());
>>>>>> >>> +                    tty.print("\" nid=");
>>>>>> >>> cur.printThreadIDOn(tty);
>>>>>> >>>                      tty.print(": (state = " + 
>>>>>> cur.getThreadState());
>>>>>> >>>                      if (verbose) {
>>>>>> >>>
>>>>>> >>> Regards,
>>>>>> >>> Chihiro
>>>>>> >>>
>>>>>> >>
>>>>>> >
>>>>>>
>>>>>
>>>>
>>

-- 

Chihiro Ito | Principal Consultant | +81.90.6148.8815
Oracle <http://www.oracle.com> Consultant
ORACLE Japan | Akasaka Center Bldg. | Motoakasaka 1-3-13 | 1070051 
Minato-ku, Tokyo, JAPAN

Oracle is committed to developing practices and products that help 
protect the environment <http://www.oracle.com/commitment>


More information about the serviceability-dev mailing list