|
|
@@ -1,74 +1,45 @@
|
|
|
package com.x.server.console.action;
|
|
|
|
|
|
-import java.io.File;
|
|
|
-import java.lang.Thread.State;
|
|
|
-import java.util.Comparator;
|
|
|
+import java.lang.management.ManagementFactory;
|
|
|
+import java.lang.management.RuntimeMXBean;
|
|
|
+import java.nio.file.Path;
|
|
|
import java.util.Date;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Map.Entry;
|
|
|
+
|
|
|
+import org.apache.commons.lang3.SystemUtils;
|
|
|
|
|
|
import com.x.base.core.project.config.Config;
|
|
|
import com.x.base.core.project.logger.Logger;
|
|
|
import com.x.base.core.project.logger.LoggerFactory;
|
|
|
import com.x.base.core.project.tools.DateTools;
|
|
|
-import com.x.base.core.project.tools.DefaultCharset;
|
|
|
-
|
|
|
-import org.apache.commons.io.FileUtils;
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
-import org.apache.commons.lang3.ThreadUtils;
|
|
|
|
|
|
public class ThreadDump {
|
|
|
|
|
|
- private static Logger logger = LoggerFactory.getLogger(DumpData.class);
|
|
|
+ private static Logger logger = LoggerFactory.getLogger(ThreadDump.class);
|
|
|
|
|
|
public void execute(Integer count) throws Exception {
|
|
|
new Thread() {
|
|
|
public void run() {
|
|
|
try {
|
|
|
- Map<Long, Integer> state_new = new HashMap<>();
|
|
|
- Map<Long, Integer> state_runable = new HashMap<>();
|
|
|
- Map<Long, Integer> state_blocked = new HashMap<>();
|
|
|
- Map<Long, Integer> state_waiting = new HashMap<>();
|
|
|
- Map<Long, Integer> state_timed_waiting = new HashMap<>();
|
|
|
- Map<Long, Integer> state_terminated = new HashMap<>();
|
|
|
- File startFile = null;
|
|
|
- for (int i = 1; i <= count; i++) {
|
|
|
- Date date = new Date();
|
|
|
- StringBuffer buffer = new StringBuffer();
|
|
|
- for (Thread thread : ThreadUtils.getAllThreads()) {
|
|
|
- state(thread, state_new, state_runable, state_blocked, state_waiting,
|
|
|
- state_timed_waiting, state_terminated);
|
|
|
- dump(buffer, thread);
|
|
|
- }
|
|
|
- File file = new File(Config.dir_logs(true), fileName(i, count, date));
|
|
|
- if (i == 1) {
|
|
|
- startFile = file;
|
|
|
- }
|
|
|
- if (i != count) {
|
|
|
- FileUtils.write(file, buffer, DefaultCharset.charset_utf_8);
|
|
|
- logger.print(String.format("thread dump to file(%d/%d): %s.", i, count,
|
|
|
- file.getAbsolutePath()));
|
|
|
- Thread.sleep(5000);
|
|
|
+ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
|
|
|
+ String jvmName = runtimeBean.getName();
|
|
|
+ long pid = Long.parseLong(jvmName.split("@")[0]);
|
|
|
+ Path path = SystemUtils.getJavaHome().toPath();
|
|
|
+ path = path.getParent().resolve("bin/jcmd").toAbsolutePath();
|
|
|
+ for (int i = 0; i < count; i++) {
|
|
|
+ Path out = Config.dir_logs(true).toPath()
|
|
|
+ .resolve("jcmd_Thread.print_" + pid + "_"
|
|
|
+ + DateTools.format(new Date(), DateTools.formatCompact_yyyyMMddHHmmss) + ".txt")
|
|
|
+ .toAbsolutePath();
|
|
|
+ String cmd = path.toString() + " " + pid + " Thread.print >" + out.toString();
|
|
|
+ ProcessBuilder processBuilder = new ProcessBuilder();
|
|
|
+ if (SystemUtils.IS_OS_WINDOWS) {
|
|
|
+ processBuilder.command("cmd", "/c", cmd);
|
|
|
} else {
|
|
|
- buffer.append(System.lineSeparator()).append("Thread state statistics:");
|
|
|
- buffer.append(" NEW(" + state_new.size() + "),");
|
|
|
- buffer.append(" RUNABLE(" + state_runable.size() + "),");
|
|
|
- buffer.append(" blocked(" + state_blocked.size() + "),");
|
|
|
- buffer.append(" waiting(" + state_waiting.size() + "),");
|
|
|
- buffer.append(" timed_waiting(" + state_timed_waiting.size() + "),");
|
|
|
- buffer.append(" terminated(" + state_terminated.size() + ").");
|
|
|
- buffer.append(System.lineSeparator());
|
|
|
- writeState(buffer, state_new, State.NEW, count);
|
|
|
- writeState(buffer, state_runable, State.RUNNABLE, count);
|
|
|
- writeState(buffer, state_blocked, State.BLOCKED, count);
|
|
|
- writeState(buffer, state_waiting, State.WAITING, count);
|
|
|
- writeState(buffer, state_timed_waiting, State.TIMED_WAITING, count);
|
|
|
- writeState(buffer, state_terminated, State.TERMINATED, count);
|
|
|
- FileUtils.write(file, buffer, DefaultCharset.charset_utf_8);
|
|
|
- logger.print(String.format("thread dump to files: %s - %s.",
|
|
|
- startFile.getAbsolutePath(), file.getAbsolutePath()));
|
|
|
+ processBuilder.command("sh", "-c", cmd);
|
|
|
}
|
|
|
+ processBuilder.start();
|
|
|
+ logger.print("thread dump to file:{}.", out.toString());
|
|
|
+ Thread.sleep(1000);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
@@ -76,68 +47,4 @@ public class ThreadDump {
|
|
|
}
|
|
|
}.start();
|
|
|
}
|
|
|
-
|
|
|
- private void writeState(StringBuffer buffer, Map<Long, Integer> map, State state, Integer count) {
|
|
|
- buffer.append(state).append(", count:").append(map.size()).append(".").append(System.lineSeparator());
|
|
|
- map.entrySet().stream().sorted(Comparator.comparing(Entry::getValue, Comparator.reverseOrder())).forEach(o -> {
|
|
|
- buffer.append("\t\t").append(o.getKey()).append(":").append(o.getValue()).append("/").append(count)
|
|
|
- .append(System.lineSeparator());
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- private void state(Thread thread, Map<Long, Integer> state_new, Map<Long, Integer> state_runable,
|
|
|
- Map<Long, Integer> state_blocked, Map<Long, Integer> state_waiting, Map<Long, Integer> state_timed_waiting,
|
|
|
- Map<Long, Integer> state_terminated) {
|
|
|
- Map<Long, Integer> state;
|
|
|
- switch (thread.getState()) {
|
|
|
- case NEW:
|
|
|
- state = state_new;
|
|
|
- break;
|
|
|
- case RUNNABLE:
|
|
|
- state = state_runable;
|
|
|
- break;
|
|
|
- case BLOCKED:
|
|
|
- state = state_blocked;
|
|
|
- break;
|
|
|
- case WAITING:
|
|
|
- state = state_waiting;
|
|
|
- break;
|
|
|
- case TIMED_WAITING:
|
|
|
- state = state_timed_waiting;
|
|
|
- break;
|
|
|
- case TERMINATED:
|
|
|
- state = state_terminated;
|
|
|
- break;
|
|
|
- default:
|
|
|
- state = state_terminated;
|
|
|
- break;
|
|
|
- }
|
|
|
- state.compute(thread.getId(), (k, v) -> {
|
|
|
- if (null == v) {
|
|
|
- return 1;
|
|
|
- }
|
|
|
- return v + 1;
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- private void dump(StringBuffer buffer, Thread thread) {
|
|
|
- this.title(buffer, thread);
|
|
|
- for (StackTraceElement stackTrace : thread.getStackTrace()) {
|
|
|
- this.stackTrace(buffer, stackTrace);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void title(StringBuffer buffer, Thread thread) {
|
|
|
- buffer.append(String.format("id:%s, state:%s, threadGroup:%s, priority:%d.", thread.getId(), thread.getState(),
|
|
|
- thread.getThreadGroup(), thread.getPriority())).append(System.lineSeparator());
|
|
|
- }
|
|
|
-
|
|
|
- private void stackTrace(StringBuffer buffer, StackTraceElement stackTraceElement) {
|
|
|
- buffer.append("\t\t").append(stackTraceElement.toString()).append(System.lineSeparator());
|
|
|
- }
|
|
|
-
|
|
|
- private String fileName(int idx, int count, Date date) {
|
|
|
- return "stack_" + DateTools.format(date, "yyyyMMddHHmmssSSS") + "_"
|
|
|
- + StringUtils.repeat('0', ((count + "").length()) - ((idx + "").length())) + idx + "_" + count + ".txt";
|
|
|
- }
|
|
|
}
|