当前位置:首页 > 科技  > 软件

一篇文章彻底理解 Java 的 Suppressed exceptions 机制

来源: 责编: 时间:2024-05-17 17:47:19 103观看
导读1. 前言在查看 JAVA 应用抛出的异常堆栈以排查问题时,我们有时会看到所谓 suppressed exceptions,即被抑制的异常。理解 suppressed exceptions 的原理,对我们分析问题的底层真实原因大有裨益。所以本文分析总结下 Java

1. 前言

在查看 JAVA 应用抛出的异常堆栈以排查问题时,我们有时会看到所谓 suppressed exceptions,即被抑制的异常。理解 suppressed exceptions 的原理,对我们分析问题的底层真实原因大有裨益。所以本文分析总结下 Java 中的 suppressed exceptions。f6928资讯网——每日最新资讯28at.com

2. suppressed exceptions 机制总结

  • 简单来说,suppressed exceptions 是 JVM 中一个真实发生了的异常,但由于某些原因被 JVM 忽略/抑制了;
  • 一个常见的异常被忽略/抑制的场景是 try-catch-finally 代码块:由于无论 try 代码块是否正常执行结束,finally 代码块都会执行,所以如果 try 代码块和 finally 代码块都抛出异常时,为在打印的异常堆栈中完整还原异常现场,代码中可以做特殊处理(具体的处理方式见后文),以将两个异常都打印,并标记 try 中的异常为 suppressed;(用户需要对异常代码做处理);
  • 另一个常见的异常被忽略的场景是 try-with-resources 代码块:java7 引进了 try-with-resources 代码块和 AutoCloseable 接口来管理资源,当 try-with-resources 底层的业务逻辑代码执行完毕时,无论其执行是否正常结束,jvm 都会自动关闭 try 中指定的 AutoCloseable 资源,以避免资源泄露,如果业务逻辑代码的处理和 AutoCloseable 资源的关闭都发生了异常,此时 jvm 会将两个异常都打印,并标记关闭 AutoCloseable 资源触发的异常为try 中的异常为 suppressed;(用户不用做特殊处理);
  • 所以,为有效利用 suppressed exceptions 机制妥善打印异常堆栈以辅助问题排查,从 Java 7 开始, 我们可以使用 Throwable 类的如下方法来处理 suppressed exceptions: 即 java.lang.Throwable#addSuppressed 和java.lang.Throwable#getSuppressed
  • A suppressed exception is an exception that is thrown but somehow ignored;
  • A common scenario for this is the try-catch-finally block: when the finally block throws an exception,any exception originally thrown in the try block is then suppressed;
  • Another common scenario is the try-with-resources block:Java 7 introduced the try-with-resources construct and the AutoCloseable interface for resource management,when exception occurs both in the business processing and resource closing,it’s the exception thrown in the close method that’s suppressed;
  • Starting with Java 7, we can now use two methods on the Throwable class to handle our suppressed exceptions: addSuppressed and getSuppressed.

3 suppressed exceptions 机制 细节- try-catch-finally 代码块

  • 当 finally 代码块没有使用 java.lang.Throwable#addSuppressed 对异常进行特殊处理时,如果 try 代码块和 finally 代码块都抛出异常,打印的异常堆栈的示例如下,可以看到,没有打印try 中的异常,而仅仅打印了 finally 中的异常,此时用户显然无法轻易获知异常的真实原因;
java.lang.NullPointerExceptionat com.keep.bdata.SuppressedExceptionsDemo.demoExceptionWithNoSuppress(SuppressedExceptionsDemo.java:21)at com.keep.bdata.SuppressedExceptionsDemo.givenNonExistentFileName_whenAttemptFileOpen_thenNullPointerException(SuppressedExceptionsDemo.java:12)

图片图片f6928资讯网——每日最新资讯28at.com

  • 当 finally 代码块使用 java.lang.Throwable#addSuppressed 对异常进行了特殊处理时,如果 try 代码块和 finally 代码块都抛出异常,打印的异常堆栈的示例如下,可以看到,try 中的异常和 finally 中的异常都被打印了,且 try 中的异常被标记为 suppressed exceptions, 如果用户理解 suppressed exceptions 的机制,通过这些异常堆栈,显然可以轻松获知异常的真实原因;
