Что такое подавленное исключение?
комментарий (от пользователя soc) на ответ вопрос об оптимизации хвостового вызова упоминалось, что Java 7 имеет новую функцию под названием "подавленные исключения", из-за" добавления ARM " (поддержка процессоров ARM?).
Что такое "подавленное исключение" в этом контексте? В других контекстах "подавленное исключение" было бы исключением, которое было поймано, а затем проигнорировано (редко хорошая идея); это явно что-то другое.
8 ответов:
Я считаю, что комментатор ссылается на исключение, которое наполовину игнорируется, когда оно выбрасывается в неявном
finallyблок a try-with-resources блок, в контексте существующего исключения изtryблок:исключение может быть выдано из блока кода, связанного с инструкцией try-with-resources. В Примере writeToFileZipFileContents исключение может быть вызвано из блока try и до двух исключения могут быть вызваны из инструкции try-with-resources при попытке закрыть объекты ZipFile и BufferedWriter. Если исключение создается из блока try и одно или несколько исключений создаются из оператора try-with-resources, то эти исключения, создаваемые из оператора try-with-resources, подавляются, а исключение, создаваемое блоком, является исключением, создаваемым методом writeToFileZipFileContents. Вы можете получить эти подавленные исключения, вызвав Метательный.метод getSuppressed из исключения, вызванного блоком try.
(это цитирует раздел под названием "подавленные исключения" из связанной страницы.)
чтобы уточнить цитату в ответе Джона, только одно исключение может быть брошено методом (за выполнение), но это возможно, в случае
try-with-resources, для нескольких исключений, которые будут брошены. Например, один может быть брошен в блок, а другой может быть брошен из неявногоfinallyпредставленнойtry-with-resources.компилятор должен определить, какой из них "действительно" бросить. Он выбирает, чтобы бросить исключение, вызванное в явном коде (код в
tryзаблокировать) вместо того, чтобы тот, брошенный неявным кодом (finallyблок). Поэтому исключения, брошенные в неявном блоке, подавляются (игнорируются). Это происходит только в случае нескольких исключений.
перед 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() добавляется как подавленное исключение по умолчанию вместе с исключением попытки.
также известно, что это отличается от цепи исключений (были введены с JDK 1.4 и были предназначены, чтобы сделать возможным легко отслеживать причинно-следственные связи между исключениями.)
подавленных исключений являются дополнительными исключениями, которые происходят в инструкции try-with-resources (введено в Java 7) при
AutoCloseableресурсы закрыты. Потому что несколько исключений могут возникнуть при закрытииAutoCloseableресурсы, дополнительные исключения прилагаются к первичное исключение как подавленные исключения.глядя на байт-код фрагмента примера кода try-with-resources, standard JVM обработчики исключений используются для размещения семантики try-with-resources.
уступая код ниже:
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
Я думаю, что это связано с "chained exception facility". Это повлияет на то, как исключение обрабатывается этим средством по мере развития трассировки стека. Со временем исключения, которые являются частью группы цепных исключений, могут быть подавлены. Посмотри на Throwable documentation для более подробной информации.
вы также можете подавлять исключения в 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
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(); } }
Comments