[10] RFR 8181647: jhsdb jstack could not output thread name
chihiro ito
chihiro.ito at oracle.com
Wed Jun 28 15:02:11 UTC 2017
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>
>
--
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