【转】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库
【转】StackTraceElement获取方法调用栈的信息的更多相关文章
- Linux下手动获取当前调用栈
被问到如何手动获取当前的调用栈,之前碰到过一时没记起来,现在回头整理一下. 其原理是:使用backtrace()从栈中获取当前调用各层函数调用的返回地址,backtrace_symbols()将对应地 ...
- Java中异常的处理以及自定义异常,抛出异常到方法调用栈底层
package com.gezhi; /** * 创建一个自定义异常SpendMoneyException类 * * @author square 凉 * */@SuppressWarnings(& ...
- JVM方法调用栈
摘自深入分析java web技术内幕
- 《浏览器工作原理与实践》<08>调用栈:为什么JavaScript代码会出现栈溢出?
在上篇文章中,我们讲到了,当一段代码被执行时,JavaScript 引擎先会对其进行编译,并创建执行上下文.但是并没有明确说明到底什么样的代码才算符合规范. 那么接下来我们就来明确下,哪些情况下代码才 ...
- Windows下获取Dump文件以及进程下各线程调用栈的方法总结(转)
1. Dump文件的用途 Dump文件, 主要用于诊断一个进程的运行状态,尤其是碰到崩溃(Crash)或者挂起(hang)不响应时,需要分析它的工作状态. 除了平时常见的attach到这个进程, 分 ...
- 利用backtrace和backtrace_symbols函数打印调用栈信息
在头文件"execinfo.h"中声明了三个函数用于获取当前线程的函数调用堆栈. #include <execinfo.h> int backtrace(void * ...
- java方法的理解、调用栈与异常处理
一.流程分支 If/else :基于boolean值的双分支 Switch:基于数字(整数.char.byte.枚举).字符串 类型的多分支 Int month =5; Switch 二.方法meth ...
- .NET使用StackTrace获取方法调用者信息
前言 在日常工作中,偶尔需要调查一些诡异的问题,而业务代码经过长时间的演化,很可能已经变得错综复杂,流程.分支众多,如果能在关键方法的日志里添加上调用者的信息,将对定位问题非常有帮助. 介绍 Stac ...
- 在C/C++程序里打印调用栈信息
我们知道,GDB的backtrace命令可以查看堆栈信息.但很多时候,GDB根本用不上.比如说,在线上环境中可能没有GDB,即使有,也不太可能让我们直接在上面调试.如果能让程序自己输出调用栈,那是最好 ...
随机推荐
- easyui datagrid的editor编辑器如何为validatebox控件添加改变事件
项目中需要为行编辑器Editor的某个列的文本框添加改变事件 需求:新增行时,为用户名输入特殊字符进行验证,不允许保存用户数据 html页面 <table id="gridlist&q ...
- 【Python】解析Python中的迭代器
目录结构: contents structure [-] Iterator VS Iterable Itertools 模块 生成器(Generator) 在开始文章之前,先贴上一张Iterable. ...
- pip安装daemon模块
E:\> pip install python-daemon Collecting python-daemon Downloading https://files.pythonhosted.or ...
- (原创)C++ 同步队列
(原创)C++ 同步队列 同步队列作为一个线程安全的数据共享区,经常用于线程之间数据读取,比如半同步半异步线程池的同步队列. 其实做起来比较简单,要用到list.锁和条件变量,条件变量的作用是在队列满 ...
- 泡泡一分钟:Robust Attitude Estimation Using an Adaptive Unscented Kalman Filter
张宁 Robust Attitude Estimation Using an Adaptive Unscented Kalman Filter 使用自适应无味卡尔曼滤波器进行姿态估计链接:https: ...
- Cassandra开发入门文档第一部分
Cassandra的特点 横向可扩展性: Cassandra部署具有几乎无限的存储和处理数据的能力.当需要额外的容量时,可以简单地将更多的机器添加到集群中.当新机器加入集群时,Cassandra需要对 ...
- 初识RxSwift
初识Observable Observable<T> 这个类就是Rx框架的基础, 我们可以称他为可观察序列, 他的作用就是可以异步的产生一系列的Event(事件), 即一个Observab ...
- [Linux.centOS].安装Redis 腾讯云
环境 { "服务器运营商":"腾讯云", "操作系统":"CentOS 7.5 64位", "CPU" ...
- Centos7安装部署MongoDB教程
安装方式: RPM包安装 安装步骤: 一.下载RPM包 下图是需要注意的事项.其一选择MongoDB的社区版本,默认是企业版本.其二,选中版本后,在下方会出现下载地址,直接复制下载即可 二.安装并查 ...
- java学习摘抄笔记mybaits1
mybatis 第一天 mybatis的基础知识 课程安排: mybatis和springmvc通过订单商品 案例驱动 第一天:基础知识(重点,内容量多) 对原生态jdbc程序(单独使用jdbc开发) ...