一、场景
在一些多线程的代码逻辑中,一个方法可能会被很多不同的线程所调用,如果没办法知道该方法具体的调用者,在通过日志排查问题时,日志会非常难以分析
解决:可以在打印日志时,将方法的上一级调用者打印出来
二、工具类
/**
* 堆栈相关工具类
*
* @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