得到当前堆栈信息的两种方式(Thread和Throwable)的方法
今天看到有一個工具類中有一句
Thread.currentThread().getStackTrace()[2].getClassName();
原來工作中遇到的問題:使用Thread.currentThread().getStackTrace()[1].getClassName()得到的是當前類而不是調用類。
所以弄個明白 。
我進行了一組測試:
測試A:
public class ThreadTest {public static void TestString(){StackTraceElement[] arr = new Exception().getStackTrace();for(int i=0;i<=arr.length-1;i++){System.out.println(arr[i].getClassName()+";"+arr[i].getMethodName()+";"+arr[i].getFileName());}} } public class App {public static void main( String[] args ){ThreadTest.TestString();} }? ? ?結果是:
test.ThreadTest;TestString;ThreadTest.java(當前方法和類)
test.App;main;App.java(調用該方法的方法和類)
測試B:
public class ThreadTest {public static void TestString(){StackTraceElement[] arr = Thread.currentThread().getStackTrace();for(int i=0;i<=arr.length-1;i++){System.out.println(arr[i].getClassName()+";"+arr[i].getMethodName()+";"+arr[i].getFileName());}} }App類同上,得到的結果是:
java.lang.Thread;getStackTrace;Thread.java(Thread的信息)
test.ThreadTest;TestString;ThreadTest.java(當前方法和類)
test.App;main;App.java(調用該方法的方法和類)
查看了下jdk的源碼。
首先是Throwable的getStackTrace方法,代碼如下:
public StackTraceElement[] getStackTrace() {return getOurStackTrace().clone();}private synchronized StackTraceElement[] getOurStackTrace() {// Initialize stack trace field with information from// backtrace if this is the first call to this methodif (stackTrace == UNASSIGNED_STACK ||(stackTrace == null && backtrace != null) /* Out of protocol state */) {int depth = getStackTraceDepth();stackTrace = new StackTraceElement[depth];for (int i=0; i < depth; i++)stackTrace[i] = getStackTraceElement(i);} else if (stackTrace == null) {return UNASSIGNED_STACK;}return stackTrace;}再看下Thread的getStackTrace方法,代碼如下:
public StackTraceElement[] getStackTrace() {if (this != Thread.currentThread()) {// check for getStackTrace permissionSecurityManager security = System.getSecurityManager();if (security != null) {security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION);}// optimization so we do not call into the vm for threads that// have not yet started or have terminatedif (!isAlive()) {return EMPTY_STACK_TRACE;}StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});StackTraceElement[] stackTrace = stackTraceArray[0];// a thread that was alive during the previous isAlive call may have// since terminated, therefore not having a stacktrace.if (stackTrace == null) {stackTrace = EMPTY_STACK_TRACE;}return stackTrace;} else {// Don't need JVM help for current threadreturn (new Exception()).getStackTrace();}}在if語句里面因為 ??this != Thread.currentThread()是為true的,所以方法會執行else里面的語句
return (new Exception()).getStackTrace();new Exception().getStackTrace();就是這句話讓使用Thread的getStackTrace方法就有可能多打印一句java.lang.Thread;getStackTrace;Thread.java ? ? ?
這也就是為什么使用
logger = LoggerFactory.getLogger(Thread.currentThread().getStackTrace()[1].getClassName());會得不到正確的日志信息的原因了!
應該就是這樣子了,為了驗證我想的對不對,寫了一個測試驗證的例子,代碼如下:
public class TestException {public static StackTraceElement[] getStackTrace() {return new Exception().getStackTrace();} } public class ThreadTest {public static void TestString(){StackTraceElement[] arr = TestException.getStackTrace();for(int i=0;i<=arr.length-1;i++){System.out.println(arr[i].getClassName()+";"+arr[i].getMethodName()+";"+arr[i].getFileName());}} } public class App {public static void main( String[] args ){ThreadTest.TestString();} }執行之后的結果是:
test.TestException;getStackTrace;TestException.java
test.ThreadTest;TestString;ThreadTest.java
test.App;main;App.java
解決辦法很簡單,
要么使用new Exception().getStackTrace()[1];
要么使用Thread.currentThread().getStackTrace()[2]。
總結
以上是生活随笔為你收集整理的得到当前堆栈信息的两种方式(Thread和Throwable)的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: rxlifecycle 框架的使用
- 下一篇: AppCompat DayNight t