在使用log4j过程中,很好奇log4j是如何获取到调用类以及调用方法的信息的,如
Logger.getLogger("").info("info");
Logger.getLogger("").warn("warn");
Logger.getLogger("").error("error");
通过查资料想到在java中,可以使用
Thread.currentThread().getStackTrace();
获取堆栈信息,例如
public class Log4jTest {
public static void main(String[] args) {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
for (int i = 0; i < stackTraceElements.length; i++) {
System.out.println(stackTraceElements[i]);
}
}
}
运行程序,可以看到结果为
堆栈信息的规则为先进后出,最上方的为堆栈顶,最下面为堆栈底,因此可以知道,这次调用共产生了两个线程,在main调用的时候先产生了一个线程,而后在调用Thread.currentThread().getStackTrace();的时候又产生了一个线程
分析完毕,自己写一个小例子,看看能否实现
class MLog {
public static void info() {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
System.out.println(stackTraceElements[2].getClassName());
}
}
class B {
public void bbb() {
MLog.info();
}
}
public class Test {
public static void main(String[] args) {
new B().bbb();
MLog.info();
}
}
运行结果为
可以看到结果正确,那么为什么stackTraceElements指定的下标为2呢,根据之前的分析,程序先调用main生成第一个线程,然后创建对象B调用bbb()方法,生成第二个线程,再然后调用MLog的info()方法生成第三个线程,最后调用Thread.currentThread().getStackTrace()生成第四个线程,由于实际调用MLog.info()方法的为对象B的bbb()方法,因此下标指定为2,同理,在main()中直接调用MLog.info()也是一样,main生成第一个线程,调用MLog的info()方法生成第二个线程,最后调用Thread.currentThread().getStackTrace()生成第三个线程,由于实际调用MLog.info()方法的位置是在main()中,所以下标同样应指定为2。注意点:堆栈为先进后出,所以在stackTraceElements中下标越大的调用顺序越靠前,也就是越靠近堆栈底
====================================================================
小白文章,如有错误希望能够给予指正