得到当前堆栈信息的两种方式(Thread和Throwable)的方法
2016-11-19 16:24
239 查看
今天看到有一个工具类中有一句
Thread.currentThread().getStackTrace()[2].getClassName();
原来工作中遇到的问题:使用Thread.currentThread().getStackTrace()[1].getClassName()得到的是当前类而不是调用类。
所以弄个明白 。
我进行了一组测试:
测试A:
结果是:
test.ThreadTest;TestString;ThreadTest.java(当前方法和类)
test.App;main;App.java(调用该方法的方法和类)
测试B:
App类同上,得到的结果是:
java.lang.Thread;getStackTrace;Thread.java(Thread的信息)
test.ThreadTest;TestString;ThreadTest.java(当前方法和类)
test.App;main;App.java(调用该方法的方法和类)
查看了下jdk的源码。
首先是Throwable的getStackTrace方法,代码如下:
再看下Thread的getStackTrace方法,代码如下:
在if语句里面因为 this != Thread.currentThread()是为true的,所以方法会执行else里面的语句
new Exception().getStackTrace();就是这句话让使用Thread的getStackTrace方法就有可能多打印一句java.lang.Thread;getStackTrace;Thread.java
这也就是为什么使用
会得不到正确的日志信息的原因了!
应该就是这样子了,为了验证我想的对不对,写了一个测试验证的例子,代码如下:
执行之后的结果是:
test.TestException;getStackTrace;TestException.java
test.ThreadTest;TestString;ThreadTest.java
test.App;main;App.java
解决办法很简单,
要么使用new Exception().getStackTrace()[1];
要么使用Thread.currentThread().getStackTrace()[2]。
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 method if (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 permission SecurityManager 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 terminated if (!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 thread return (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)的纠结
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 得到当前方法的名字Thread.currentThread().getStackTrace()[1].getMethodName();
- 得到当前方法的名字Thread.currentThread().getStackTrace()[1].getMethodName();
- java实现多线程的两种方式继承Thread类和实现Runnable接口的方法
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 线程 创建和启动线程的两种方式 实现Runnable接口 继承Thread类 重写唯一方法run()
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 正确得到线程退出信息的方法详解-变量存储退出信息结构、使用动态存储的方式退出信息结构、使用全局变量方式推相互信息结构、使用main函数中的局部变量存储退出信息结构
- 如何用JS得到当前页面的url信息方法
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 如何用js得到当前页面的url信息方法