Bootstrap

Java工具类:获取当前方法上一级、全部的调用者


一、场景

在一些多线程的代码逻辑中,一个方法可能会被很多不同的线程所调用,如果没办法知道该方法具体的调用者,在通过日志排查问题时,日志会非常难以分析

解决:可以在打印日志时,将方法的上一级调用者打印出来


二、工具类

/**
 * 堆栈相关工具类
 *
 * @author hcs
 * @date 2023/8/21 14:05
 */
public class StackTraceUtils {

    /**
     * 获取方法整个调用过程的相关信息
     *
     * @return
     */
    public static String getAllTag() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (StackTraceElement e : stackTrace) {
            System.out.println("当前方法调用过程 = " + e.getClassName() + "\t"
                    + e.getMethodName() + "\t" + e.getLineNumber());
        }
        StackTraceElement log = stackTrace[1];
        String tag = null;
        for (int i = 1; i < stackTrace.length; i++) {
            StackTraceElement e = stackTrace[i];
            if (!e.getClassName().equals(log.getClassName())) {
                tag = e.getClassName() + "." + e.getMethodName();
                break;
            }
        }
        if (tag == null) {
            tag = log.getClassName() + "." + log.getMethodName();

        }
        System.out.println("当前方法 = " + tag);
        return tag;
    }

    /**
     * 获取方法上一级调用者的相关信息
     *
     * @return
     */
    public static String getParentTag() {
        String trace = null;
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        int index = stackTrace.length >= 4 ? 3 : (stackTrace.length == 3 ? 2 : 0);
        if (index > 0) {
            trace = "[" + stackTrace[index].getClassName() + "]-["
                    + stackTrace[index].getMethodName() + " - line:" + stackTrace[index].getLineNumber() + "]";
        }
        System.out.println("当前方法上一级的调用者 = " + trace);
        return trace;
    }
}


三、测试类

public class StackTraceTest {

    public static void main(String[] args) {
        v();
        i();
    }

    /**
     * 获取方法上一级调用者的相关测试方法
     */
    public static void v() {
        d();
    }

    public static void d() {
        f();
    }

    public static String f() {
        return StackTraceUtils.getParentTag();
    }


    /**
     * 获取方法整个调用过程的相关测试方法
     */
    public static void i() {
        w();
    }

    public static void w() {
        e();
    }

    public static void e() {
        StackTraceUtils.getAllTag();
    }
}


四、测试结果

调用StackTraceTest方法:v()

结果为

当前方法上一级的调用者 = [com.xxx.StackTraceTest]-[d - line:19]

调用StackTraceTest方法:i()

结果为

当前方法调用过程 = java.lang.Thread	getStackTrace	1559
当前方法调用过程 = com.xxx.util.StackTraceUtils	getAllTag	53
当前方法调用过程 = com.xxx.StackTraceTest	e	39
当前方法调用过程 = com.xxx.StackTraceTest	w	35
当前方法调用过程 = com.xxx.StackTraceTest	i	31
当前方法调用过程 = com.xxx.StackTraceTest	main	8
当前方法 = com.xxx.StackTraceTest.e
;