什么是抑制异常?

发布于 2024-12-11 17:35:13 字数 450 浏览 4 评论 0原文

(用户soc)对回答一个关于尾部调用优化的问题提到Java 7由于“添加了 ARM”(支持 ARM CPU?),有一个名为“抑制异常”的新功能。

在这种情况下,什么是“受抑制的异常”?在其他情况下,“抑制的异常”是捕获然后忽略的异常(很少是一个好主意);这显然是不同的。

A comment (by user soc) on an answer to a question about tail call optimisation mentioned that Java 7 has a new feature called "suppressed exceptions", because of "the addition of ARM" (support for ARM CPUs?).

What is a "suppressed exception" in this context? In other contexts a "suppressed exception" would be an exception that was caught and then ignored (rarely a good idea); this is clearly something different.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

厌倦 2024-12-18 17:35:14

Java7之前;代码中抛出了异常,但不知何故被忽略了。

例如)

public class SuppressedExceptions {
  public static void main(String[] args) throws Exception {
    try {
        callTryFinallyBlock();
    } catch (Exception e) {
        e.printStackTrace(); **//Only Finally Exception is Caught**
    }
  }

  private static void callTryFinallyBlock() throws Exception {
    try 
    {
        throw new TryException(); **//This is lost**
    }
    finally
    {
        FinallyException fEx = new FinallyException();
        throw fEx;
    }
  }
}

class TryException extends Exception {
}

class FinallyException extends Exception {
}

JDK 7 中的 Throwable 类中添加了一个新的构造函数和两个新方法。
这些如下:

Throwable.getSupressed(); // Returns Throwable[]
Throwable.addSupressed(aThrowable);

通过这种新方法,我们也可以处理那些被抑制的异常。

public class SuppressedExceptions {
  public static void main(String[] args) throws Exception {
    try {
        callTryFinallyBlock();
    } catch (Exception e) {
        e.printStackTrace();
        for(Throwable t: e.getSuppressed())
        {
            t.printStackTrace();
        }
    }
  }

  private static void callTryFinallyBlock() throws Exception {
    Throwable t = null;
    try 
    {
        throw new TryException();
    }
    catch (Exception e) {
        t = e;
    }
    finally
    {
        FinallyException fEx = new FinallyException();
        if(t != null)fEx.addSuppressed(t);
        throw fEx;
    }
  }
}

class TryException extends Exception {
}

class FinallyException extends Exception {
}

在 Java7 中尝试资源; AutoCloseable::close() 处的异常
默认情况下与 try 异常一起添加为抑制异常。

另请注意,这与链式异常不同(随 JDK 1.4 引入,旨在以便轻松跟踪异常之间的因果关系。)

Before Java7; There are exceptions thrown in the code but were ignored somehow.

e.g.)

public class SuppressedExceptions {
  public static void main(String[] args) throws Exception {
    try {
        callTryFinallyBlock();
    } catch (Exception e) {
        e.printStackTrace(); **//Only Finally Exception is Caught**
    }
  }

  private static void callTryFinallyBlock() throws Exception {
    try 
    {
        throw new TryException(); **//This is lost**
    }
    finally
    {
        FinallyException fEx = new FinallyException();
        throw fEx;
    }
  }
}

class TryException extends Exception {
}

class FinallyException extends Exception {
}

A new constructor and two new methods were added to the Throwable class in JDK 7.
These are as below:

Throwable.getSupressed(); // Returns Throwable[]
Throwable.addSupressed(aThrowable);

with this new approach, we can handle those suppressed exception as well.

public class SuppressedExceptions {
  public static void main(String[] args) throws Exception {
    try {
        callTryFinallyBlock();
    } catch (Exception e) {
        e.printStackTrace();
        for(Throwable t: e.getSuppressed())
        {
            t.printStackTrace();
        }
    }
  }

  private static void callTryFinallyBlock() throws Exception {
    Throwable t = null;
    try 
    {
        throw new TryException();
    }
    catch (Exception e) {
        t = e;
    }
    finally
    {
        FinallyException fEx = new FinallyException();
        if(t != null)fEx.addSuppressed(t);
        throw fEx;
    }
  }
}

class TryException extends Exception {
}

class FinallyException extends Exception {
}

In Java7 try-with-resources; the exception at AutoCloseable::close()
is added as suppressed exception by default along with try exception.

Also aware that this is different from chained exceptions (were introduced with JDK 1.4 and were intended to make it possible to easily track causal relationships between exceptions.)

说谎友 2024-12-18 17:35:14

考虑到下面的代码:

public class MultipleExceptionsExample {

   static class IOManip implements Closeable{
       @Override
       public void close() {
           throw new RuntimeException("from IOManip.close");
       }
   }

