【转】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,即使有,也不太可能让我们直接在上面调试.如果能让程序自己输出调用栈,那是最好 ...
随机推荐
- linux系统错误码大全
#define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #defi ...
- java面试题实战二
1.spring 是如何创建bean的? 在IoC容器中,bean的获取主要通过BeanFactory和ApplicationContext获取,这里ApplicationContext实际上是继承自 ...
- postman 测试Excel文件导入导出功能
1.导入的测试方法 选择form-data,key值填写方法对应的参数,选择File,Value处上传文件即可. 2. 导出的测试方法 在导出文件的时候,响应结果是乱码,然后在测试的时候选择下载,下载 ...
- elasticsearch 搜索提示DSL
1,创建mapping: PUT /news_website { "mappings": { "news" : { "properties" ...
- Classic BAdi and New BAdi
Former Member Classic BAdi and New BAdi ... 2007年04月27日 04:43 | 1.5k Views Hi all, I have a question ...
- blade-boot操作之Idea使用Mave和Dockerfile文件推送到harbor仓库
mvn clean package docker:build 错误提示: Failed to execute goal com.spotify:docker-maven-plugin:1.1.0:bu ...
- Houdini Python开发实战 课程笔记
P2 + P3 + P4 + P5 - 基础: 1. Houdini中使用Python的地方 2. Textport:可使用cd.ls等路径操作的命令(命令前加%,可在python中使用) 3. So ...
- LwIP应用开发笔记之五:LwIP无操作系统TCP服务器
前面我们实现了UDP服务器及客户端以及基于其上的TFTP应用服务器.接下来我们将实现同样广泛应用的TCP协议各类应用. 1.TCP简述 TCP(Transmission Control Protoco ...
- Navicat连接Mysql8.0.11出现1251错误
# 登录mysql mysql -u root -p # 修改加密规则 mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_pas ...
- ajax处理csrf的三种方式
方式一: $.post({ url: '/get_result/', data: { value0: $('#v1').val(), value1: $('#v2').val(), csrfmiddl ...