通过StackTraceElement获取方法调用者的具体信息

原文链接: http://blog.csdn.net/argel_lj/article/details/49925657

StackTrace(堆栈轨迹) 其中包含的消息   ,  其实就是我们跑程序的时候报错 的相关消息。


本文简要介绍了StackTrace(堆栈轨迹)以及StackTraceElement的一些用法


一、什么是StackTrace

StackTrace(堆栈轨迹)可以认为是一系列方法调用过程的集合。

异常处理中常用的printStackTrace()即为打印异常调用的堆栈信息。

二、StackTraceElement介绍

StackTraceElement表示StackTrace(堆栈轨迹)中的一个元素,属性包括方法调用者的类名、方法名、文件名以及调用的行数。

[java]  view plain  copy
  1. public final class StackTraceElement implements java.io.Serializable {  
  2.     // Normally initialized by VM (public constructor added in 1.5)  
  3.     private String declaringClass;  
  4.     private String methodName;  
  5.     private String fileName;  
  6.     private int    lineNumber;  

StackTraceElement被定义为final,可见其作为一个Java的基础类不允许被继承。

获取StackTraceElement的方法有两种,均返回StackTraceElement数组

1、Thread.currentThread().getStackTrace()
2、new Throwable().getStackTrace()

StackTraceElement数组包含了StackTrace(堆栈轨迹)的内容,通过遍历它可以得到方法间的调用过程,

即可以得到当前方法以及其调用者的方法名、调用行数等信息

[java]  view plain  copy
  1. public class TestClass  
  2. {    
  3.     public static void main(String[] args)    
  4.     {  
  5.         new TestClass().methodA();  
  6.     }  
  7.   
  8.     private void methodA(){  
  9.         System.out.println("------进入methodA----------");  
  10.         methodB();  
  11.     }  
  12.   
  13.     private void methodB(){  
  14.         System.out.println("------进入methodB----------");  
  15.         StackTraceElement elements[] = Thread.currentThread().getStackTrace();  
  16.         for (int i = 0; i < elements.length; i++) {  
  17.             StackTraceElement stackTraceElement=elements[i];  
  18.             String className=stackTraceElement.getClassName();  
  19.             String methodName=stackTraceElement.getMethodName();  
  20.             String fileName=stackTraceElement.getFileName();  
  21.             int lineNumber=stackTraceElement.getLineNumber();  
  22.             System.out.println("StackTraceElement数组下标 i="+i+",fileName="  
  23.                     +fileName+",className="+className+",methodName="+methodName+",lineNumber="+lineNumber);  
  24.         }  
  25.     }  
  26. }  
执行main方法,输出信息如下


可以看到在方法B中使用getStackTrace,

得到StackTraceElement数组中下标为2的element表示方法B的调用者方法A的详细信息


三、用途

1、我们可以封装一个日志库,在打印目标日志的时候,也可以通过这个调用栈打印出这个日志所在的行数,这样就可以迅速的定位到日志输出行,再也不要全局搜索去查找了。

public static void d(String tag, String msg, Object... params) {
    StackTraceElement targetStackTraceElement = getTargetStackTraceElement();
    Log.d(tag, "(" + targetStackTraceElement.getFileName() + ":"
            + targetStackTraceElement.getLineNumber() + ")");
    Log.d(tag, String.format(msg, params));
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2、如果我们写了一个SDK,希望某个方法在固定的位置被调用,我们也可以在这个方法被调用的时候,进行检查,看这个方法的调用位置是否正确。

例如,必须在Activity.onResume中执行,PVSdk.onResume,所以我们在调用PVSdk.onResume方法的时候,在PVSdk.onResume方法里面来通过获取调用栈的信息检测这个方法是否在Activity的onResume方法中调用的。

public class PVSdk {

    public static void onResume() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        boolean result = false;
        for (StackTraceElement stackTraceElement : stackTrace) {
            String methodName = stackTraceElement.getMethodName();
            String className = stackTraceElement.getClassName();
            try {
                boolean assignableFromClass = Class.forName(className).isAssignableFrom(Activity.class);
                if (assignableFromClass && "onResume".equals(methodName)) {
                    result = true;
                    break;
                }
            } catch (ClassNotFoundException e) {

            }
        }
        if (!result)
            throw new RuntimeException("PVSdk.onResume must in Activity.onResume");
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

3、我们在进行源码分析的时候,如果想分析整个代码的执行流程,我们可以进行通过打印栈的信息来获取,这个在源码分析的时候还是挺有用的。





  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值