   public static void main(String[] args) {
       try(IOManip ioManip = new IOManip()){
           throw new RuntimeException("from try!");
       }catch(Exception e){
           throw new RuntimeException("from catch!");
       }finally{
           throw new RuntimeException("from finally!");
       }
   }
}

对于所有行,您将得到: java.lang.RuntimeException: from finally!

删除 finally 块,您将得到: java.lang.RuntimeException : from catch!

删除 catch 块,您将得到:

Exception in thread "main" java.lang.RuntimeException: from try!
    Suppressed: java.lang.RuntimeException: from IOManip.close

Concedering the code below:

public class MultipleExceptionsExample {

   static class IOManip implements Closeable{
       @Override
       public void close() {
           throw new RuntimeException("from IOManip.close");
       }
   }

   public static void main(String[] args) {
       try(IOManip ioManip = new IOManip()){
           throw new RuntimeException("from try!");
       }catch(Exception e){
           throw new RuntimeException("from catch!");
       }finally{
           throw new RuntimeException("from finally!");
       }
   }
}

With all lines you will get: java.lang.RuntimeException: from finally!

Removing finally block you will get: java.lang.RuntimeException: from catch!

Removing catch block you will get:

Exception in thread "main" java.lang.RuntimeException: from try!
    Suppressed: java.lang.RuntimeException: from IOManip.close
雾里花 2024-12-18 17:35:14

抑制的异常 是 try-with-resources 语句中发生的其他异常 (在 Java 7 中引入)当 AutoCloseable 资源已关闭。由于关闭 AutoCloseable 资源时可能会发生多个异常,因此将附加异常附加到 主要异常作为抑制异常

查看一段 try-with-resources 示例代码的字节码,标准 JVM 异常处理程序 用于适应 try-with-resources 语义。

Suppressed exceptions are additional exceptions that occur within a try-with-resources statement (introduced in Java 7) when AutoCloseable resources are closed. Because multiple exceptions may occur while closing AutoCloseable resources, additional exceptions are attached to a primary exception as suppressed exceptions.

Looking at the bytecode of a piece of try-with-resources sample code, standard JVM exception handlers are used to accommodate the try-with-resources semantics.

GRAY°灰色天空 2024-12-18 17:35:14

您也可以在 Java 6 中抑制异常(涉及一些技巧),

我创建了一个实用程序,可以透明地处理 Java 1.6 和 Java 1.7 中的抑制异常。您可以找到实现 这里

您所需要的只是调用:

public static <T extends Throwable> T suppress(final T t, final Throwable suppressed) 

抑制异常,并

