zoukankan      html  css  js  c++  java
  • 【转】StackTraceElement获取方法调用栈的信息

    本文链接:https://blog.csdn.net/hp910315/article/details/52702199


    一、什么是StackTrace

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

    二、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;

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

    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));
    }

    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");
    }
    }

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

    参考文章:
    通过StackTraceElement获取方法调用者的具体信息

    Android 从StackTraceElement反观Log库

  • 相关阅读:
    C primer plus 摘抄(第三章 数据和C)
    lambda表达式+python内置函数
    补充(pass)
    If语句和while语句
    解释器和编译器的区别
    关于python编码
    初识Python
    unity学习(一)ide窗口
    unity学习
    redis实践 —— redisReply简析
  • 原文地址:https://www.cnblogs.com/wytiger/p/11552355.html
Copyright © 2011-2022 走看看