方法一:通过 StackTraceElement
方法:
public static void printCallStatck() {
StackTraceElement[] stackElements = Thread.currentThread().getStackTrace();
//StackTraceElement[] stackElements = new Throwable().getStackTrace();
if (stackElements != null) {
for (StackTraceElement stackTraceElement : stackElements) {
System.out.println("ClassName:" + stackTraceElement.getClassName());
System.out.println("FileName:" + stackTraceElement.getFileName());
System.out.println("LineNumber:" + stackTraceElement.getLineNumber());
System.out.println("MethodName:" + stackTraceElement.getMethodName());
System.out.println("isNativeMethod:" + stackTraceElement.isNativeMethod());
System.out.println("信息:" + stackTraceElement.toString());
System.out.println("-----------------------------------");
}
}
}
//StackTraceElement[] stackElements = new Throwable().getStackTrace();
x
1
public static void printCallStatck() {
2
StackTraceElement[] stackElements = Thread.currentThread().getStackTrace();
3
//StackTraceElement[] stackElements = new Throwable().getStackTrace();
4
if (stackElements != null) {
5
for (StackTraceElement stackTraceElement : stackElements) {
6
System.out.println("ClassName:" + stackTraceElement.getClassName());
7
System.out.println("FileName:" + stackTraceElement.getFileName());
8
System.out.println("LineNumber:" + stackTraceElement.getLineNumber());
9
System.out.println("MethodName:" + stackTraceElement.getMethodName());
10
System.out.println("isNativeMethod:" + stackTraceElement.isNativeMethod());
11
System.out.println("信息:" + stackTraceElement.toString());
12
System.out.println("-----------------------------------");
13
}
14
}
15
}
结果:
ClassName:java.lang.Thread
FileName:Thread.java
LineNumber:1552
MethodName:getStackTrace
isNativeMethod:false
信息:java.lang.Thread.getStackTrace(Thread.java:1552)
-----------------------------------
ClassName:Test
FileName:Test.java
LineNumber:7
MethodName:printCallStatck
isNativeMethod:false
信息:Test.printCallStatck(Test.java:7)
-----------------------------------
ClassName:Test
FileName:Test.java
LineNumber:3
MethodName:main
isNativeMethod:false
信息:Test.main(Test.java:3)
-----------------------------------
x
1
ClassName:java.lang.Thread
2
FileName:Thread.java
3
LineNumber:1552
4
MethodName:getStackTrace
5
isNativeMethod:false
6
信息:java.lang.Thread.getStackTrace(Thread.java:1552)
7
-----------------------------------
8
ClassName:Test
9
FileName:Test.java
10
LineNumber:7
11
MethodName:printCallStatck
12
isNativeMethod:false
13
信息:Test.printCallStatck(Test.java:7)
14
-----------------------------------
15
ClassName:Test
16
FileName:Test.java
17
LineNumber:3
18
MethodName:main
19
isNativeMethod:false
20
信息:Test.main(Test.java:3)
21
-----------------------------------
注意:
1、数组中元素的个数是不确定个的,这完全取决于打印堆栈信息时经过了几步的调用。
2、并非最后一个元素的就一定是我们最想要的信息,因为在框架中,后续可能还会有很多层的调用,比如在Android中打印日志的一个案例:
dalvik.system.VMStack:getThreadStackTrace:-2
java.lang.Thread:getStackTrace:1566
com.yibasan.lizhifm.ad.Lg:log:58
com.yibasan.lizhifm.ad.Lg:i:34//这里调用了Log.i
com.yibasan.lizhifm.ad.SplashAdManager:canShowAd:66//我们是在这里调用了封装好的Lg类中的Lg.i方法,所以这里的元素是我们最想要的
com.yibasan.lizhifm.activities.BaseActivity:onResume:518
com.yibasan.lizhifm.activities.fm.NavBarActivity:onResume:375
android.app.Instrumentation:callActivityOnResume:1276
android.app.Activity:performResume:6937
android.app.ActivityThread:performResumeActivity:3468
android.app.ActivityThread:handleResumeActivity:3531
android.app.ActivityThread$H:handleMessage:1569
android.os.Handler:dispatchMessage:102
android.os.Looper:loop:154
android.app.ActivityThread:main:6209
java.lang.reflect.Method:invoke:-2
com.android.internal.os.ZygoteInit$MethodAndArgsCaller:run:900
com.android.internal.os.ZygoteInit:main:790
x
1
dalvik.system.VMStack:getThreadStackTrace:-2
2
java.lang.Thread:getStackTrace:1566
3
com.yibasan.lizhifm.ad.Lg:log:58
4
com.yibasan.lizhifm.ad.Lg:i:34//这里调用了Log.i
5
com.yibasan.lizhifm.ad.SplashAdManager:canShowAd:66//我们是在这里调用了封装好的Lg类中的Lg.i方法,所以这里的元素是我们最想要的
6
com.yibasan.lizhifm.activities.BaseActivity:onResume:518
7
com.yibasan.lizhifm.activities.fm.NavBarActivity:onResume:375
8
android.app.Instrumentation:callActivityOnResume:1276
9
android.app.Activity:performResume:6937
10
android.app.ActivityThread:performResumeActivity:3468
11
android.app.ActivityThread:handleResumeActivity:3531
12
android.app.ActivityThread$H:handleMessage:1569
13
android.os.Handler:dispatchMessage:102
14
android.os.Looper:loop:154
15
android.app.ActivityThread:main:6209
16
java.lang.reflect.Method:invoke:-2
17
com.android.internal.os.ZygoteInit$MethodAndArgsCaller:run:900
18
com.android.internal.os.ZygoteInit:main:790
方法二:通过 Exception
new Exception("this is a log").printStackTrace();
System.out.println("这里会继续执行");
x
1
new Exception("this is a log").printStackTrace();
2
System.out.println("这里会继续执行");
结果
java.lang.Exception: this is a log
at Test.main(Test.java:3)
这里会继续执行
1
java.lang.Exception: this is a log
2
at Test.main(Test.java:3)
3
这里会继续执行
StackTraceElement 类简介
此类在 java.lang 包下
public final class StackTraceElement extends Object implements Serializable
x
8
1
public final class StackTraceElement extends Object implements Serializable
堆栈跟踪元素,它由 Throwable.getStackTrace() 返回。每个元素表示单独的一个【堆栈帧】。所有的堆栈帧(堆栈顶部的那个堆栈帧除外)都表示一个【方法调用】。堆栈顶部的帧表示【生成堆栈跟踪的执行点】。通常,这是创建对应于堆栈跟踪的 throwable 的点。
构造方法
public StackTraceElement(String declaringClass, String methodName, String fileName, int lineNumber)
1
public StackTraceElement(String declaringClass, String methodName, String fileName, int lineNumber)
创建表示指定【执行点】的【堆栈跟踪元素】。
参数:
- declaringClass - 类的完全限定名,该类包含由堆栈跟踪元素所表示的执行点
- methodName - 方法名,该方法包含由堆栈跟踪元素所表示的执行点
- fileName - 文件名,该文件包含由堆栈跟踪元素所表示的执行点;如果该信息不可用,则该参数为 null
- lineNumber - 源代码行的行号,该代码行包含由堆栈跟踪元素所表示的执行点;如果此信息不可用,则该参数为负数。值 -2 表示包含执行点的方法是一个本机方法
抛出:
- NullPointerException - 如果 declaringClass 或 methodName 为 null
普通方法
- String getClassName() 返回类的完全限定名,该类包含由该堆栈跟踪元素所表示的执行点。
- String getFileName() 返回源文件名,该文件包含由该堆栈跟踪元素所表示的执行点。
- int getLineNumber() 返回源行的行号,该行包含由该堆栈该跟踪元素所表示的执行点。
- String getMethodName() 返回方法名,此方法包含由该堆栈跟踪元素所表示的执行点。
- boolean isNativeMethod() 如果包含由该堆栈跟踪元素所表示的执行点的方法是一个本机方法,则返回 true。
重写的Object的方法
- boolean equals(Object obj) 如果指定的对象是另一个 StackTraceElement 实例,并且该对象表示的【执行点】与该实例的相同,则返回 ture。
- int hashCode() 返回此堆栈跟踪元素的哈希码值。
- String toString() 返回表示该堆栈跟踪元素的字符串。
该字符串的格式取决于实现,但是可将以下示例格式视为典型的格式:
"MyClass.mash(MyClass.java:9)" - 其中,"MyClass" 是类的完全限定名,该类包含由该堆栈跟踪元素所表示的执行点;"mash" 是包含执行点的方法的名字;"MyClass.java" 是包含执行点的源文件;"9" 是包含执行点的源行的行号。
"MyClass.mash(MyClass.java)" - 同上,但是行号不可用。
"MyClass.mash(Unknown Source)" - 同上,但是文件名和行号都不可用。
"MyClass.mash(Native Method)" - 同上,但是文件名和行号都不可用,并且已知包含执行点的方法是本机方法。
1
该字符串的格式取决于实现,但是可将以下示例格式视为典型的格式:
2
"MyClass.mash(MyClass.java:9)" - 其中,"MyClass" 是类的完全限定名,该类包含由该堆栈跟踪元素所表示的执行点;"mash" 是包含执行点的方法的名字;"MyClass.java" 是包含执行点的源文件;"9" 是包含执行点的源行的行号。
3
"MyClass.mash(MyClass.java)" - 同上,但是行号不可用。
4
"MyClass.mash(Unknown Source)" - 同上,但是文件名和行号都不可用。
5
"MyClass.mash(Native Method)" - 同上,但是文件名和行号都不可用,并且已知包含执行点的方法是本机方法。
2018-1-3