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

Захват ошибок Java

Я слышал, что ловить java.lang.Error считается плохой практикой. Я в настоящее время загружаю .dll, который не гарантируется в PATH, и хотел бы переключиться на настроенное пользователем местоположение в случае, если это не так.

try {
    System.loadLibrary("HelloWorld");
} catch(UnsatisfiedLinkError ule){
    System.load("C:/libraries/HelloWorld.dll");
}

Есть ли лучший способ сделать это? Или ловить UnsatisfiedLinkError здесь приемлемо?

4b9b3361

Ответ 1

Помимо предоставления рекомендаций о том, как технически преодолеть эту проблему, я хотел бы остановиться и объяснить, почему в первую очередь это считается "плохой практикой".

Пусть начнется, уточнив класс Error.


В java генерируются ошибки и исключения (которые являются основными типами). Выбрасывание одного из указанных выше выполняется с помощью ключевого слова throw. Каждый класс, который расширяет базовый java.lang.Throwable, может быть брошен.

Существует два класса, которые наследуют базовый класс Throwable: Exception и Error. Разница между этими двумя объясняется в их документах:

Ошибка - это подкласс Throwable, который указывает на серьезный проблемы, которые разумное приложение не должно пытаться поймать. Наиболее такие ошибки являются ненормальными условиями. [...]

Источник

Класс Exception и его подклассы являются формой Throwable что указывает условия, которые может потребовать разумное приложение ловить.

Источник


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

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


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

Да, вполне разумно поймать UnsatisfiedLinkError, потому что ваше приложение может восстановить его.


Я рассмотрел выше (более подробно и с примерами) и некоторую расширенную информацию в статье в моем блоге.

Ответ 2

loadLibrary вызывает findLibrary(), который был бы полезен, но он был защищен, лучше всего написать собственный класс, расширяющий ClassLoader. У загрузчика классов есть защищенный метод, называемый findLibrary(), который вернет путь к библиотеке или null, если он не существует. Таким образом, вы можете просто проверить нуль, а не ловить ошибки. Я не уверен, что это на самом деле "лучше", но это избавит вас от необходимости попробовать catch;

Ответ 3

Если вы защищаете код и можете восстановить его из проблемы, то это не Java Error. Если такая проблема не очень вероятна, создайте подкласс Exception и бросьте и поймите. Если такая проблема вероятна, то она не должна даже бросать Exception; но должен быть частью обычного потока кода.

try {
  if (config.hasCustomDLL()) {
    System.load(config.getCustomDLL());
  } else {
    System.loadLibrary(Config.DEFAULT_DLL);
  }
} catch (UnstatisfiedLinkError e) {
  System.out.println("Error loading DLL: " + e);
}

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

Ответ 4

Вы должны улавливать ошибки только в особых случаях. Только улов и ошибка, если вы изучили все другие возможности. Я полностью согласен со всем, что сказал Лукас Кнут. Но у меня есть одно небольшое дополнение. Если вы поймаете какую-либо ошибку, убедитесь, что вы улавливаете ошибки как можно более узкие. Кроме того, если это возможно, убедитесь, что методы, по которым вы обнаруживаете ошибки, объявляются окончательными. Причина в том, что улавливающие ошибки обычно приводят к некоторым очень шатким программам. Подумайте, что вы поймаете ошибку в методе, который позже расширен для вызова других методов, все эти базовые методы теперь также будут иметь ошибки, которые были бы уловлены (непреднамеренно) с помощью вышележащего улова.

Если вам нужно поймать ошибку, сделайте это в узком, контролируемом fasion.