[10] RFR 8181647: jhsdb jstack could not output thread name
chihiro ito
chihiro.ito at oracle.com
Tue Jul 4 17:17:38 UTC 2017
Hi Yasumasa,
Thank you for reviewing.
I modified these following source code that you commented.
> + 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));
Based on your advice, I have modified as following. Could you possibly
review for this code ?
+ private static final String ADDRESS_FORMAT = VM.getVM().isLP64() ?
"0x%016x" : "0x%08x";
+ out.print(this.getAddress());
+ 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(ADDRESS_FORMAT,0L));
Regards,
Chihiro
hg diff -g is following.
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
@@ -70,6 +70,8 @@
private static int NOT_TERMINATED;
private static int EXITING;
+ private static final String ADDRESS_FORMAT = VM.getVM().isLP64() ?
"0x%016x" : "0x%08x";
+
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
@@ -475,4 +477,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(this.getAddress());
+ 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(ADDRESS_FORMAT,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/04 23:44, Yasumasa Suenaga wrote:
> Hi Chihiro,
>
> Thank you for updating your patch!
> I have a comment to printThreadInfoOn() in JavaThread.java:
>
>> + 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));
>
> You set "0x%016x" to format string for address value.
> However, this length is changed by pointer length e.g. "0x%08x" should
> be set on ILP32 platforms.
>
> In case of Linux, Address#toString() generates platform-aware string
> value in DebuggerUtilities#addressValueToString(). So you can use
> Address#toString() if Address is not null.
>
>
> Yasumasa
>
>
> On 2017/07/04 0:32, chihiro ito wrote:
>> 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