Throwable.getStackTrace()
스택 트레이스를 나타내는 문자열로 결과를 변환하는 가장 쉬운 방법은 무엇입니까 ?
Throwable.getStackTrace()
스택 트레이스를 나타내는 문자열로 결과를 변환하는 가장 쉬운 방법은 무엇입니까 ?
답변:
다음 방법을 사용하여 Exception
스택 추적을 로 변환 할 수 있습니다 String
. 이 클래스는 많이 사용되는 오픈 소스가있는 가장 일반적인 종속 라이브러리 인 Apache commons-lang으로 제공됩니다.
org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)
org.apache.commons.lang3.exception.ExceptionUtils
있습니다.
Throwable.printStackTrace(PrintWriter pw)
스택 추적을 적절한 기록기에 보내려면 사용하십시오 .
import java.io.StringWriter;
import java.io.PrintWriter;
// ...
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
String sStackTrace = sw.toString(); // stack trace as a string
System.out.println(sStackTrace);
StringWriter
and 를 닫지 않아야 PrintWriter
합니까?
이것은 작동해야합니다 :
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
printStackTrace
문자열을 반환하고 사용자에게 인쇄할지 여부를 결정합니다 :)
printXXX()
XXX를 인쇄해야합니다.
Android 용으로 개발하는 경우 훨씬 쉬운 방법은 다음을 사용하는 것입니다.
import android.util.Log;
String stackTrace = Log.getStackTraceString(exception);
형식은 getStacktrace와 동일합니다. 예를 들어
09-24 16:09:07.042: I/System.out(4844): java.lang.NullPointerException 09-24 16:09:07.042: I/System.out(4844): at com.temp.ttscancel.MainActivity.onCreate(MainActivity.java:43) 09-24 16:09:07.042: I/System.out(4844): at android.app.Activity.performCreate(Activity.java:5248) 09-24 16:09:07.043: I/System.out(4844): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread.access$800(ActivityThread.java:139) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210) 09-24 16:09:07.043: I/System.out(4844): at android.os.Handler.dispatchMessage(Handler.java:102) 09-24 16:09:07.043: I/System.out(4844): at android.os.Looper.loop(Looper.java:136) 09-24 16:09:07.044: I/System.out(4844): at android.app.ActivityThread.main(ActivityThread.java:5097) 09-24 16:09:07.044: I/System.out(4844): at java.lang.reflect.Method.invokeNative(Native Method) 09-24 16:09:07.044: I/System.out(4844): at java.lang.reflect.Method.invoke(Method.java:515) 09-24 16:09:07.044: I/System.out(4844): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 09-24 16:09:07.044: I/System.out(4844): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
Log.e("TAG", "My message", new Throwable());
Throwables
수업실제 Throwable
인스턴스 가있는 경우 Google Guava는를 제공합니다 Throwables.getStackTraceAsString()
.
예:
String s = Throwables.getStackTraceAsString ( myException ) ;
경고 : 원인을 포함하지 않습니다 (일반적으로 유용한 비트입니다).
public String stackTraceToString(Throwable e) {
StringBuilder sb = new StringBuilder();
for (StackTraceElement element : e.getStackTrace()) {
sb.append(element.toString());
sb.append("\n");
}
return sb.toString();
}
String.format("%n")
대신 또는 비슷한 것을 사용하십시오 "\n"
.
public static String getStackTrace(Throwable t) {
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
StringWriter
와 PrintWriter
객체가 close
d PrintWriter
이어야한다고 지적하고 StringWriter
싶습니다.
다음 코드를 사용하면 String
log4J 또는 심지어 API를 사용하지 않고도 전체 stackTrace를 형식 으로 가져올 수 있습니다 java.util.Logger
.
catch (Exception e) {
StackTraceElement[] stack = e.getStackTrace();
String exception = "";
for (StackTraceElement s : stack) {
exception = exception + s.toString() + "\n\t\t";
}
System.out.println(exception);
// then you can send the exception string to a external file.
}
다음은 코드에 직접 복사하여 붙여 넣을 수있는 버전입니다.
import java.io.StringWriter;
import java.io.PrintWriter;
//Two lines of code to get the exception into a StringWriter
StringWriter sw = new StringWriter();
new Throwable().printStackTrace(new PrintWriter(sw));
//And to actually print it
logger.info("Current stack trace is:\n" + sw.toString());
또는 캐치 블록에서
} catch (Throwable t) {
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
logger.info("Current stack trace is:\n" + sw.toString());
}
Throwable
정의 된 곳이 맞습니까?
Arrays.toString(thrown.getStackTrace())
결과를 문자열로 변환하는 가장 쉬운 방법입니까? 프로그램에서 이것을 사용하여 스택 추적을 인쇄합니다.
LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});
문자열로 스택 추적 인쇄
import java.io.PrintWriter;
import java.io.StringWriter;
public class StackTraceUtils {
public static String stackTraceToString(StackTraceElement[] stackTrace) {
StringWriter sw = new StringWriter();
printStackTrace(stackTrace, new PrintWriter(sw));
return sw.toString();
}
public static void printStackTrace(StackTraceElement[] stackTrace, PrintWriter pw) {
for(StackTraceElement stackTraceEl : stackTrace) {
pw.println(stackTraceEl);
}
}
}
인스턴스를 만들지 않고 현재 스레드 스택 추적을 인쇄하려고 할 때 유용 Throwable
하지만 새 Throwable
스택 을 만들고 스택 추적을 얻는 것이 실제로 호출하는 것보다 빠르고 저렴하다는 점에 유의하십시오 Thread.getStackTrace
.
private String getCurrentStackTraceString() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
return Arrays.stream(stackTrace).map(StackTraceElement::toString)
.collect(Collectors.joining("\n"));
}
첫 번째 주석 세트의 영리한 저격은 매우 재미 있었지만 실제로는하려는 일에 달려 있습니다. 올바른 라이브러리가 없다면 (D. Wroblewski의 답변에서와 같이) 3 줄의 코드가 완벽합니다. OTOH, apache.commons 라이브러리가 이미 있다면 (대부분의 큰 프로젝트처럼) Amar의 대답은 더 짧습니다. 라이브러리를 가져 와서 올바르게 설치하는 데 10 분이 걸릴 수 있습니다 (무엇을하고 있는지 아는 경우 1 개 미만). 그러나 시계가 똑딱 거리므로 여유 시간이 없을 수 있습니다. Jarek Przygódzki는 흥미로운 중첩을 가지고있었습니다.
그러나 전체 스택 추적, 중첩 및 전체 가 필요한 경우 어떻게 해야합니까? 이 경우 비밀은 apache.common의 getFullStackTrace를 사용하는 것입니다 ( http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html 참조) # getFullStackTrace % 28java.lang.Throwable % 29 )
베이컨을 구했습니다. 힌트를 주셔서 감사합니다.
Apache Commons Lang 3.4 ( JavaDoc )의 코드 :
public static String getStackTrace(final Throwable throwable) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true);
throwable.printStackTrace(pw);
return sw.getBuffer().toString();
}
다른 답변에 차이가 있다는 점이다 이 사용하는 autoFlush
온 PrintWriter
.
java.io.*
그것 없이는 이렇게 할 수 있습니다.
String trace = e.toString() + "\n";
for (StackTraceElement e1 : e.getStackTrace()) {
trace += "\t at " + e1.toString() + "\n";
}
그리고 trace
변수는 스택 추적을 유지합니다. 출력은 또한 초기 원인을 보유하며 출력은printStackTrace()
예를 들면 다음과 printStackTrace()
같습니다.
java.io.FileNotFoundException: / (Is a directory)
at java.io.FileOutputStream.open0(Native Method)
at java.io.FileOutputStream.open(FileOutputStream.java:270)
at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
at java.io.FileOutputStream.<init>(FileOutputStream.java:101)
at Test.main(Test.java:9)
trace
에 인쇄 할 때 문자열 보유stdout
java.io.FileNotFoundException: / (Is a directory)
at java.io.FileOutputStream.open0(Native Method)
at java.io.FileOutputStream.open(FileOutputStream.java:270)
at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
at java.io.FileOutputStream.<init>(FileOutputStream.java:101)
at Test.main(Test.java:9)
스칼라 버전
def stackTraceToString(e: Exception): String = {
import java.io.PrintWriter
val sw = new StringWriter()
e.printStackTrace(new PrintWriter(sw))
sw.toString
}
Java 8을 사용하는 경우 이것을 시도하십시오
Arrays.stream(e.getStackTrace())
.map(s->s.toString())
.collect(Collectors.joining("\n"));
다음 과 같이 getStackTrace()
제공되는 기능 코드를 찾을 수 있습니다 Throwable.java
.
public StackTraceElement[] getStackTrace() {
return getOurStackTrace().clone();
}
그리고이를 위해 다음 StackTraceElement
과 같이 제공 toString()
됩니다.
public String toString() {
return getClassName() + "." + methodName +
(isNativeMethod() ? "(Native Method)" :
(fileName != null && lineNumber >= 0 ?
"(" + fileName + ":" + lineNumber + ")" :
(fileName != null ? "("+fileName+")" : "(Unknown Source)")));
}
StackTraceElement
"\ n"과 함께 가입하십시오 .
Gala의 답변에 대한 확장은 예외의 원인도 포함합니다.
private String extrapolateStackTrace(Exception ex) {
Throwable e = ex;
String trace = e.toString() + "\n";
for (StackTraceElement e1 : e.getStackTrace()) {
trace += "\t at " + e1.toString() + "\n";
}
while (e.getCause() != null) {
e = e.getCause();
trace += "Cause by: " + e.toString() + "\n";
for (StackTraceElement e1 : e.getStackTrace()) {
trace += "\t at " + e1.toString() + "\n";
}
}
return trace;
}
Java 8 Stream API 를 사용 하면 다음과 같은 작업을 수행 할 수 있습니다.
Stream
.of(throwable.getStackTrace())
.map(StackTraceElement::toString)
.collect(Collectors.joining("\n"));
스택 추적 요소의 배열을 가져 와서 문자열로 변환하고 여러 줄 문자열로 결합합니다.
스택 추적을 동봉 된 여러 줄 문자열로 변환하는 oneliner :
Stream.of(e.getStackTrace()).map((a) -> a.toString()).collect(Collectors.joining("\n", "[", "]"))
"있는 그대로"로거에 전달하기 쉽습니다.
printStackTrace()
다음 과 다른 것을 얻습니다. 여기 에서 느슨하게 할 것입니다. 1) 예외가 발생했습니다. 2) 원인과 스택
printStackTrace()
문제의 일부가 아니 었기 때문에 그 차이는 꽤 예상 됩니다.
외부 라이브러리를 사용하지 않고 Android 용으로 개발하지 않는 경우 다음 과 같이 '확장'방법을 만들 수 있습니다 .
public static String getStackTraceString(Throwable e) {
return getStackTraceString(e, "");
}
private static String getStackTraceString(Throwable e, String indent) {
StringBuilder sb = new StringBuilder();
sb.append(e.toString());
sb.append("\n");
StackTraceElement[] stack = e.getStackTrace();
if (stack != null) {
for (StackTraceElement stackTraceElement : stack) {
sb.append(indent);
sb.append("\tat ");
sb.append(stackTraceElement.toString());
sb.append("\n");
}
}
Throwable[] suppressedExceptions = e.getSuppressed();
// Print suppressed exceptions indented one level deeper.
if (suppressedExceptions != null) {
for (Throwable throwable : suppressedExceptions) {
sb.append(indent);
sb.append("\tSuppressed: ");
sb.append(getStackTraceString(throwable, indent + "\t"));
}
}
Throwable cause = e.getCause();
if (cause != null) {
sb.append(indent);
sb.append("Caused by: ");
sb.append(getStackTraceString(cause, indent));
}
return sb.toString();
}
오래된 질문이지만 모든 스택을 인쇄하고 싶지 않은 특별한 경우를 추가하고 싶습니다. 특정 클래스 또는 패키지를 제외하고 실제로 관심이없는 부분을 제거하여 .
PrintWriter
사용하는 대신 SelectivePrintWriter
:
// This filters out this package and up.
String packageNameToFilter = "org.springframework";
StringWriter sw = new StringWriter();
PrintWriter pw = new SelectivePrintWriter(sw, packageNameToFilter);
e.printStackTrace(pw);
String sStackTrace = sw.toString();
System.out.println(sStackTrace);
를 Where SelectivePrintWriter
클래스는 다음과 같이 주어진다 :
public class SelectivePrintWriter extends PrintWriter {
private boolean on = true;
private static final String AT = "\tat";
private String internal;
public SelectivePrintWriter(Writer out, String packageOrClassName) {
super(out);
internal = "\tat " + packageOrClassName;
}
public void println(Object obj) {
if (obj instanceof String) {
String txt = (String) obj;
if (!txt.startsWith(AT)) on = true;
else if (txt.startsWith(internal)) on = false;
if (on) super.println(txt);
} else {
super.println(obj);
}
}
}
이 클래스는 Regex contains
또는 다른 기준에 따라 쉽게 필터링 할 수 있습니다 . 또한 Throwable
구현 세부 사항에 따라 다릅니다 (변경되지는 않지만 여전히).
import java.io.PrintWriter;
import java.io.StringWriter;
public class PrintStackTrace {
public static void main(String[] args) {
try {
int division = 0 / 0;
} catch (ArithmeticException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
System.out.println(exceptionAsString);
}
}
}
프로그램을 실행하면 비슷한 결과가 나타납니다.
java.lang.ArithmeticException: / by zero
at PrintStackTrace.main(PrintStackTrace.java:9)
경고 : 이것은 약간 벗어난 주제 일 수 있지만 오 잘 ...;)
원래의 포스터 이유 가 스택 추적을 문자열로 문자열로 원했던 이유를 모르겠습니다 . 스택 추적이 SLF4J / Logback LOG로 끝나야하지만 예외가 발생하지 않아야하는 경우 여기에 내가하는 일이 있습니다.
public void remove(List<String> ids) {
if(ids == null || ids.isEmpty()) {
LOG.warn(
"An empty list (or null) was passed to {}.remove(List). " +
"Clearly, this call is unneccessary, the caller should " +
"avoid making it. A stacktrace follows.",
getClass().getName(),
new Throwable ("Stacktrace")
);
return;
}
// actual work, remove stuff
}
외부 라이브러리가 필요하지 않기 때문에 좋아합니다 (물론 대부분의 장소에 기록되는 로깅 백엔드 제외).
몇 가지 옵션
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Google Guava lib 사용
String stackTrace = Throwables.getStackTraceAsString ( myException ) ;
org.apache.commons.lang.exception.ExceptionUtils.getStackTrace (Throwable)