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

Poonam Parhar poonam.bajaj at oracle.com
Wed Jul 5 18:23:20 UTC 2017


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.java

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
> >>>>>>>>> >>>
> >>>>>>>>> >>
> >>>>>>>>> >
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>
> >>>>>
> >>>
> >


More information about the serviceability-dev mailing list