diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/ThreadModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/ThreadModel.java index 57e72903a00..ae4d8044604 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/ThreadModel.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/ThreadModel.java @@ -25,6 +25,8 @@ public class ThreadModel extends ResultModel { private Map threadStateCount; private boolean all; + private int stacktraceMax; + public ThreadModel() { } @@ -98,4 +100,19 @@ public boolean isAll() { public void setAll(boolean all) { this.all = all; } + + /** + * @return int return the stacktraceMax + */ + public int getStacktraceMax() { + return stacktraceMax; + } + + /** + * @param stacktraceMax the stacktraceMax to set + */ + public void setStacktraceMax(int stacktraceMax) { + this.stacktraceMax = stacktraceMax; + } + } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/ThreadCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/ThreadCommand.java index 2ef0db2383e..047cb9813b6 100755 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/ThreadCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/ThreadCommand.java @@ -57,6 +57,7 @@ public class ThreadCommand extends AnnotatedCommand { private boolean lockedMonitors = false; private boolean lockedSynchronizers = false; private boolean all = false; + private int stacktraceMax; static { states = new HashSet(State.values().length); @@ -71,6 +72,12 @@ public void setId(long id) { this.id = id; } + @Option(longName = "stacktrace-max", shortName = "smax") + @Description("limit stacktrace max number") + public void setStacktraceMax(int stacktraceMax) { + this.stacktraceMax = stacktraceMax; + } + @Option(longName = "all", flag = true) @Description("Display all thread results instead of the first page") public void setAll(boolean all) { @@ -168,7 +175,9 @@ private ExitStatus processAllThreads(CommandProcess process) { threadSampler.pause(sampleInterval); List threadStats = threadSampler.sample(resultThreads); - process.appendResult(new ThreadModel(threadStats, stateCountMap, all)); + final ThreadModel model = new ThreadModel(threadStats, stateCountMap, all); + model.setStacktraceMax(stacktraceMax); + process.appendResult(model); return ExitStatus.success(); } @@ -177,7 +186,9 @@ private ExitStatus processBlockingThread(CommandProcess process) { if (blockingLockInfo.getThreadInfo() == null) { return ExitStatus.failure(1, "No most blocking thread found!"); } - process.appendResult(new ThreadModel(blockingLockInfo)); + final ThreadModel model = new ThreadModel(blockingLockInfo); + model.setStacktraceMax(stacktraceMax); + process.appendResult(model); return ExitStatus.success(); } @@ -215,7 +226,9 @@ private ExitStatus processTopBusyThreads(CommandProcess process) { BusyThreadInfo busyThread = new BusyThreadInfo(thread, threadInfo); busyThreadInfos.add(busyThread); } - process.appendResult(new ThreadModel(busyThreadInfos)); + final ThreadModel model = new ThreadModel(busyThreadInfos); + model.setStacktraceMax(stacktraceMax); + process.appendResult(model); return ExitStatus.success(); } @@ -235,7 +248,9 @@ private ExitStatus processThread(CommandProcess process) { return ExitStatus.failure(1, "thread do not exist! id: " + id); } - process.appendResult(new ThreadModel(threadInfos[0])); + final ThreadModel model = new ThreadModel(threadInfos[0]); + model.setStacktraceMax(stacktraceMax); + process.appendResult(model); return ExitStatus.success(); } } diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/ThreadView.java b/core/src/main/java/com/taobao/arthas/core/command/view/ThreadView.java index b1d2ca362cf..0bd49fc3e57 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/ThreadView.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/ThreadView.java @@ -21,18 +21,19 @@ public class ThreadView extends ResultView { @Override public void draw(CommandProcess process, ThreadModel result) { + final int stacktraceMax = result.getStacktraceMax(); if (result.getThreadInfo() != null) { // no cpu usage info - String content = ThreadUtil.getFullStacktrace(result.getThreadInfo()); + String content = ThreadUtil.getFullStacktrace(result.getThreadInfo(), stacktraceMax); process.write(content); } else if (result.getBusyThreads() != null) { List threadInfos = result.getBusyThreads(); for (BusyThreadInfo info : threadInfos) { - String stacktrace = ThreadUtil.getFullStacktrace(info, -1, -1); + String stacktrace = ThreadUtil.getFullStacktrace(info, -1, -1, stacktraceMax); process.write(stacktrace).write("\n"); } } else if (result.getBlockingLockInfo() != null) { - String stacktrace = ThreadUtil.getFullStacktrace(result.getBlockingLockInfo()); + String stacktrace = ThreadUtil.getFullStacktrace(result.getBlockingLockInfo(), stacktraceMax); process.write(stacktrace); } else if (result.getThreadStateCount() != null) { diff --git a/core/src/main/java/com/taobao/arthas/core/util/ThreadUtil.java b/core/src/main/java/com/taobao/arthas/core/util/ThreadUtil.java index b709857cb7f..15d57daa1d5 100644 --- a/core/src/main/java/com/taobao/arthas/core/util/ThreadUtil.java +++ b/core/src/main/java/com/taobao/arthas/core/util/ThreadUtil.java @@ -158,16 +158,23 @@ public static BlockingLockInfo findMostBlockingLock() { return blockingLockInfo; } - public static String getFullStacktrace(ThreadInfo threadInfo) { return getFullStacktrace(threadInfo, -1, -1, -1, 0, 0); } + public static String getFullStacktrace(final ThreadInfo threadInfo, final int stacktraceMax) { + return getFullStacktrace(threadInfo, -1, -1, -1, 0, 0, stacktraceMax); + } + public static String getFullStacktrace(BlockingLockInfo blockingLockInfo) { return getFullStacktrace(blockingLockInfo.getThreadInfo(), -1, -1, -1, blockingLockInfo.getLockIdentityHashCode(), blockingLockInfo.getBlockingThreadCount()); } + public static String getFullStacktrace(final BlockingLockInfo blockingLockInfo, final int stacktraceMax) { + return getFullStacktrace(blockingLockInfo.getThreadInfo(), -1, -1, -1, blockingLockInfo.getLockIdentityHashCode(), + blockingLockInfo.getBlockingThreadCount(), stacktraceMax); + } /** * 完全从 ThreadInfo 中 copy 过来 @@ -179,6 +186,11 @@ public static String getFullStacktrace(BlockingLockInfo blockingLockInfo) { */ public static String getFullStacktrace(ThreadInfo threadInfo, double cpuUsage, long deltaTime, long time, int lockIdentityHashCode, int blockingThreadCount) { + return getFullStacktrace(threadInfo, cpuUsage, deltaTime, time, lockIdentityHashCode, blockingThreadCount, 0); + } + + public static String getFullStacktrace(ThreadInfo threadInfo, double cpuUsage, long deltaTime, long time, + int lockIdentityHashCode, int blockingThreadCount, final int stacktraceMax) { StringBuilder sb = new StringBuilder("\"" + threadInfo.getThreadName() + "\"" + " Id=" + threadInfo.getThreadId()); @@ -242,6 +254,9 @@ public static String getFullStacktrace(ThreadInfo threadInfo, double cpuUsage, l } } ++i; + if (stacktraceMax > 0 && i >= stacktraceMax) { + break; + } } if (i < threadInfo.getStackTrace().length) { sb.append("\t..."); @@ -265,7 +280,11 @@ public static String getFullStacktrace(ThreadInfo threadInfo, double cpuUsage, l return sb.toString().replace("\t", " "); } - public static String getFullStacktrace(BusyThreadInfo threadInfo, int lockIdentityHashCode, int blockingThreadCount) { + public static String getFullStacktrace(BusyThreadInfo threadInfo, int lockIdentityHashCode, int blockingThreadCount) { + return getFullStacktrace(threadInfo, lockIdentityHashCode, blockingThreadCount, 0); + } + + public static String getFullStacktrace(BusyThreadInfo threadInfo, int lockIdentityHashCode, int blockingThreadCount, int stacktraceMax) { StringBuilder sb = new StringBuilder("\"" + threadInfo.getName() + "\""); if (threadInfo.getId() > 0) { sb.append(" Id=").append(threadInfo.getId()); @@ -338,6 +357,10 @@ public static String getFullStacktrace(BusyThreadInfo threadInfo, int lockIdenti sb.append('\n'); } } + + if (stacktraceMax > 0 && i > stacktraceMax) { + break; + } } if (i < threadInfo.getStackTrace().length) { sb.append("\t...");