Hello Chihiro, The updated webrev looks good!
Thanks, Poonam > -----Original Message----- > From: chihiro ito > Sent: Wednesday, July 05, 2017 12:58 PM > To: Poonam Parhar; Yasumasa Suenaga > Cc: serviceability-dev@openjdk.java.net > Subject: Re: [10] RFR 8181647: jhsdb jstack could not output thread > name > > Hello Poonam, > > Thank you for reviewing. > > I applyed your advices. The webrev is following. > > http://cr.openjdk.java.net/~dbuck/8181647.1/ > > Could you review, please? > > Regards, > Chihiro > > On 2017/07/06 3:23, Poonam Parhar wrote: > > Hello Chihiro, > > > > The changes in the following webrev look good to me: > > http://cr.openjdk.java.net/~dbuck/8181647.0/ > > > > A few minor suggestions though: > > > > - > src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.j > ava > > > > Lines 354 - 370: > > Extra whitespace in the if conditions can be removed: > > if( status == THREAD_STATUS_NEW ){ > > to > > if(status == THREAD_STATUS_NEW){ > > > > please do this for all the 'if' statements. > > > > - share/classes/sun/jvm/hotspot/runtime/JavaThread.java. > > Line 482: extra line; can be removed > > Line 507: not indented properly > > > > Thanks, > > Poonam > > > > > >> -----Original Message----- > >> From: Yasumasa Suenaga [mailto:yasue...@gmail.com] > >> Sent: Tuesday, July 04, 2017 3:44 PM > >> To: chihiro ito > >> Cc: serviceability-dev@openjdk.java.net > >> Subject: Re: [10] RFR 8181647: jhsdb jstack could not output thread > >> name > >> > >> Hi Chihiro, > >> > >> It looks good to me. > >> However, I cannot be a sponsor because I cannot access JPRT. The > >> change(s) for HotSpot should be pushed via JPRT. > >> > >> Please find a sponsor for this change. > >> (Of course, you can list me as a reviewer (ysuenaga)) > >> > >> > >> Thanks, > >> > >> Yasumasa > >> > >> > >> On 2017/07/05 2:17, chihiro ito wrote: > >>> 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").intV > >> alue(); > >>> - 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").intV > >> alue(); > >>> + 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/JavaThrea > >> d.java > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.java > >>> --- > >> > a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.java > >>> +++ > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.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/ThreadSta > >> te.java > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadSta > >> te.java > >>> new file mode 100644 > >>> --- /dev/null > >>> +++ > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadSta > >> te.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").intV > >> alue(); > >>>>> - 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").intV > >> alue(); > >>>>> + 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/JavaThrea > >> d.java > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.java > >>>>> --- > >> > a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.java > >>>>> +++ > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.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/ThreadSta > >> te.java > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadSta > >> te.java > >>>>> new file mode 100644 > >>>>> --- /dev/null > >>>>> +++ > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadSta > >> te.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").intV > >> alue(); > >>>>>>> - 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").intV > >> alue(); > >>>>>>> + 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/JavaThrea > >> d.java > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.java > >>>>>>> --- > >> > a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.java > >>>>>>> +++ > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.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/ThreadSta > >> te.java > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadSta > >> te.java > >>>>>>> new file mode 100644 > >>>>>>> --- /dev/null > >>>>>>> +++ > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadSta > >> te.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").intV > >> alue(); > >>>>>>>>>> - 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").intV > >> alue(); > >>>>>>>>>> + 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/JavaThrea > >> d.java > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.java > >>>>>>>>>> --- > >> > a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.java > >>>>>>>>>> +++ > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThrea > >> d.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/ThreadSta > >> te.java > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadSta > >> te.java > >>>>>>>>>> new file mode 100644 > >>>>>>>>>> --- /dev/null > >>>>>>>>>> +++ > >> > b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadSta > >> te.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=RoP1YumCXCgaWHvlZYR8PQcxBKCX5YTpkKY0 > >> > 57SbK10&r=0SCyhNQIV2jPt0aEruqsRB6bzVcIXHTDh1GkXLV1dyY&m=3QRaQqXxp0PcpNU > >> QsiJOAlmzxeN3O9PyZoFxlIPpsUs&s=KMibjgBgQ9DJ0ddSGSJrvH7PZMz4zGnH- > CZml- > >> iRTMM&e= ----------------------------------------------------------- > --- > >> ---------- > >>>>>>>>>>> *From:* serviceability-dev <serviceability-dev- > >> boun...@openjdk.java.net> on behalf of chihiro ito > >> <chihiro....@oracle.com> > >>>>>>>>>>> *Sent:* Wednesday, June 14, 2017 9:17:42 AM > >>>>>>>>>>> *To:* Jini George; serviceability-dev@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::addQuot > >> ationMarks).forEach(out::shouldContain); > >>>>>>>>>>> + Consumer<String> testMethod = null; > >>>>>>>>>>> + if (mixed) { > >>>>>>>>>>> + testMethod = out::shouldContain; > >>>>>>>>>>> + } else { > >>>>>>>>>>> + testMethod = out::shouldNotContain; > >>>>>>>>>>> + } > >>>>>>>>>>> + > >>>>>>>>>>> > >> > Arrays.stream(mixedModeThreadNames).map(JhsdbThreadNameTest::addQuotati > >> onMarks).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 @Oracle Consulting