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

Yasumasa Suenaga yasuenag at gmail.com
Wed Jun 28 22:40:47 UTC 2017


Hi chihiro,

getThreadState() in OSThread.java:

>> +        } else if (val ==  BREAKPOINTED) {
>> +            return ThreadState.BREAKPOINTED;
>> +        } else if (val ==  BREAKPOINTED) {
>> +            return ThreadState.BREAKPOINTED;

These conditions are duplicated.


Please upload webrev if you can :-)


Yasumasa


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


More information about the serviceability-dev mailing list