-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathThrowableUtils.java
More file actions
91 lines (84 loc) · 3.4 KB
/
ThrowableUtils.java
File metadata and controls
91 lines (84 loc) · 3.4 KB
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package com.xzy.utils.throwable;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* Throwable 相关的工具类。
* 参考 https://github.com/Blankj/AndroidUtilCode/blob/master/lib/utilcode/src/main/
* java/com/blankj/utilcode/util/ThrowableUtils.java
*
* @author xzy
*/
@SuppressWarnings("unused")
public class ThrowableUtils {
private static final String LINE_SEP = System.getProperty("line.separator");
private ThrowableUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
public static String getFullStackTrace(Throwable throwable) {
final List<Throwable> throwableList = new ArrayList<>();
while (throwable != null && !throwableList.contains(throwable)) {
throwableList.add(throwable);
throwable = throwable.getCause();
}
final int size = throwableList.size();
final List<String> frames = new ArrayList<>();
List<String> nextTrace = getStackFrameList(throwableList.get(size - 1));
for (int i = size; --i >= 0; ) {
final List<String> trace = nextTrace;
if (i != 0) {
nextTrace = getStackFrameList(throwableList.get(i - 1));
removeCommonFrames(trace, nextTrace);
}
if (i == size - 1) {
frames.add(throwableList.get(i).toString());
} else {
frames.add(" Caused by: " + throwableList.get(i).toString());
}
frames.addAll(trace);
}
StringBuilder sb = new StringBuilder();
for (final String element : frames) {
sb.append(element).append(LINE_SEP);
}
return sb.toString();
}
private static List<String> getStackFrameList(final Throwable throwable) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true);
throwable.printStackTrace(pw);
final String stackTrace = sw.toString();
final StringTokenizer frames = new StringTokenizer(stackTrace, LINE_SEP);
final List<String> list = new ArrayList<>();
boolean traceStarted = false;
while (frames.hasMoreTokens()) {
final String token = frames.nextToken();
// Determine if the line starts with <whitespace>at
final int at = token.indexOf("at");
if (at != -1 && token.substring(0, at).trim().isEmpty()) {
traceStarted = true;
list.add(token);
} else if (traceStarted) {
break;
}
}
return list;
}
private static void removeCommonFrames(final List<String> causeFrames, final List<String> wrapperFrames) {
int causeFrameIndex = causeFrames.size() - 1;
int wrapperFrameIndex = wrapperFrames.size() - 1;
while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
// Remove the frame from the cause trace if it is the same
// as in the wrapper trace
final String causeFrame = causeFrames.get(causeFrameIndex);
final String wrapperFrame = wrapperFrames.get(wrapperFrameIndex);
if (causeFrame.equals(wrapperFrame)) {
causeFrames.remove(causeFrameIndex);
}
causeFrameIndex--;
wrapperFrameIndex--;
}
}
}