如何在heroku上为Java进程生成线程转储?
我希望能够为运行在heroku上的java应用程序生成java线程转储?我看到heroku正在运行jstack,但我不知道如何运行它在我的进程上生成线程转储。我不知道如何将PID发送到jstack。一旦我有了PID,我只需从我的开发机器上运行“heroku jstack-l”(它安装了toolbelt)?您可以尝试以下操作-将此函数放在某个类中,并有方法调用它,将输出保存到文件或在页面上显示它如何在heroku上为Java进程生成线程转储?,java,heroku,Java,Heroku,我希望能够为运行在heroku上的java应用程序生成java线程转储?我看到heroku正在运行jstack,但我不知道如何运行它在我的进程上生成线程转储。我不知道如何将PID发送到jstack。一旦我有了PID,我只需从我的开发机器上运行“heroku jstack-l”(它安装了toolbelt)?您可以尝试以下操作-将此函数放在某个类中,并有方法调用它,将输出保存到文件或在页面上显示它 static StringBuilder allStack() { StringBuilder
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;
}
静态StringBuilder allStack(){
StringBuilder sb=新的StringBuilder();
Map trace=Thread.getAllStackTraces();
对于(线程t:trace.keySet()){
StackTraceElement[]trc=trace.get(t);
某人附加(“\n”);
sb.append(t.getName());
某人加上(“”);
sb.append(t.getId());
某人加上(“|”);
sb.append(t.getThreadGroup());
某人加上(“|”);
某人附加(t);
sb.追加(“:-\n”);
用于(StackTraceElement e:trc){
某人附加(如toString());
某人附加(“\n”);
}
sb.追加(“-***-\n”);
}
归还某人;
}
您可以尝试以下操作-将此函数放入某个类中,并有方法调用它,将输出保存到文件或在页面上显示它
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;
}
静态StringBuilder allStack(){
StringBuilder sb=新的StringBuilder();
Map trace=Thread.getAllStackTraces();
对于(线程t:trace.keySet()){
StackTraceElement[]trc=trace.get(t);
某人附加(“\n”);
sb.append(t.getName());
某人加上(“”);
sb.append(t.getId());
某人加上(“|”);
sb.append(t.getThreadGroup());
某人加上(“|”);
某人附加(t);
sb.追加(“:-\n”);
用于(StackTraceElement e:trc){
某人附加(如toString());
某人附加(“\n”);
}
sb.追加(“-***-\n”);
}
归还某人;
}
好的,下面是最好的方法。这将为您提供JVM使用的格式,而不必以编程方式重新创建它。同样,这是为了heroku,其他环境将需要调整此代码。这将其公开为rest接口
@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 );
}
好的,这是最好的方法。这将为您提供JVM使用的格式,而不必以编程方式重新创建它。同样,这是为了heroku,其他环境将需要调整此代码。这将其公开为rest接口
@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 );
}
您也可以考虑将REST API嵌入到java JMX中来执行这个线程转储。约洛基亚似乎是个不错的候选人。它还将支持内置身份验证,并且更加灵活,因为您可以访问任何JMX mbean,而无需实现新的REST端点
看尤其是使用调用方法的REST协议,您也可以考虑将REST API嵌入到java JMX中来执行这个线程转储。约洛基亚似乎是个不错的候选人。它还将支持内置身份验证,并且更加灵活,因为您可以访问任何JMX mbean,而无需实现新的REST端点 看
特别是使用调用方法的REST协议。谢谢,我知道怎么做。但我不想以编程的方式来做。我想在控制台上做。因此,对于在Heroku dyno上运行的web服务器,我想从本地机器生成一个线程转储。不知道。如果进程被挂起,它将更强大。为什么不在你的主人那里买张票呢?谢谢,我知道怎么做。但我不想以编程的方式来做。我想在控制台上做。因此,对于在Heroku dyno上运行的web服务器,我想从本地机器生成一个线程转储。不知道。如果进程被挂起,它将更强大。为什么不在您的主机中通过票证提问?是org.springframework.util.StreamUtils吗?什么是响应类型?为什么不将输出写入文件?只是好奇。我理解kill-3部分,但想知道为什么你会选择这种方法来获得回复。我想把它写在我的书面记录中,我也想让它像Ctrl-Break一样回复。我真的不想把它归档。我不确定我是否理解你关于回复类型的问题。在StreamUtils上,您还可以使用Guava CharStreams.toString(in)并将其发送到函数public Response threadDump()中的LOG或System.out{,这个响应类的全名是什么?我不熟悉。所以这会将结果打印到应用程序系统中?哦,我只是在使用JAX-RS Jersey。这是他们拥有的一个响应类。是org.springframework.util.StreamUtils吗?响应类型是什么?为什么不将输出写入文件?只是好奇。我理解kill-3的b部分我想知道你为什么选择这种方法来获取回复。我希望它出现在我的书面记录中,我也希望它能像Ctrl-Break一样响应。我不希望它出现在文件中。我不确定我是否理解你关于回复类型的问题。在StreamUtils上,你也可以使用Guava CharStreams.toString(in)在你的函数中,public Response threadDump()抛出异常{,这个响应类的全名是什么?我不太熟悉。所以这会将结果打印到应用程序系统输出?哦,我只是在使用JAX-RS Jersey。这是他们的响应类。