jstack在服务器上无法工作

18

我们在服务器上使用jstack来检测Java应用程序是否被死锁。但是它在我们的一个Linux服务器上无法正常工作。我认为操作系统版本是:

$cat /etc/issue.net
Red Hat Enterprise Linux Server release 5.6 (Tikanga)
Kernel \r on an \m

服务器上运行的 Java 版本:

java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode)

当我尝试:

jstack 19114

我得到:

19114: Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding

当我尝试时:

jstack -F 19114

我得到:

Attaching to process ID 19114, please wait...
Debugger attached successfully.

Deadlock Detection:

No deadlocks found.

Thread 19180: (state = BLOCKED)
Error occurred during stack walking:
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
        at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.execute(LinuxDebuggerLocal.java:152)
        at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet(LinuxDebuggerLocal.java:466)
        at sun.jvm.hotspot.debugger.linux.LinuxThread.getContext(LinuxThread.java:65)
        at sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess.getCurrentFrameGuess(LinuxAMD64JavaThreadPDAccess.java:92)
        at sun.jvm.hotspot.runtime.JavaThread.getCurrentFrameGuess(JavaThread.java:256)
        at sun.jvm.hotspot.runtime.JavaThread.getLastJavaVFrameDbg(JavaThread.java:218)
        at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:76)
        at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:45)
        at sun.jvm.hotspot.tools.JStack.run(JStack.java:60)
        at sun.jvm.hotspot.tools.Tool.start(Tool.java:221)
        at sun.jvm.hotspot.tools.JStack.main(JStack.java:86)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at sun.tools.jstack.JStack.runJStackTool(JStack.java:118)
        at sun.tools.jstack.JStack.main(JStack.java:84)
Caused by: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
        at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet0(Native Method)
        at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.access$800(LinuxDebuggerLocal.java:51)
        at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$1GetThreadIntegerRegisterSetTask.doit(LinuxDebuggerLocal.java:460)
        at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.run(LinuxDebuggerLocal.java:127)

有人知道是什么原因导致这个问题吗?

4个回答

20

4
语法很简单:

sudo -u USERID jstack PID

例子:

sudo -u tomcat7 jstack 2498

是的 - 我现在经常使用这种语法。 - Sam Goldberg

3
尝试使用kill -3 <pid>来获取您的虚拟机的堆栈跟踪。

如果我们想要获取一个普通的线程转储,我们可以这样做。然而,jstack会解析线程转储以找出是否存在任何死锁。你可以从普通的线程转储中看到死锁,但如果有很多线程,那么找到问题就更加困难。Jstack速度更快。 - Sam Goldberg
1
我理解您的观点,我的建议是最后的解决方案,这比从jstack中得不到任何结果更好。 - Emmanuel Bourg
1
谢谢,Emmanuel。IBM有一个很好的GUI工具,ftp://public.dhe.ibm.com/software/websphere/appserv/support/tools/jca/jca423.zip,它可以为您解析线程转储,并识别死锁和其他线程特性。昨天当我们无法让jstack工作时,我们使用了这种方法。再次感谢您的建议。 - Sam Goldberg
这可能是针对Linux的特定内容。但所有好的应用程序都不应该只在Windows上吧? :) - tgkprog

2

可以使用类似输出的jsp代替。

以下jsp将线程堆栈信息打印到屏幕上,但您也可以将输出更改为文件,或在常规POJO类中使用。

<%@ page import="java.util.*" %><%
    Map<Thread,StackTraceElement[]> map = Thread.getAllStackTraces();
    Set tt = map.keySet();
    Iterator<Thread> ti = tt.iterator();
    Thread thrd = null;
    final String br = "<" + "br" + ">";//website does not parse it
    try{
        
        int cnt = 1;
        StackTraceElement[] st = null;
        while(ti.hasNext() ){
            thrd = ti.next();
            out.print(br + "<" + "hr" + ">" + br + cnt + " \"" + thrd.getName());
            out.println("\", priority :" + thrd.getPriority()  + ", state :" + thrd.getState());
            
            out.print(", id :" + thrd.getId() + ", hex :" +  Long.toHexString(thrd.getId()) );
            out.print(" alive :"  + thrd.isAlive() + ", daemon :" + thrd.isDaemon() );
            out.print(" interrupted  :"  + thrd.isInterrupted() + ", daemon :" + thrd.isDaemon() );
            out.print(".\n" + br);
            st = thrd.getStackTrace();
            for(int sti = 0; sti < st.length; sti++){
                out.println(br + " &nbsp; &nbsp; " + st[sti].getClassName() + "." + st[sti].getMethodName());
                out.println("(" + st[sti].getFileName());
                if(st[sti].getLineNumber() < 1){
                    out.print("Native method");
                }else{
                    out.print(":" + st[sti].getLineNumber());
                }
                out.println(")");
            }
            
            out.println("");
            cnt++;
        }
    }catch(Exception e){
        out.println(br + "err " + e + br);
    }
    



%>

样例输出:

121 "Thread-40",优先级:6,状态:等待,ID:134,十六进制:86,存活:true,守护线程:false,被中断:false,守护线程:false。

java.lang.Object.wait (Object.java 原生方法)
java.lang.Object.wait (Object.java :485)
org.jpos.iso.ISOMUX$Receiver.run (ISOMUX.java :326)
java.lang.Thread.run (Thread.java :662)

122 "Thread-48",优先级:5,状态:定时等待,ID:142,十六进制:8e,存活:true,守护线程:false,被中断:false,守护线程:false。

java.lang.Thread.sleep (Thread.java 原生方法)
org.jpos.apps.qsp.QSP.monitorConfigFile (QSP.java :301)
org.jpos.apps.qsp.QSP.run (QSP.java :346)
java.lang.Thread.run (Thread.java :662)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接