StackTraceElement的简单使用

来源:互联网 发布:linux查看samba服务 编辑:程序博客网 时间:2024/05/16 10:04

 一、什么是StackTraceElement

StackTraceElement e(堆栈轨迹)存放的就是方法调用栈的信息,异常处理中常用的printStackTrace()实质就是打印异常调用的堆栈信息。

二、StackTraceElement的简单使用

        StackTraceElement表示StackTrace(堆栈轨迹)中的一个方法对象,属性包括方法的类名、方法名、文件名以及调用的行数。
我们写个 简单的事例:
public class StackTraceElementTest {public static void main(String[] args) {StackTraceElement[] stackElement = Thread.currentThread().getStackTrace();int q = 0;for(int i = 0;i<stackElement.length;i++){ System.out.println("----  the " + i + " element  ----");          System.out.println("toString: " + stackElement[i].toString());          System.out.println("ClassName: " + stackElement[i].getClassName());          System.out.println("FileName: " + stackElement[i].getFileName());          System.out.println("LineNumber: " + stackElement[i].getLineNumber());          System.out.println("MethodName: " + stackElement[i].getMethodName());}}}
运行结果如下:
----  the 0 element  ----toString: java.lang.Thread.getStackTrace(Thread.java:1589)ClassName: java.lang.ThreadFileName: Thread.javaLineNumber: 1589MethodName: getStackTrace----  the 1 element  ----toString: com.hxfxy.stackTraceElementTest.StackTraceElementTest.main(StackTraceElementTest.java:8)ClassName: com.hxfxy.stackTraceElementTest.StackTraceElementTestFileName: StackTraceElementTest.javaLineNumber: 8MethodName: main

二、StackTraceElement介绍

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

public final class StackTraceElement implements java.io.Serializable {      // Normally initialized by VM (public constructor added in 1.5)      private String declaringClass;      private String methodName;      private String fileName;      private int    lineNumber;  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

获取StackTraceElement的方法有两种,均返回StackTraceElement数组,也就是这个栈的信息。

1、Thread.currentThread().getStackTrace()

2、new Throwable().getStackTrace()

StackTraceElement数组包含了StackTrace(堆栈轨迹)的内容,通过遍历它可以得到方法间的调用过程,即可以得到当前方法以及其调用者的方法名、调用行数等信息

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

三、用途

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



0 0
原创粉丝点击