java.lang.NullPointerException	at com.keep.bdata.SuppressedExceptionsDemo.demoExceptionWithSuppressed(SuppressedExceptionsDemo.java:38)	at com.keep.bdata.SuppressedExceptionsDemo.givenNonExistentFileName_whenAttemptFileOpen_thenNullPointerException_withSuppressed(SuppressedExceptionsDemo.java:27)	Suppressed: java.io.FileNotFoundException: /non-existent-path/non-existent-file.txt (系统找不到指定的路径。)		at java.io.FileInputStream.open0(Native Method)		at java.io.FileInputStream.open(FileInputStream.java:195)		at java.io.FileInputStream.<init>(FileInputStream.java:138)		at java.io.FileInputStream.<init>(FileInputStream.java:93)		at com.keep.bdata.SuppressedExceptionsDemo.demoExceptionWithSuppressed(SuppressedExceptionsDemo.java:33)

图片图片f6928资讯网——每日最新资讯28at.com

4 suppressed exceptions 机制 细节 - try-with-resources 代码块

  • java7 引进了 try-with-resources 代码块和 AutoCloseable 接口来管理资源,当 try-with-resources 底层的业务逻辑代码执行完毕时,无论其执行是否正常结束,jvm 都会自动关闭 try 中指定的 AutoCloseable 资源,以避免资源泄露;
  • 如果业务逻辑代码的处理和 AutoCloseable 资源的关闭都发生了异常,此时 jvm 会将两个异常都打印,并标记关闭 AutoCloseable 资源触发的异常为try 中的异常为 suppressed,打印的异常堆栈的示例如下,如果用户理解 suppressed exceptions 的机制,通过这些异常堆栈,显然可以轻松获知异常的真实原因;
  • 注意这是jvm自己实现的,用户不需要对代码做特殊处理;
java.lang.IllegalArgumentException: Thrown from processSomething()	at com.keep.bdata.TryWithResourceDemo$ExceptionalResource.processSomething(TryWithResourceDemo.java:23)	at com.keep.bdata.TryWithResourceDemo.demoExceptionalResource(TryWithResourceDemo.java:17)	at com.keep.bdata.TryWithResourceDemo.givenNonExistentFileName_whenAttemptFileOpen_thenNullPointerException_suppressed(TryWithResourceDemo.java:12)	Suppressed: java.lang.NullPointerException: Thrown from close()		at com.keep.bdata.TryWithResourceDemo$ExceptionalResource.close(TryWithResourceDemo.java:28)		at com.keep.bdata.TryWithResourceDemo.demoExceptionalResource(TryWithResourceDemo.java:18)

图片图片f6928资讯网——每日最新资讯28at.com

5 suppressed exceptions 机制完整示例代码

  • suppressed exceptions 机制的完整示例代码如下(try-catch-finally ):
package com.keep.bdata;import org.junit.jupiter.api.Test;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;publicclass SuppressedExceptionsDemo {    @Test    public void givenNonExistentFileName_whenAttemptFileOpen_thenNullPointerException() throws IOException {        demoExceptionWithNoSuppress("/non-existent-path/non-existent-file.txt");    }    public static void demoExceptionWithNoSuppress(String filePath) throws IOException {        FileInputStream fileIn = null;        try {            fileIn = new FileInputStream(filePath);        } catch (FileNotFoundException e) {            thrownew IOException(e);        } finally {            fileIn.close();        }    }    @Test    public void givenNonExistentFileName_whenAttemptFileOpen_thenNullPointerException_withSuppressed() throws IOException{        demoExceptionWithSuppressed("/non-existent-path/non-existent-file.txt");    }    public static void demoExceptionWithSuppressed(String filePath) throws IOException {        Throwable firstException = null;        FileInputStream fileIn = null;        try {            fileIn = new FileInputStream(filePath);        } catch (IOException e) {            firstException = e;        } finally {            try {                fileIn.close();            } catch (NullPointerException npe) {                if (firstException != null) {                    npe.addSuppressed(firstException);                }                throw npe;            }        }    }}
  • suppressed exceptions 机制的完整示例代码如下(try-with-resources 完整示例代码):
package com.keep.bdata;import org.junit.jupiter.api.Test;publicclass TryWithResourceDemo  {    @Test    public void givenNonExistentFileName_whenAttemptFileOpen_thenNullPointerException_suppressed() throws Exception {        demoExceptionalResource();    }    public void demoExceptionalResource() throws Exception {        try (ExceptionalResource exceptionalResource = new ExceptionalResource()) {            exceptionalResource.processSomething();        }    }    class ExceptionalResource implements AutoCloseable {        public void processSomething() {            thrownew IllegalArgumentException("Thrown from processSomething()");        }        @Override        public void close() throws Exception {            thrownew NullPointerException("Thrown from close()");        }    }


f6928资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-88927-0.html一篇文章彻底理解 Java 的 Suppressed exceptions 机制

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 一文彻底搞明白享元模式

下一篇: 在.Net开发中使用Math.NET Filtering开源库实现巴特沃斯滤波器

标签:
  • 热门焦点
Top