以编程方式触发完整堆栈转储? [英] Trigger complete stack dump programmatically?
问题描述
当我向我的java进程发送SIGQUIT命令(使用kill -3或kill -QUIT)时,它会向stderr打印所有堆栈的跟踪,包含有关锁的信息和死锁检测。我能以某种方式从程序内部触发这个吗?我希望每次某个操作都花费太长时间时自动执行此操作。
When I send a SIGQUIT command to my java process (using kill -3 or kill -QUIT ), it prints a trace of all stacks to stderr, with information about locks held, and deadlock detection. Can I trigger this from inside the program somehow? I want to do this automatically every time a certain operation takes too long.
我知道可以获得堆栈跟踪(参见有没有办法在不丢弃的情况下转储堆栈跟踪java中的一个例外?,以编程方式进行线程转储/ JDI(Java Debugger)接口))。但是我希望看到所有的东西:堆栈跟踪,线程状态,持有的锁,阻塞锁,死锁检测等,即我发送SIGQUIT时得到的一切;不只是堆栈跟踪。
I know it's possible to get a stack trace (see Is there a way to dump a stack trace without throwing an exception in java?, Thread dump programmatically /JDI (Java Debugger Interface)). But I want to see the whole everything: stack traces, thread states, locks held, locks blocked on, deadlock detection, etc., i.e. everything I get when I sent a SIGQUIT; not just the stack trace.
推荐答案
是的,你可以。我一直在成功使用这段代码来调试随机触发的并发错误:
Yes you can. I've been using this code successfully to debug randomly triggered concurrency bugs:
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正在做的事情,除了在同一个过程中。
It requires Java 8 and HotSpot as the JVM as it mimics what jstack is doing, except from within the same process.
这篇关于以编程方式触发完整堆栈转储?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!