Подтвердить что ты не робот

Что такое подавленное исключение?

Комментарий (пользователь soc) в ответ на вопрос об оптимизации хвостовых опций упоминал, что Java 7 имеет новую функцию, называемую "подавленные исключения", из-за "добавления ARM" (поддержка процессоров ARM?).

Что такое "исключенное исключение" в этом контексте? В других контекстах "исключенное исключение" было бы исключением, которое было поймано, а затем проигнорировано (редко хорошая идея); это явно что-то другое.

4b9b3361

Ответ 1

Я полагаю, что комментатор ссылается на это исключение, которое игнорируется, когда оно выбрано внутри неявного блока finally try-with-resources, в контексте того, что существующее исключение выбрано из блока try:

Исключение может быть выбрано из блока кода, связанного с оператором try-with-resources. В примере writeToFileZipFileContents исключение может быть выбрано из блока try, и до двух исключений может быть выбрано из инструкции try-with-resources при попытке закрыть объекты ZipFile и BufferedWriter. Если исключение выбрано из блока try, и одно или несколько исключений выбрасываются из оператора try-with-resources, то те исключения, которые выбраны из инструкции try-with-resources, подавляются, а исключение, созданное блоком, является тем, который вызывается методом writeToFileZipFileContents. Вы можете получить эти подавленные исключения, вызвав метод Throwable.getSuppressed из исключения, созданного блоком try.

(Это цитирует раздел "Подавленные исключения" на связанной странице.)

Ответ 2

Чтобы прояснить цитату в ответе Джона, только одно исключение может быть выбрано методом (за выполнение), но в случае try-with-resources возможно забросить несколько исключений. Например, можно было бы бросить в блок, а другой можно было бы выбросить из неявного finally, предоставленного try-with-resources.

Компилятор должен определить, какой из них "действительно" бросить. Он выбирает исключение, выраженное в явном коде (код в блоке try), а не в том, что выбрано неявным кодом (блок finally). Поэтому исключение (исключения), которое бросается в неявный блок, подавляется (игнорируется). Это происходит только в случае нескольких исключений.

Ответ 3

До 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 {
}

В класс Throwable в JDK 7 был добавлен новый конструктор и два новых метода. Они приведены ниже:

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 и были предназначены для того, чтобы можно было легко отслеживать причинно-следственные связи между исключениями.)

Ответ 4

Подавленные исключения являются дополнительными исключениями, которые происходят в инструкции try-with-resources (представленный в Java 7), когда AutoCloseable ресурсы закрыты. Поскольку при закрытии ресурсов AutoCloseable могут возникать множественные исключения, дополнительные исключения исключаются из в качестве исключенных исключений.

Глядя на байт-код фрагмента кода примера try-with-resources, стандартные обработчики исключений JVM используются для -ресурсы семантики.

Ответ 5

Выполнение кода ниже:

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

Ответ 6

Я думаю, что это связано с "цепным средством исключения". Это повлияет на то, каким образом исключение обрабатывается этим средством по мере развития трассировки стека. Со временем исключения, которые являются частью группы связанных исключений, могут быть подавлены. Подробнее см. Throwable documentation.

Ответ 7

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() функция выбрасывает Exception, а затем даже close() функция [в finally block] выдает исключение, то более поздняя версия получает больше приоритета и возвращается к вызывающей функции. В этом случае Exception thrown by the readLine() method is ignored/suppressed. Вы можете связать вызывающее исключение в своем исключении и сбросить свое исключение из блока finally.

Так как для извлечения исключенных исключений предусмотрена функция java 7. Вы можете вызвать функцию 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(); line throws Exception1, а затем позволяет сказать, что Exception2 вызывается при закрытии ресурса [Представьте, что это происходит в неявном блоке finally, который создается с помощью команды try-with-resource], тогда Exception1 подавляет Exception2.

Несколько пунктов, чтобы отметить здесь -

  • Если try-with-resource блокирует исключение, то при создании экземпляра ресурса, тогда попытка блокировки не будет выполняться, и будет отправлено одно и то же исключение.
  • Если экземпляр ресурса успешный, попробуйте блокировать исключение и исключение генерируется при закрытии ресурса, тогда исключение, созданное при закрытии ресурса, подавляется исключением, выведенным из блока try.
  • Если вы предоставите явный окончательный блок, и исключение будет выбрано из этого блока, оно будет подавлять все остальные исключения. (Этот явный блок finally выполняется после закрытия ресурсов)

Я собрал большинство возможных сценариев с фрагментами кода и выводами в следующем сообщении.

Подавленные исключения в java 7

Надеюсь, что это поможет.

Ответ 8

Вы также можете подавлять исключения на 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) {

чтобы получить исключенные исключения из Exception, если кто-либо еще использует Java 1.6