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

Poonam Parhar poonam.bajaj at oracle.com
Wed Jul 5 20:05:33 UTC 2017


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 at 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:yasuenag at gmail.com]
> >> Sent: Tuesday, July 04, 2017 3:44 PM
> >> To: chihiro ito
> >> Cc: serviceability-dev at 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-
> >> bounces at openjdk.java.net> on behalf of chihiro ito
> >> <chihiro.ito at oracle.com>
> >>>>>>>>>>> *Sent:* Wednesday, June 14, 2017 9:17:42 AM
> >>>>>>>>>>> *To:* Jini George; serviceability-dev at openjdk.java.net
> >>>>>>>>>>> *Subject:* Re: [10] RFR 8181647: jhsdb jstack could not
> >> output thread name
> >>>>>>>>>>> Hi all,
> >>>>>>>>>>>
> >>>>>>>>>>> I added a test case and modified previous patch including
> fix
> >> the
> >>>>>>>>>>> copyright year to 2017.
> >>>>>>>>>>> I changed to output Java thread name next the separator
> lines
> >> in "jhsdb
> >>>>>>>>>>> jstack --mixed" case as following.
> >>>>>>>>>>>
> >>>>>>>>>>> ----------------- 32117 -----------------
> >>>>>>>>>>> "main"
> >>>>>>>>>>> 0x00007f6c8feafa82    __pthread_cond_timedwait + 0x132
> >>>>>>>>>>>
> >>>>>>>>>>> Could you possibly review for this following small change?
> If
> >> review is
> >>>>>>>>>>> ok, please commit this as cito.
> >>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>> Source:
> >>>>>>>>>>> diff --git
> >>>>>>>>>>>
> >>
> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
> >>
> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
> >>>>>>>>>>> ---
> >>
> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
> >>>>>>>>>>> +++
> >>
> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
> >>>>>>>>>>> @@ -1,5 +1,5 @@
> >>>>>>>>>>>    /*
> >>>>>>>>>>> - * Copyright (c) 2003, 2013, Oracle and/or its affiliates.
> >> All rights
> >>>>>>>>>>> reserved.
> >>>>>>>>>>> + * Copyright (c) 2003, 2017, Oracle and/or its affiliates.
> >> All rights
> >>>>>>>>>>> reserved.
> >>>>>>>>>>>     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE
> >> HEADER.
> >>>>>>>>>>>     *
> >>>>>>>>>>>     * This code is free software; you can redistribute it
> >> and/or modify it
> >>>>>>>>>>> @@ -88,6 +88,12 @@
> >>>>>>>>>>>                   out.print("----------------- ");
> >>>>>>>>>>>                   out.print(th);
> >>>>>>>>>>>                   out.println(" -----------------");
> >>>>>>>>>>> +               JavaThread jthread = (JavaThread)
> >> proxyToThread.get(th);
> >>>>>>>>>>> +               if (jthread != null) {
> >>>>>>>>>>> +                   out.print("\"");
> >>>>>>>>>>> + out.print(jthread.getThreadName());
> >>>>>>>>>>> +                   out.println("\"");
> >>>>>>>>>>> +               }
> >>>>>>>>>>>                   while (f != null) {
> >>>>>>>>>>>                      ClosestSymbol sym =
> >> f.closestSymbolToPC();
> >>>>>>>>>>>                      Address pc = f.pc();
> >>>>>>>>>>> diff --git
> >>>>>>>>>>>
> >>
> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.
> >> java
> >>
> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.
> >> java
> >>>>>>>>>>> ---
> >>>>>>>>>>>
> >>
> a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.
> >> java
> >>>>>>>>>>> +++
> >>>>>>>>>>>
> >>
> b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.
> >> java
> >>>>>>>>>>> @@ -1,5 +1,5 @@
> >>>>>>>>>>>    /*
> >>>>>>>>>>> - * Copyright (c) 2002, 2013, Oracle and/or its affiliates.
> >> All rights
> >>>>>>>>>>> reserved.
> >>>>>>>>>>> + * Copyright (c) 2002, 2017, Oracle and/or its affiliates.
> >> All rights
> >>>>>>>>>>> reserved.
> >>>>>>>>>>>     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE
> >> HEADER.
> >>>>>>>>>>>     *
> >>>>>>>>>>>     * This code is free software; you can redistribute it
> >> and/or modify it
> >>>>>>>>>>> @@ -75,7 +75,9 @@
> >>>>>>>>>>>                for (JavaThread cur = threads.first(); cur
> !=
> >> null; cur =
> >>>>>>>>>>> cur.next(), i++) {
> >>>>>>>>>>>                    if (cur.isJavaThread()) {
> >>>>>>>>>>>                        Address sp = cur.getLastJavaSP();
> >>>>>>>>>>> -                    tty.print("Thread ");
> >>>>>>>>>>> +                    tty.print("\"");
> >>>>>>>>>>> +                    tty.print(cur.getThreadName());
> >>>>>>>>>>> +                    tty.print("\" nid=");
> >>>>>>>>>>>                        cur.printThreadIDOn(tty);
> >>>>>>>>>>>                        tty.print(": (state = " +
> >> cur.getThreadState());
> >>>>>>>>>>>                        if (verbose) {
> >>>>>>>>>>> diff --git
> a/test/serviceability/sa/JhsdbThreadNameTest.java
> >>>>>>>>>>> b/test/serviceability/sa/JhsdbThreadNameTest.java
> >>>>>>>>>>> new file mode 100644
> >>>>>>>>>>> --- /dev/null
> >>>>>>>>>>> +++ b/test/serviceability/sa/JhsdbThreadNameTest.java
> >>>>>>>>>>> @@ -0,0 +1,107 @@
> >>>>>>>>>>> +/*
> >>>>>>>>>>> + * Copyright (c) 2017, Oracle and/or its affiliates. All
> >> rights reserved.
> >>>>>>>>>>> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE
> >> HEADER.
> >>>>>>>>>>> + *
> >>>>>>>>>>> + * This code is free software; you can redistribute it
> >> and/or modify it
> >>>>>>>>>>> + * under the terms of the GNU General Public License
> version
> >> 2 only, as
> >>>>>>>>>>> + * published by the Free Software Foundation.
> >>>>>>>>>>> + *
> >>>>>>>>>>> + * This code is distributed in the hope that it will be
> >> useful, but WITHOUT
> >>>>>>>>>>> + * ANY WARRANTY; without even the implied warranty of
> >> MERCHANTABILITY or
> >>>>>>>>>>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
> >> Public License
> >>>>>>>>>>> + * version 2 for more details (a copy is included in the
> >> LICENSE file that
> >>>>>>>>>>> + * accompanied this code).
> >>>>>>>>>>> + *
> >>>>>>>>>>> + * You should have received a copy of the GNU General
> Public
> >> License
> >>>>>>>>>>> version
> >>>>>>>>>>> + * 2 along with this work; if not, write to the Free
> >> Software Foundation,
> >>>>>>>>>>> + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-
> 1301
> >> USA.
> >>>>>>>>>>> + *
> >>>>>>>>>>> + * Please contact Oracle, 500 Oracle Parkway, Redwood
> >> Shores, CA 94065 USA
> >>>>>>>>>>> + * or visit www.oracle.com <http://www.oracle.com> if you
> >> need additional information or have any
> >>>>>>>>>>> + * questions.
> >>>>>>>>>>> + */
> >>>>>>>>>>> +
> >>>>>>>>>>> +import java.util.ArrayList;
> >>>>>>>>>>> +import java.util.Arrays;
> >>>>>>>>>>> +import java.util.List;
> >>>>>>>>>>> +import java.util.function.Consumer;
> >>>>>>>>>>> +
> >>>>>>>>>>> +import jdk.test.lib.apps.LingeredApp;
> >>>>>>>>>>> +import jdk.test.lib.JDKToolLauncher;
> >>>>>>>>>>> +import jdk.test.lib.Platform;
> >>>>>>>>>>> +import jdk.test.lib.process.OutputAnalyzer;
> >>>>>>>>>>> +import jdk.test.lib.Utils;
> >>>>>>>>>>> +
> >>>>>>>>>>> +/*
> >>>>>>>>>>> + * @test
> >>>>>>>>>>> + * @library /test/lib
> >>>>>>>>>>> + * @run main/othervm JhsdbThreadNameTest
> >>>>>>>>>>> + */
> >>>>>>>>>>> +public class JhsdbThreadNameTest {
> >>>>>>>>>>> +
> >>>>>>>>>>> +    private static String notMixedModeThreadNames[] =
> >>>>>>>>>>> {"Common-Cleaner", "Signal Dispatcher", "Finalizer",
> >> "Reference
> >>>>>>>>>>> Handler", "main"};
> >>>>>>>>>>> +    private static String mixedModeThreadNames[] = {"C2
> >>>>>>>>>>> CompilerThread0", "C1 CompilerThread1", "Sweeper thread",
> >> "Service Thread"};
> >>>>>>>>>>> +
> >>>>>>>>>>> +    private static void startHsdbJstack(boolean mixed)
> >> throws Exception {
> >>>>>>>>>>> +
> >>>>>>>>>>> +        LingeredApp app = null;
> >>>>>>>>>>> +
> >>>>>>>>>>> +        try {
> >>>>>>>>>>> +            List<String> vmArgs = new ArrayList<String>();
> >>>>>>>>>>> +            vmArgs.add("-Xmx10m");
> >>>>>>>>>>> +            vmArgs.addAll(Utils.getVmOptions());
> >>>>>>>>>>> +
> >>>>>>>>>>> +            app = LingeredApp.startApp(vmArgs);
> >>>>>>>>>>> +            System.out.println("Started LingeredApp with
> pid
> >> " +
> >>>>>>>>>>> app.getPid());
> >>>>>>>>>>> +
> >>>>>>>>>>> +            JDKToolLauncher jhsdbLauncher =
> >>>>>>>>>>> JDKToolLauncher.createUsingTestJDK("jhsdb");
> >>>>>>>>>>> +
> >>>>>>>>>>> +            jhsdbLauncher.addToolArg("jstack");
> >>>>>>>>>>> +            jhsdbLauncher.addToolArg("--pid");
> >>>>>>>>>>> + jhsdbLauncher.addToolArg(Long.toString(app.getPid()));
> >>>>>>>>>>> +
> >>>>>>>>>>> +            if (mixed) {
> >>>>>>>>>>> + jhsdbLauncher.addToolArg("--mixed");
> >>>>>>>>>>> +            }
> >>>>>>>>>>> +            ProcessBuilder pb = new ProcessBuilder();
> >>>>>>>>>>> +            pb.command(jhsdbLauncher.getCommand());
> >>>>>>>>>>> +            Process jhsdb = pb.start();
> >>>>>>>>>>> +
> >>>>>>>>>>> +            jhsdb.waitFor();
> >>>>>>>>>>> +
> >>>>>>>>>>> +            OutputAnalyzer out = new
> OutputAnalyzer(jhsdb);
> >>>>>>>>>>> +
> >>>>>>>>>>> +
> >>>>>>>>>>>
> >>
> Arrays.stream(notMixedModeThreadNames).map(JhsdbThreadNameTest::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


More information about the serviceability-dev mailing list