java - 以编程方式触发完整的堆栈转储?

标签 java jvm signals stack-trace

当我向我的 java 进程发送 SIGQUIT 命令(使用 kill -3 或 kill -QUIT )时,它会将所有堆栈的踪迹打印到 stderr,以及有关持有的锁和死锁检测的信息。我能以某种方式从程序内部触发吗?我想在每次某个操作花费太长时间时自动执行此操作。

我知道可以获取堆栈跟踪(请参阅 Is there a way to dump a stack trace without throwing an exception in java?Thread dump programmatically /JDI (Java Debugger Interface))。但我想看到所有的一切:堆栈跟踪、线程状态、持有的锁、阻塞的锁、死锁检测等,即我发送 SIGQUIT 时得到的一切;不仅仅是堆栈跟踪。

最佳答案

是的,你可以。我一直在使用这段代码成功地调试随机触发的并发错误:

package utils.stack;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.management.ManagementFactory;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.function.Supplier;
import javax.management.JMX;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

public interface DiagnosticCommand {
    String threadPrint(String... args);

    DiagnosticCommand local = ((Supplier<DiagnosticCommand>) () -> {
        try {
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            ObjectName name = new ObjectName("com.sun.management", 
                "type", "DiagnosticCommand");
            return JMX.newMBeanProxy(server, name, DiagnosticCommand.class);
        } catch(MalformedObjectNameException e) {
            throw new AssertionError(e);
        }
    }).get();

    static void dump() {
        String print = local.threadPrint();
        Path path = Paths.get(LocalDateTime.now() + ".dump.txt");
        try {
            byte[] bytes = print.getBytes("ASCII");
            Files.write(path, bytes);
        } catch(IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}

它需要 Java 8 和 HotSpot 作为 JVM,因为它模仿 jstack 正在做的事情,除了在同一进程中。

关于java - 以编程方式触发完整的堆栈转储?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12965836/

相关文章:

c++ - 带信号的 Scanf

c - 自动附加到 SEGV 和其他致命信号(panic_action)上的进程

java - 如何计算最短路径?

java - 这里需要显式解码吗?

java - 我想打印 hi GrandFather;但它似乎打印 hi Father

garbage-collection - 如何从 GC 日志文件中找到应用程序挂起时间

java - JSF中模型和 Controller 的区别

java - API 上的 GET 调用出现 403 状态

clojure - 在 clojure leinengen 项目中需要命名空间

Android:在电话中操纵语音