Когда ловить java.lang.Error? - PullRequest
       48

Когда ловить java.lang.Error?

108 голосов
/ 09 декабря 2008

В каких ситуациях нужно поймать java.lang.Error в приложении?

Ответы [ 16 ]

96 голосов
/ 09 декабря 2008

Как правило, никогда. Однако иногда вам нужно отлавливать определенные ошибки.

Если вы пишете код инфраструктуры (загрузка сторонних классов), может быть целесообразно перехватить LinkageErrors (определение класса не найдено, неудовлетворительная ссылка, несовместимое изменение класса). Я также видел несколько глупых сторонних кодов, выдающих подкадры ошибок, так что вам придется справиться и с ними.

Кстати, я не уверен, что невозможно восстановить из OutOfMemory.

50 голосов
/ 09 декабря 2008

Никогда. Вы никогда не можете быть уверены, что приложение сможет выполнить следующую строку кода. Если вы получаете OutOfMemoryError, у вас нет гарантии того, что вы сможете что-либо сделать надежно Поймать RuntimeException и проверить исключения, но не ошибки.

http://pmd.sourceforge.net/rules/strictexception.html

15 голосов
/ 05 марта 2009

Как правило, вы всегда должны ловить java.lang.Error и записывать его в журнал или отображать его пользователю. Я работаю в поддержке и ежедневно вижу, что программисты не могут сказать, что произошло в программе.

Если у вас есть поток демона, вы должны предотвратить его прерывание. В других случаях ваше приложение будет работать правильно.

Вы должны ловить java.lang.Error только на самом высоком уровне.

Если вы посмотрите на список ошибок, вы увидите, что большинство из них могут быть обработаны. Например, ZipError возникает при чтении поврежденных zip-файлов.

Наиболее распространенными ошибками являются OutOfMemoryError и NoClassDefFoundError, которые в большинстве случаев являются проблемами во время выполнения.

Например:

int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];

может выдать OutOfMemoryError, но это проблема времени выполнения и нет причин для завершения вашей программы.

NoClassDefFoundError в основном, если библиотека отсутствует или вы работаете с другой версией Java. Если это необязательная часть вашей программы, вам не следует прерывать ее.

Я могу привести еще много примеров того, почему стоит поймать Throwable на верхнем уровне и выдать полезное сообщение об ошибке.

14 голосов
/ 07 марта 2009

В многопоточной среде вы чаще всего захотите его поймать! Когда вы поймаете это, войдите в систему и закройте все приложение! Если вы этого не сделаете, какой-то поток, который может выполнять какую-то важную часть, будет мертв, а остальная часть приложения будет думать, что все нормально. Из-за этого может случиться много нежелательных ситуаций. Одной из самых маленьких проблем является то, что вы не сможете легко найти корень проблемы, если другие потоки начнут выдавать некоторые исключения из-за того, что один поток не работает.

Например, обычно цикл должен быть:

try {
   while (shouldRun()) {
       doSomething();
   }
}
catch (Throwable t) {
   log(t);
   stop();
   System.exit(1);
}

Даже в некоторых случаях вы захотите по-разному обрабатывать разные ошибки, например, в OutOfMemoryError вы сможете регулярно закрывать приложение (даже, может быть, освободить часть памяти и продолжить), в некоторых других вас не так много. можно сделать.

8 голосов
/ 09 декабря 2008

Очень редко.

Я бы сказал, только на верхнем уровне потока, чтобы попытаться выдать сообщение с причиной смерти потока.

Если вы в платформе, которая делает такие вещи для вас, оставьте это для каркаса.

6 голосов
/ 10 декабря 2008

Если вы достаточно сумасшедшие, чтобы создавать новую платформу для модульных тестов, вашему тестирующему организатору, вероятно, потребуется отлавливать java.lang.AssertionError, выдаваемый любыми тестовыми примерами.

В противном случае см. Другие ответы.

6 голосов
/ 09 декабря 2008

Error обычно не следует ловить , поскольку указывает на ненормальное состояние, которое никогда не должно возникать .

Из спецификации API Java для Error класса:

Error является подклассом Throwable что указывает на серьезные проблемы, которые разумное приложение не должно пытаться ловить. Большинство таких ошибок ненормальные условия. [...]

Метод не требуется объявлять в его броски оговорка любые подклассы Ошибка, которая может быть выдана во время выполнение метода, но не поймал, так как эти ошибки ненормальные условия, которые никогда не должны происходят.

Как упоминается в спецификации, Error выбрасывается только при обстоятельствах, которые Скорее всего, когда происходит Error, приложение может сделать очень мало, и в некоторых случаях сама виртуальная машина Java может находиться в нестабильном состоянии (например, VirtualMachineError)

Хотя Error является подклассом Throwable, что означает, что он может быть перехвачен предложением try-catch, но, вероятно, в этом нет особой необходимости, поскольку приложение будет в ненормальном состоянии, когда Error выбрасывается JVM.

Существует также короткий раздел на эту тему в разделе 11.5 Иерархия исключений спецификации языка Java, 2-е издание .

6 голосов
/ 09 декабря 2008

Почти никогда. Ошибки предназначены для проблем, с которыми приложения обычно ничего не могут поделать. Единственное исключение может заключаться в обработке сообщения об ошибке, но даже оно может не соответствовать запланированному в зависимости от ошибки.

5 голосов
/ 09 декабря 2008

И в нескольких других случаях, когда вы поймаете ошибку, вам придется сбросить ее . Например, ThreadDeath никогда не следует перехватывать, это может вызвать большие проблемы, если вы перехватываете его в изолированной среде (например, на сервере приложений):

Приложение должно ловить экземпляры этого класса, только если оно должно очистить после завершения асинхронно. Если ThreadDeath перехватывается методом, важно, чтобы он был переброшен, чтобы нить действительно умерла.

4 голосов
/ 09 декабря 2008

Очень, очень редко.

Я сделал это только для одного очень специфического известного случая. Например, java.lang.UnsatisfiedLinkError может быть сброшен, если два независимости ClassLoader загружают одну и ту же DLL. (Я согласен, что я должен переместить JAR в общий загрузчик классов)

Но наиболее распространенным случаем является необходимость входа в систему, чтобы узнать, что произошло, когда пользователь пришел, чтобы пожаловаться. Вы хотите сообщение или всплывающее окно для пользователя, а не молча.

Даже программист на C / C ++ выдает ошибку и сообщает что-то, чего люди не понимают, до его выхода (например, сбой памяти).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...