public static Throwable [] getSuppressed(final Throwable t) {

获取异常的抑制异常,以防有人仍然使用 Java 1.6

You can suppress Exceptions in Java 6 as well (a little trickery involved),

I created a utility that transparently handles suppressing exception in Java 1.6 and Java 1.7. You can find the implementation here

All you need is to call:

public static <T extends Throwable> T suppress(final T t, final Throwable suppressed) 

to supress a exception, and

public static Throwable [] getSuppressed(final Throwable t) {

to get the suppressed exceptions of a Exception, in case anybody still uses Java 1.6

一曲爱恨情仇 2024-12-18 17:35:14

ARM - 自动资源管理(从 Java 7 开始引入)

举一个非常简单的例子

static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

现在如果 readLine() 函数抛出异常,然后甚至 close() 函数[在finally块中]抛出异常,然后后者被赋予更高的优先级并被扔回调用函数。在这种情况下,由 readLine() 方法抛出的异常将被忽略/抑制。您可以将引发异常链接到异常中,并从finally 块中重新抛出异常。

java 7 以来,已经提供了检索被抑制的异常的功能。您可以在捕获的 throwable 对象上调用 public final java.lang.Throwable[] getSuppressed() 函数来查看抑制的异常。

对于例如。

static String readFirstLineFromFileWithFinallyBlock(String path)
        throws Exception {
    try (BufferedReader br = new BufferedReader(new FileReader(path));) {
        return br.readLine();
    }
}

现在,如果 br.readLine(); 行抛出 Exception1,然后假设在关闭资源时抛出 Exception2 [想象一下这发生在隐式finally 阻止 try-with-resource 语句创建],然后 Exception1 抑制 Exception2。

这里有几点需要注意 -

  1. 如果 try-with-resource 块抛出异常,即在资源实例化时,则 try 块将不会执行,并且将抛出相同的异常。
  2. 如果资源实例化成功,try块抛出异常,并且在关闭资源时抛出异常,然后关闭资源时抛出的异常被try块抛出的异常抑制。
  3. 如果您提供显式的finally块并且从该块抛出异常,它将抑制所有其他异常。 (这个显式的finally块在资源关闭后执行)

我已经在下面的文章中使用代码片段和输出编译了大多数可能的场景。

java 7 中的抑制异常

希望有所帮助。

ARM - Automatic Resource Management(Introduced since Java 7)

Take a very simple example

static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

Now if readLine() function throws Exception and then even close() function [in finally block] throws exception then the later is given more priority and is thrown back to the calling function. In this case the Exception thrown by the readLine() method is ignored/suppressed. You can chain the causing exception in your exception and rethrow your exception from finally block.

Since java 7 functionality has been provided to retrieve suppressed Exceptions. You can call public final java.lang.Throwable[] getSuppressed() function on the catched throwable object to view the suppressed Exceptions.

For Eg.

static String readFirstLineFromFileWithFinallyBlock(String path)
        throws Exception {
    try (BufferedReader br = new BufferedReader(new FileReader(path));) {
        return br.readLine();
    }
}

Now if br.readLine(); line throws Exception1 and then lets say Exception2 is thrown while closing the resource [Imagine this happening in an implicit finally block that try-with-resource statement creates] then Exception1 suppresses Exception2.

Few points to note here -

  1. If try-with-resource block throws exception i.e while resource instantiation then try block will not execute and the same exception will be thrown.
  2. If instantiation of resource is successful, try block throws an exception and exception is thrown while closing the resource then the exception thrown while closing resource is suppressed by the exception thrown from try block.
  3. If you provide explicit finally block and exception is thrown from that block it will suppress all other exception. (This explicit finally block executes after resources are closed)

I have compiled most of the possible scenarios with code snippets and output in following post.

Suppressed exceptions in java 7

Hope that helps.

荒芜了季节 2024-12-18 17:35:14

我认为这与“链式异常设施”有关。随着堆栈跟踪的发展,它将影响该工具处理异常的方式。随着时间的推移,作为一组链式异常的一部分的异常可以被抑制。有关更多详细信息,请参阅Throwable 文档

I think this has to do with the "chained exception facility". It will affect how an exception is handled by this facility as the stack trace evolves. Over time exceptions that are part of a group of chained exception can be suppressed. Look at the Throwable documentation for more details.

寄离 2024-12-18 17:35:13

为了澄清乔恩答案中的引用,一种方法(每次执行)只能抛出一个异常,但在 try-with-resources 的情况下,可能会抛出多个异常。例如,一个可能会被抛出到块中,另一个可能会从 try-with-resources 提供的隐式 finally 中抛出。

编译器必须确定其中哪一个“真正”抛出。它选择抛出显式代码(try 块中的代码)引发的异常,而不是隐式代码(finally 块)引发的异常。因此,隐式块中引发的异常将被抑制(忽略)。这只发生在多个异常的情况下。

To clarify the quote in Jon's answer, only one exception can be thrown by a method (per execution) but it is possible, in the case of a try-with-resources, for multiple exceptions to be thrown. For instance one might be thrown in the block and another might be thrown from the implicit finally provided by the try-with-resources.

The compiler has to determine which of these to "really" throw. It chooses to throw the exception raised in the explicit code (the code in the try block) rather than the one thrown by the implicit code (the finally block). Therefore the exception(s) thrown in the implicit block are suppressed (ignored). This only occurs in the case of multiple exceptions.

指尖微凉心微凉 2024-12-18 17:35:13

我相信评论者指的是一个异常,当它在 try-with-resources 块,在从 try 块抛出现有异常的上下文中:

与 try-with-resources 语句关联的代码块可能会引发异常。在 writeToFileZipFileContents 示例中,当尝试关闭 ZipFile 和 BufferedWriter 对象时,try 块可以引发异常,并且 try-with-resources 语句最多可以引发两个异常。如果 try 块中抛出了一个异常,并且 try-with-resources 语句中抛出了一个或多个异常,则 try-with-resources 语句中抛出的这些异常将被抑制,并且该块抛出的异常是第一个由 writeToFileZipFileContents 方法抛出。您可以通过从 try 块抛出的异常中调用 Throwable.getSuppressed 方法来检索这些被抑制的异常。

(这是引用链接页面中名为“抑制的异常”的部分。)

I believe the commenter is referring to is an exception which is semi-ignored when it's thrown within the implicit finally block of a try-with-resources block, in the context of an existing exception being thrown from the try block:

An exception can be thrown from the block of code associated with the try-with-resources statement. In the example writeToFileZipFileContents, an exception can be thrown from the try block, and up to two exceptions can be thrown from the try-with-resources statement when it tries to close the ZipFile and BufferedWriter objects. If an exception is thrown from the try block and one or more exceptions are thrown from the try-with-resources statement, then those exceptions thrown from the try-with-resources statement are suppressed, and the exception thrown by the block is the one that is thrown by the writeToFileZipFileContents method. You can retrieve these suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block.

(That's quoting a section called "Suppressed Exceptions" from the linked page.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文