【问题标题】:Which method is the least obtrusive for generating thread dumps in java?哪种方法在 java 中生成线程转储最不显眼?
【发布时间】:2015-01-03 21:50:30
【问题描述】:

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

  • 杀死-3
  • jstack
  • JVM 内部的 JMX
  • JMX 远程
  • JPDA(远程)
  • JVMTI (C API)

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

【问题讨论】:

    标签: performance jvm thread-dump


    【解决方案1】:

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

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

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

    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 线程都将停止。

    【讨论】:

      【解决方案2】:

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

      当然,能否使用取决于你需要线程转储文件,还是只需要数据。

      【讨论】:

      • 这实际上是最糟糕的选择。堆栈跟踪ThreadInfo[] 的 Java-land 表示需要大量堆内存,并且需要大量时间来构建和打印。
      猜你喜欢
      • 1970-01-01
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-04
      • 2019-10-12
      • 2011-07-04
      相关资源
      最近更新 更多