我知道以下用于在 java 中生成线程转储的方法:
- 杀死 -3
- 堆栈
- 来自 JVM 内部的 JMX
- JMX 远程
- JPDA(远程)
- JVMTI (C API)
在这些方法中,哪种方法对 JVM 的性能影响最小?
我知道以下用于在 java 中生成线程转储的方法:
在这些方法中,哪种方法对 JVM 的性能影响最小?
如果您只需要将所有堆栈跟踪转储到stdout,kill -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 线程都将停止。
性能最高的选项可能是使用 ThreadMXBean.dumpAllThreads() API,而不是请求写入磁盘的文本线程转储:http: //docs.oracle.com/javase/7/docs/api/java/lang /management/ThreadMXBean.html#dumpAllThreads(boolean,%20boolean)
当然,是否可以使用取决于您是否需要线程转储文件,或者只是数据。