5

我知道以下用于在 java 中生成线程转储的方法:

  • 杀死 -3
  • 堆栈
  • 来自 JVM 内部的 JMX
  • JMX 远程
  • JPDA(远程)
  • JVMTI (C API)

在这些方法中,哪种方法对 JVM 的性能影响最小?

4

2 回答 2

8

如果您只需要将所有堆栈跟踪转储到stdoutkill -3并且jstack应该是最便宜的。该功能在 JVM 代码中本地实现。没有创建中间结构——VM 在遍历堆栈时会自行打印所有内容。

这两个命令执行相同的 VM 操作,除了信号处理程序在本地将堆栈跟踪打印到Java 进程的标准输出jstack,同时通过 IPC( Linux 上的Unix 域套接字或Windows上的命名管道)接收来自目标 VM 的输出。

jstack在引擎盖下使用动态附加机制。如果您希望将堆栈跟踪作为纯字节流接收,您也可以直接使用动态附加。

import com.sun.tools.attach.VirtualMachine;
import sun.tools.attach.HotSpotVirtualMachine;
import java.io.InputStream;

public class StackTrace {

    public static void main(String[] args) throws Exception {
        String pid = args[0];
        HotSpotVirtualMachine vm = (HotSpotVirtualMachine) VirtualMachine.attach(pid);

        try (InputStream in = vm.remoteDataDump()) {
            byte[] buf = new byte[8000];
            for (int bytes; (bytes = in.read(buf)) > 0; ) {
                System.out.write(buf, 0, bytes);
            }
        } finally {
            vm.detach();
        }
    }
}

请注意,所有提到的方法无论如何都在 VM 安全点中运行。这意味着在收集堆栈跟踪时所有 Java 线程都将停止。

于 2014-11-07T21:54:41.377 回答
0

性能最高的选项可能是使用 ThreadMXBean.dumpAllThreads() API,而不是请求写入磁盘的文本线程转储:http: //docs.oracle.com/javase/7/docs/api/java/lang /management/ThreadMXBean.html#dumpAllThreads(boolean,%20boolean)

当然,是否可以使用取决于您是否需要线程转储文件,或者只是数据。

于 2014-11-07T11:51:30.203 回答