当在下面的代码中重新抛出异常时,不保留原始堆栈跟踪。
在第148行&在第150行重新抛出。在Rethrowing之后,第150行是指定的例外来源。
我该怎么做才能保留原始的堆栈跟踪?
代码:
try {
content = (InputStream) conn.getContent(); //line 148
} catch (IOException e) {
throw new RuntimeException(e); //line 150
}
原始堆栈跟踪:
(java.lang.StackTraceElement[]) [sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source), java.net.URLConnection.getContent(Unknown Source), com.mycompany.myapp.client.services.impl.AbstractClientService.getResponseEle(AbstractClientService.java:148), com.mycompany.myapp.client.services.impl.AbstractClientService.getResponseEleWithCheck(AbstractClientService.java:162), com.mycompany.myapp.client.services.impl.AbstractClientService.getResponseEleWithCheck(AbstractClientService.java:158), com.mycompany.myapp.client.services.impl.InfoQueryClientServiceImpl.getFileOnTmpList(InfoQueryClientServiceImpl.java:84), com.mycompany.myapp.client.myappClient.getFileOnTmpList(myappClient.java:196), com.mycompany.myapp.client.model.Model.updateStudyInfos(Model.java:96), com.mycompany.myapp.client.model.Model.instantiateSingleton(Model.java:46), com.mycompany.myapp.applet.MainApplet.addMainPanel(MainApplet.java:106), com.mycompany.myapp.applet.MainApplet.createUIPanel(MainApplet.java:76), com.mycompany.myapp.applet.MainApplet.init(MainApplet.java:58), com.sun.deploy.uitoolkit.impl.awt.AWTAppletAdapter.init(Unknown Source), sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source), java.lang.Thread.run(Unknown Source)]
重新抛出后的堆栈跟踪:
(java.lang.StackTraceElement[]) [com.mycompany.myapp.client.services.impl.AbstractClientService.getResponseEle(AbstractClientService.java:150), com.mycompany.myapp.client.services.impl.AbstractClientService.getResponseEleWithCheck(AbstractClientService.java:162), com.mycompany.myapp.client.services.impl.AbstractClientService.getResponseEleWithCheck(AbstractClientService.java:158), com.mycompany.myapp.client.services.impl.InfoQueryClientServiceImpl.getFileOnTmpList(InfoQueryClientServiceImpl.java:84), com.mycompany.myapp.client.myappClient.getFileOnTmpList(myappClient.java:196), com.mycompany.myapp.client.model.Model.updateStudyInfos(Model.java:96), com.mycompany.myapp.client.model.Model.instantiateSingleton(Model.java:46), com.mycompany.myapp.applet.MainApplet.addMainPanel(MainApplet.java:106), com.mycompany.myapp.applet.MainApplet.createUIPanel(MainApplet.java:76), com.mycompany.myapp.applet.MainApplet.init(MainApplet.java:58), com.sun.deploy.uitoolkit.impl.awt.AWTAppletAdapter.init(Unknown Source), sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source), java.lang.Thread.run(Unknown Source)]
答案 0 :(得分:3)
您的代码不会重新抛出原始异常,但会抛出RuntimeException
的新实例,该实例在创建时填充了堆栈跟踪。
当您捕获RuntimeException或时,您可以调用Throwable.getCause().getStackTrace()
在抛出RuntimeException之前,将RuntimeException的堆栈跟踪设置为原始异常之一。
答案 1 :(得分:2)
“问题”是你不会重新抛出异常。而是你抛出一个新的异常。如果您确实重新抛出了这样的异常:
try {
content = (InputStream) conn.getContent();
} catch (IOException e) {
throw e;
}
您会发现堆栈跟踪已保留。
如果在现代JVM上使用Throwable.printStackTrace()
,它将显示链式异常及其(唯一)堆栈帧。换句话说,保留原始异常中的信息。
有一种方法可以将堆栈跟踪从一个异常拼接到另一个异常。
try {
content = (InputStream) conn.getContent();
} catch (IOException e) {
RuntimeException re = new RuntimeException(e);
re.setStackTrace(e.getStackTrace());
throw re;
}
但是,我个人认为这不是一个好主意。虽然RuntimeException
的行号现在与原始异常相同,但是您会看到连接对象的异常情况,似乎抛出RuntimeException
,代码表明这不会发生。我认为最好以正常方式链接异常,并让程序员正确读取链接异常的堆栈跟踪。
答案 2 :(得分:0)
如果您只想要原始堆栈跟踪,请不要捕获它。另一方面,我假设您将其包装在运行时异常中是有原因的。您可以使用getCause()
答案 3 :(得分:0)
保留堆栈跟踪。
您必须从RuntimeException
获取原因并从那里获取堆栈跟踪以获取原点。
此功能称为异常链接。
答案 4 :(得分:0)
你必须遵循引起Throwables的引用来获得原始的堆栈跟踪。例如
public static StackTraceElement[] getCausingStacktrace(Throwable throwable) {
if (throwable == null) {
throw new NullPointerException();
}
while (throwable != null) {
throwable = throwable.getCause();
}
return throwable.getStacktrace();
}