Stack Trace is not fully maintained when rethrowing exception in java
本问题已经有最佳答案,请猛点这里访问。
当异常在下面的代码中重新引发时,原始堆栈跟踪不会保留。
在第148行和第150行中引发异常。重新刷新后,第150行是指定的异常源。
我必须做什么来保持原始堆栈跟踪?
代码:
1 2 3 4 5 6 7 8 9 | try { content = (InputStream) conn.getContent(); //line 148 } catch (IOException e) { throw new RuntimeException(e); //line 150 } |
原始堆栈跟踪:
1 | (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)] |
重发后的堆栈跟踪:
1 | (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)] |
您的代码不会重新引发原始异常,而是抛出
当捕获RuntimeException或在引发RuntimeException之前,将RuntimeException的堆栈跟踪设置为来自原始异常的堆栈跟踪。
"问题"是您没有重新引发异常。相反,你提出了一个新的例外。如果你真的再次提出这样的例外:
1 2 3 4 5 |
您将发现堆栈跟踪被保留。
如果您在现代JVM上使用
有一种方法可以将堆栈跟踪从一个异常拼接到另一个异常。
1 2 3 4 5 6 7 | try { content = (InputStream) conn.getContent(); } catch (IOException e) { RuntimeException re = new RuntimeException(e); re.setStackTrace(e.getStackTrace()); throw re; } |
然而,我个人认为这不是一个好主意。虽然
您必须遵循引起丢弃的引用才能获得原始stacktrace。例如
1 2 3 4 5 6 7 8 9 | public static StackTraceElement[] getCausingStacktrace(Throwable throwable) { if (throwable == null) { throw new NullPointerException(); } while (throwable != null) { throwable = throwable.getCause(); } return throwable.getStacktrace(); } |
StackTrace保留。
你必须从
此功能是调用异常链接。
如果只需要原始stacktrace,请不要捕获它。另一方面,出于某种原因,我假设您将它包装在运行时异常中。您可以使用