【发布时间】:2014-03-07 19:15:00
【问题描述】:
我希望能够为运行在 heroku 上的 Java 应用程序生成 Java 线程转储?我看到 heroku 正在运行 jstack,但我不知道如何运行它以在我的进程上生成线程转储。我不知道如何让 PID 发送到 jstack。一旦我有了 PID,我只需从我的开发机器上运行“heroku jstack -l”(它安装了工具带)?
【问题讨论】:
我希望能够为运行在 heroku 上的 Java 应用程序生成 Java 线程转储?我看到 heroku 正在运行 jstack,但我不知道如何运行它以在我的进程上生成线程转储。我不知道如何让 PID 发送到 jstack。一旦我有了 PID,我只需从我的开发机器上运行“heroku jstack -l”(它安装了工具带)?
【问题讨论】:
好的,这是最好的方法。这将为您提供 JVM 使用的格式,而不必以编程方式重新创建它。同样,这是针对 heroku 的,其他环境需要调整此代码。这会将其公开为一个休息接口。
@GET
@Transactional
@Path( "/threaddump" )
public Response threadDump() throws Exception {
dumpThreads();
return Response.ok().build();
}
public static void dumpThreads() throws Exception {
ProcessBuilder processBuilder = new ProcessBuilder( "/bin/sh", "-c", "kill -3 $PPID" );
processBuilder.redirectErrorStream( true );
Process process = processBuilder.start();
InputStream inputStream = process.getInputStream();
StreamUtils.copy( inputStream, System.out );
}
【讨论】:
您可以尝试以下操作 - 将此函数放在某个类中并有办法调用它,将输出保存到文件或在页面上显示...
static StringBuilder allStack() {
StringBuilder sb = new StringBuilder();
Map<Thread, StackTraceElement[]> trace = Thread.getAllStackTraces();
for(Thread t:trace.keySet()){
StackTraceElement[]trc = trace.get(t);
sb.append("\n");
sb.append(t.getName());
sb.append(" ");
sb.append(t.getId());
sb.append(" |");
sb.append(t.getThreadGroup());
sb.append("| ");
sb.append(t);
sb.append(" :-\n");
for(StackTraceElement e:trc){
sb.append(e.toString());
sb.append("\n");
}
sb.append(" -***-\n");
}
return sb;
}
【讨论】:
您还可以考虑将 REST API 嵌入到 java JMX 以执行此线程转储。 Jolokia 似乎是一个不错的候选人。它还将支持内置身份验证并且更加灵活,因为您可以访问任何 JMX mbean 而无需实现新的 REST 端点
看 http://www.jolokia.org,特别是使用POST Exec request调用ThreadMXBean.dumpAllThreads()方法的REST协议
【讨论】: