今天看到有一个工具类中有一句

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)的方法相关推荐

  1. Ubuntu查看IP信息的两种方式

    无论使用什么系统,都有用到ip地址的时候,习惯了windows系统的人很容易就能查找出系统的ip,但是在linux系统如何查看ip呢?作为Linux新手,以Ubuntu的使用经验,我知道Ubuntu查 ...

  2. 在Scrapy中如何利用Xpath选择器从HTML中提取目标信息(两种方式)

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 坚定,严谨,勤奋,开拓 前一阵子我 ...

  3. 微信小程序获取用户信息的两种方式

    1.只获取头像和昵称(不能将用户信息返回给后端) <open-data class="tx" type="userAvatarUrl"></o ...

  4. java jframe添加面板_JFrame添加组件的两种方式

    对JFrame添加组件有两种方式:1) 用getContentPane()方法获得JFrame的内容面板,再对其加入组件:frame.getContentPane().add(childCompont ...

  5. android asynctask源码分析,Android通过Handler与AsyncTask两种方式动态更新ListView(附源码)...

    本文实例讲述了Android通过Handler与AsyncTask两种方式动态更新ListView的方法.分享给大家供大家参考,具体如下: 有时候我们需要修改已经生成的列表,添加或者修改数据,noti ...

  6. android数据回传多个页面_Android菜鸟起飞|使用Intent实现Activity跳转的两种方式(无回传数据和有回传数据)...

    使用Intent实现Activity跳转的两种方式 1. 使用startActivity(intnet)方法实现无回传数据的Activity跳转: 使用方法: 为实现跳转动作的控件绑定监听器,在点击事 ...

  7. 如何让BERT拥有视觉感知能力?两种方式将视频信息注入BERT

    一只小狐狸带你解锁NLP/ML/DL秘籍 老板老板,听说BERT是个瞎子 此话怎讲? 它能理解语言,但是理解不了小夕的自拍! video-BERT了解一下 喵喵喵? AI的三大核心板块(CV/Spee ...

  8. fragment与activity之间的信息传递的两种方式

    因为Fragment和Activity一样是具有生命周期,不是一般的bean通过构造函数传值,会造成异常. fragment与activity之间的信息传递的两种方式: 1.第一种方式,也是最常用的方 ...

  9. 开启子进程的两种方式、进程间内存空间隔离、进程对象的方法或属性详解

    1.操作系统(推荐查看书籍:现代操作系统)     操作系统是位于计算机硬件与软件之间的控制程序     作用:         1.将硬件的复杂操作封装成简单的接口,给用户或者应用程序使用      ...

最新文章

  1. centos7 install mysql
  2. unordered_map源码解析和个人理解
  3. Internet Explorer 8 Beta 2十大看点
  4. Oracle PCTfree assm,Oracle 段空间管理方式与PCTFREE和PCTUSED的概念
  5. 国庆中秋双节快乐 | 马云不再担任阿里巴巴董事;胡厚崑当值华为轮值董事长;百度小度完成独立融资...
  6. easyui datagrid加载数据的三种方式
  7. Java接口中的成员变量为什么必须声明为public static final?
  8. svg 贝塞尔曲线图解(记录)
  9. mysql覆盖索引和回表
  10. html动态创建table不成功的一个问题
  11. Wordpress主题制作基础教程
  12. 中兴V889DRoot后可删和不可删
  13. 伦斯勒理工大学计算机专业,伦斯勒理工学院计算机科学硕士排名第60(2020年TFE Times排名)...
  14. mysql对单引号的模糊查询_SQL语句中的单引号处理以及模糊查询
  15. VUE 当前页获取来源路由地址
  16. 强大的第三方视频播放器。
  17. php 图片印章_在线生成实用又方便 (图片印章)
  18. 股票分时数据获取-东方财富
  19. java中的画图公式_GitHub - oneSaber/Compiler-java: 函数绘图语言java实现
  20. python决策树分类案例_python实现决策树分类算法

热门文章

  1. linux ntp 'ntp_request.c'远程拒绝服务漏洞,NTP拒绝服务漏洞(CVE-2015-5146)
  2. mapreduce编程初级实践_涨姿势!2020最好的 10 大国外编程学习网站
  3. php三个数字比较大小排序,php中常用的4种实现数字大小排序的冒泡选择等算法函数代码...
  4. Mybatis源码解析-sql执行
  5. 九十三、Python使用百度云接口API实现截图,文字识别和语音合成
  6. 博士申请 | 香港浸会大学万人杰教授招收计算机视觉全奖博士生/研究助理
  7. 我们做了一个医疗版MNIST数据集,发现常见AutoML算法没那么好用
  8. 基于多域连接卷积神经网络的精神分裂症脑功能网络分类
  9. SpringBoot从入门到实战只需一篇文章
  10. 【教程】写CSDN博客时 调整图片大小,图片居中