开篇
StacktraceCollectorProfiler主要用来采集线程的调用栈,原理是通过ManagementFactory.getThreadMXBean()返回的ThreadMXBean对象来实现。
源码分析
public void profile() {
// 获取此刻所有线程的dump信息
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
if (threadInfos == null) {
return;
}
// 遍历线程信息并处理每个线程
for (ThreadInfo threadInfo : threadInfos) {
String threadName = threadInfo.getThreadName();
if (threadName == null) {
threadName = "";
}
if (!ignoreThreadNamePrefix.isEmpty()
&& threadName.startsWith(ignoreThreadNamePrefix)) {
continue;
}
// 获取线程的调用栈
StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
// 创建调用栈对象
Stacktrace stacktrace = new Stacktrace();
stacktrace.setThreadName(threadName);
stacktrace.setThreadState(String.valueOf(threadInfo.getThreadState()));
// 创建保存调用栈的list
int totalLength = 0;
List<ClassAndMethod> stack = new ArrayList<>(stackTraceElements.length);
// 按照倒序保存调用链,最底层的放在最前面,把最根本的原因发在前面
for (int i = stackTraceElements.length - 1; i >= 0; i--) {
StackTraceElement stackTraceElement = stackTraceElements[i];
String className = String.valueOf(stackTraceElement.getClassName());
String methodName = String.valueOf(stackTraceElement.getMethodName());
stack.add(new ClassAndMethod(className, methodName));
totalLength += className.length() + methodName.length();
// 如果长度超出限制,那么就截断
if (totalLength >= Constants.MAX_STRING_LENGTH) {
stack.add(new ClassAndMethod("_stack_", "_trimmed_"));
break;
}
}
// 反转调用链,把最底层的放在最前面。
ClassAndMethod[] classAndMethodArray = new ClassAndMethod[stack.size()];
for (int i = 0; i < stack.size(); i++) {
classAndMethodArray[classAndMethodArray.length - 1 - i] = stack.get(i);
}
stacktrace.setStack(classAndMethodArray);
buffer.appendValue(stacktrace);
}
}
采集结果
调用链的反向序列为:
- java.lang.Thread.sleep
- com.uber.profiling.examples.HelloWorldApplication.privateSleepMethod
- com.uber.profiling.examples.HelloWorldApplication.main
{
"stacktrace": ["java.lang.Thread.sleep", "com.uber.profiling.examples.HelloWorldApplication.privateSleepMethod", "com.uber.profiling.examples.HelloWorldApplication.main"],
"endEpoch": 1536072801080,
"appId": null,
"host": "xiaozhideMacBook-Pro.local",
"name": "2203@xiaozhideMacBook-Pro.local",
"processUuid": "1e580f6e-0493-4e5b-bee2-a61c5f7b097d",
"threadState": "TIMED_WAITING",
"count": 24,
"tag": "mytag",
"startEpoch": 1536072796084,
"threadName": "main"
}