JVM Profiler StacktraceCollectorProfiler

开篇

 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 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": "[email protected]",
    "processUuid": "1e580f6e-0493-4e5b-bee2-a61c5f7b097d",
    "threadState": "TIMED_WAITING",
    "count": 24,
    "tag": "mytag",
    "startEpoch": 1536072796084,
    "threadName": "main"
}

你可能感兴趣的:(JVM Profiler StacktraceCollectorProfiler)