ale*_*ail 14 java jvm exception java-7
好吧,我通过相关问题,我阅读了JDK 1.7的源代码,但我找不到答案.
在这个问题中,我想完全忽略fillInStackTrace
.
从JDK 1.4 initCause()
开始,添加了方法.例如,当您使用核心反射来调用该方法时,您会收到InvocationTargetException,其中包含具有目标异常的原因.
当我看到这个功能时,我也开始在这样的场景中使用它
try {
//contains some code that can throw new IOException();
}
catch(IOException e){
throw new RuntimeException(e);
}
Run Code Online (Sandbox Code Playgroud)
所以,我抓住了一个异常,我还没准备好在这里处理它并且我重新抛出新的异常,其中我有原始异常作为原因.在一些scenarious而不是RuntimeException,但我的自定义异常被使用,所以有时我也调用e.getCause()
,以便在外部块中正确处理此异常.
这是JDK 1.7之前的情况.我应该何时何地使用addSuppressed()
?我应该将上面的代码更改为
try {
//contains some code that can throw new IOException();
}
catch(IOException e){
RuntimeException re= new RuntimeException(e.getMessage());
re.addSuppressed(e);
throw re;
}
Run Code Online (Sandbox Code Playgroud)
作为奖励问题,为什么不addSuppressed()
返回Throwable
作为initCause()
确实允许throw (RuntimeException)new RuntimeException().initCause(e);
?例如,为什么我不能这样做?:
try {
//contains some code that can throw new IOException();
}
catch(IOException e){
throw (RuntimeException)new RuntimeException(e.getMessage()).addSuppressed(e);
}
Run Code Online (Sandbox Code Playgroud)
我把答案提取到一个单独的帖子.
ale*_*ail 16
一般情况下,addSuppressed()
应该使用Throwable 方法,在某种程度上我们有 并行执行可以产生异常,在被抑制的情况下.我找到了两个例子;
当调用代码看到原始异常(在try或catch块中)和finally块中发生的异常时,尝试使用资源块(try-finally块).
无论当前项目的操作是否成功,我们应该继续执行下一个项目的批处理作业(批量操作)
在获取详细信息之前,正如@sarelbotha所说,在我的情况下,我只需要将原始异常包装为我的新异常的原因.
try-finally块中的默认行为,我们有2个例外,原始异常被抑制,我们只看到finally块的异常.如果我们按顺序使用finally块来关闭资源而不是我们真正希望看到的原始异常,但是我们也希望看到来自finally块的异常,这会关闭我们的资源并失败.
从版本7开始,该平台支持抑制异常的概念(与try-with-resources语句一起使用).在堆栈跟踪下方打印出为了传递异常而被抑制的任何异常.
http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html#printStackTrace%28%29
首先应该阅读有关try-with-resource的新功能.你可以在这里阅读http://www.baptiste-wicht.com/2010/08/java-7-try-with-resources-statement/,例如或者这里什么是Java 7 try-with-resources字节码等效使用的try-catch-最后?.简而言之,在某种意义上,你可以并行地使用2个Throwable,通常来自你尝试阻止和你的finally块.旧的try-catch语义将从finally块中返回异常,从try块中抑制异常(或从catch块中重新抛出异常).新的try-with-resource功能使您可以获得两个异常.更重要的是,您将收到原始异常,其中来自finally块的异常将被抑制
请注意,当一个异常导致另一个异常时,通常会捕获第一个异常,然后在响应中抛出第二个异常.换句话说,两个例外之间存在因果关系.相反,在某些情况下,可以在兄弟代码块中抛出两个独立的异常,特别是在try-with-resources语句的try块和编译器生成的finally块中,它关闭资源.在这些情况下,只能传播一个抛出的异常.在try-with-resources语句中,当存在两个此类异常时,将传播源自try块的异常,并将finally块中的异常添加到由try块中的异常抑制的异常列表中.作为异常展开堆栈,它可以累积多个抑制异常.
例:
public class TestClass {
static class ResourceA implements AutoCloseable{
public void read() throws Exception{
throw new Exception("ResourceA read exception");
}
@Override
public void close() throws Exception {
throw new Exception("ResourceA close exception");
}
};
static class ResourceB implements AutoCloseable{
public void read() throws Exception{
throw new Exception("ResourceB read exception");
}
@Override
public void close() throws Exception {
throw new Exception("ResourceB close exception");
}
};
//a test method
public static void test() throws Exception{
try (ResourceA a = new ResourceA();
//ResourceB b = new ResourceB()
) {
a.read();
//b.read();
} catch (Exception e) {
throw e;
}
}
public static void main(String[] args) throws Exception {
test();
}
Run Code Online (Sandbox Code Playgroud)
}
输出如下:
Exception in thread "main" java.lang.Exception: ResourceA read exception
at TestClass$ResourceA.read(TestClass.java:6)
at TestClass.test(TestClass.java:29)
at TestClass.main(TestClass.java:39)
Suppressed: java.lang.Exception: ResourceA close exception
at TestClass$ResourceA.close(TestClass.java:10)
at TestClass.test(TestClass.java:31)
... 1 more
Run Code Online (Sandbox Code Playgroud)
批量作业(批量操作).
好吧,我在try-with-resources之外找到了一些这种方法的用法.下面是源代码java.net.URLClassLoader.close
Run Code Online (Sandbox Code Playgroud)public void close() throws IOException { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission(new RuntimePermission("closeClassLoader")); } List<IOException> errors = ucp.closeLoaders(); // now close any remaining streams. synchronized (closeables) { Set<Closeable> keys = closeables.keySet(); for (Closeable c : keys) { try { c.close(); } catch (IOException ioex) { errors.add(ioex); } } closeables.clear(); } if (errors.isEmpty()) { return; } IOException firstex = errors.remove(0); // Suppress any remaining exceptions for (IOException error: errors) { **firstex.addSuppressed(error);** } throw firstex; }
通常,这种方法可以用于批处理作业(批量操作),当我们应该继续下一个项目(在本例中关闭下一个打开的流)时,无论当前项目的操作是否成功.以这种方式,我们已经如前所述,在某种程度上并行执行可以产生异常,在被抑制的情况下.在这种情况下,我们应该使用上面的方法来抛出异常,并在其中保留被抑制的异常.
归档时间: |
|
查看次数: |
6927 次 |
最近记录: |