ThreadDumpAction.java
package emissary.server.mvc;
import emissary.util.Version;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.glassfish.jersey.server.mvc.Template;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
@Path("")
// context is emissary
public class ThreadDumpAction {
@GET
@Path("/Threaddump.action")
@Produces(MediaType.TEXT_HTML)
@Template(name = "/threaddumps")
public Map<String, Object> getThreaddumps() {
ThreadMXBean tmbean = ManagementFactory.getThreadMXBean();
Map<String, Object> model = new HashMap<>();
model.put("emissary.version", new Version());
model.put("java.version", System.getProperty("java.vm.version"));
model.put("java.name", System.getProperty("java.vm.name"));
Map<String, Object> threadcount = new HashMap<>();
threadcount.put("current", tmbean.getThreadCount());
threadcount.put("max", tmbean.getPeakThreadCount());
threadcount.put("daemon", tmbean.getDaemonThreadCount());
model.put("threadcount", threadcount);
Set<ThreadDumpInfo> deadlocks = new HashSet<>();
long[] tids = tmbean.findMonitorDeadlockedThreads();
if (tids != null) {
for (ThreadInfo ti : tmbean.getThreadInfo(tids, Integer.MAX_VALUE)) {
deadlocks.add(new ThreadDumpInfo(ti));
}
}
model.put("deadlocks", deadlocks);
Set<ThreadDumpInfo> threads = new HashSet<>();
for (ThreadInfo ti : tmbean.getThreadInfo(tmbean.getAllThreadIds(), Integer.MAX_VALUE)) {
threads.add(new ThreadDumpInfo(ti));
}
model.put("threads", threads);
return model;
}
public static class ThreadDumpInfo {
public String stack;
public ThreadDumpInfo(@Nullable ThreadInfo ti) {
StringBuilder sb = new StringBuilder();
if (ti == null) {
sb.append("A null thread?");
} else {
sb.append("\"").append(ti.getThreadName()).append("\" tid=").append(ti.getThreadId()).append("\n");
sb.append(" thread state ").append(ti.getThreadState()); // no new line
if (ti.getLockName() != null) {
sb.append(" (on ").append(ti.getLockName()).append(" owned by ").append(ti.getLockOwnerId()).append(")\n");
}
if (ti.isSuspended()) {
sb.append(" SUSPENDED\n");
}
if (ti.isInNative()) {
sb.append(" IN NATIVE CODE\n");
}
for (StackTraceElement ste : ti.getStackTrace()) {
sb.append(" ").append(ste.toString()).append("\n");
}
}
stack = sb.toString();
}
}
}