program story

억제 된 예외 란 무엇입니까?

inputbox 2020. 11. 14. 10:10
반응형

억제 된 예외 란 무엇입니까?


(사용자에 의한 의견 SOC 온) 대답꼬리를 호출 최적화에 대한 질문이 자바 7이 때문에 "ARM의 추가"의 "억제 예외"라는 새로운 기능이 언급 (ARM CPU에 대한 지원을?).

이 컨텍스트에서 "억제 된 예외"란 무엇입니까? 다른 컨텍스트에서 "억제 된 예외"는 포착 된 후 무시 된 예외입니다 (드물게 좋은 생각입니다). 이것은 분명히 다른 것입니다.


주석 작성자가 언급하는 예외는 블록에서 throw되는 기존 예외의 맥락에서 try-with-resources 블록 의 암시 적 finally블록 내에서 throw 될 때 반 무시되는 예외라고 생각합니다 .try

try-with-resources 문과 연결된 코드 블록에서 예외가 발생할 수 있습니다. writeToFileZipFileContents 예제에서 try 블록에서 예외를 throw 할 수 있으며 ZipFile 및 BufferedWriter 개체를 닫으려고 할 때 try-with-resources 문에서 최대 두 개의 예외가 throw 될 수 있습니다. try 블록에서 예외가 발생하고 try-with-resources 문에서 하나 이상의 예외가 발생하면 try-with-resources 문에서 발생하는 예외가 억제되고 블록에서 발생한 예외가 예외입니다. writeToFileZipFileContents 메소드에 의해 발생합니다. try 블록에서 throw 된 예외에서 Throwable.getSuppressed 메서드를 호출하여 이러한 억제 된 예외를 검색 할 수 있습니다.

(링크 된 페이지에서 "Suppressed Exceptions"라는 섹션을 인용 한 것입니다.)


Jon의 답변에서 인용문을 명확히하기 위해 메서드에서 (실행 당) 하나의 예외 만 throw 될 수 있지만의 경우 try-with-resources여러 예외가 throw 될 수 있습니다. 예를 들어 하나는 블록에서 던져지고 다른 하나 finallytry-with-resources.

컴파일러는 이들 중 어떤 것을 "정말"던질 지 결정해야합니다. try암시 적 코드 ( finally블록) 가 던지는 예외가 아니라 명시 적 코드 ( 블록 의 코드)에서 발생한 예외를 던지도록 선택합니다 . 따라서 암시 적 블록에서 throw 된 예외가 억제 (무시)됩니다. 이는 여러 예외의 경우에만 발생합니다.


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에서 try-with-resources; AutoCloseable :: close ()의 예외는 try 예외와 함께 기본적으로 억제 된 예외로 추가됩니다.

또한 이것은 체인 된 예외다릅니다 (JDK 1.4에서 도입되었으며 예외 간의 인과 관계를 쉽게 추적 할 수 있도록하기위한 것입니다).


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.


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

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.


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


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.

참고URL : https://stackoverflow.com/questions/7849416/what-is-a-suppressed-exception

반응형