Как я могу обнаружить, когда исключение было выбрано глобально в Java?
Как я могу обнаружить, когда исключение было выброшено где угодно в моем приложении?
Я пытаюсь автоматически настроить отправку электронной почты всякий раз, когда исключение выбрасывается в любом месте приложения Java Desktop. Я полагаю, что я могу быть более активным.
Я знаю, что могу просто явным образом регистрировать и уведомлять себя всякий раз, когда возникает исключение, но мне придется делать это повсюду, и я мог бы (скорее всего) пропустить пару.
Любые предложения?
Ответы
Ответ 1
Вероятно, вы не хотите отправлять сообщения ни о каком исключении. В JDK есть много кода, которые зависят от исключений для нормальной работы. То, что я предполагаю, что вы более заинтересованы, - это неперехваченные исключения. Если вы перехватываете исключения, вы должны обрабатывать уведомления там.
В настольном приложении есть два места, о которых можно беспокоиться, в event-dispatch-thread (EDT) и вне EDT. Globaly вы можете зарегистрировать класс, реализующий java.util.Thread.UncaughtExceptionHandler
, и зарегистрировать его через java.util.Thread.setDefaultUncaughtExceptionHandler
. Это будет вызвано, если исключение обтекает нижнюю часть стека, а поток не имеет обработчика, установленного в текущем экземпляре потока в потоке или ThreadGroup.
У EDT есть другой крючок для обработки исключений. Системное свойство 'sun.awt.exception.handler'
должно быть зарегистрировано с Полностью квалифицированным именем класса класса с конструктором нулевого аргумента. Этот класс нуждается в дескрипторе метода экземпляра (Throwable
), который выполняет вашу работу. Тип возвращаемого значения не имеет значения, и поскольку каждый экземпляр создается каждый раз, не рассчитывайте на сохранение состояния.
Итак, если вам все равно, какой поток исключение произошло в образце, может выглядеть так:
class ExceptionHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
handle(e);
}
public void handle(Throwable throwable) {
try {
// insert your e-mail code here
} catch (Throwable t) {
// don't let the exception get thrown out, will cause infinite looping!
}
}
public static void registerExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName());
}
}
Добавьте этот класс в некоторый случайный пакет, а затем вызовите метод registerExceptionHandler
, и вы должны быть готовы к работе.
Ответ 2
Новые отладочные крючки в Java 1.5 позволяют вам это делать. Он позволяет, например, "отловить любое исключение" в отладчиках.
Здесь нужен конкретный Javadoc.
Ответ 3
Проверьте Thread.UncaughtExceptionHandler. Вы можете установить его на поток или по умолчанию для всей виртуальной машины.
Это по крайней мере поможет вам поймать те, которые вы пропустите.
Ответ 4
Если вы используете java 1.3/1.4, Thread.UncaughtExceptionHandler недоступен.
В этом случае вы можете использовать решение на основе AOP для запуска некоторого кода при вызове исключения. Spring и/или aspectJ могут быть полезны.
Ответ 5
В моем текущем проекте я столкнулся с аналогичным требованием относительно обнаружения ошибок. Для этого я применил следующий подход: я использую log4j для регистрации в моем приложении, и везде, где исключение поймано, я делаю стандартную вещь: log.error("Error description goes here", e);
, где e - это Исключение, которое бросается (подробности см. В документации log4j относительно инициализации "журнала" ).
Чтобы обнаружить ошибку, я использую свой собственный Appender, который расширяет класс log4j AppenderSkeleton:
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
public class ErrorsDetectingAppender extends AppenderSkeleton {
private static boolean errorsOccured = false;
public static boolean errorsOccured() {
return errorsOccured;
}
public ErrorsDetectingAppender() {
super();
}
@Override
public void close() {
// TODO Auto-generated method stub
}
@Override
public boolean requiresLayout() {
return false;
}
@Override
protected void append(LoggingEvent event) {
if (event.getLevel().toString().toLowerCase().equals("error")) {
System.out.println("-----------------Errors detected");
this.errorsOccured = true;
}
}
}
Файл конфигурации log4j должен содержать только определение нового приложения и его прикрепление к выбранному регистратору (в моем случае это корень):
log4j.rootLogger = OTHER_APPENDERS, ED
log4j.appender.ED=com.your.package.ErrorsDetectingAppender
Вы можете вызвать метод errorsOccured() ErrorsDetectingAppender в какой-то значительной точке потока выполнения ваших программ или немедленно отреагировать, добавив функциональность в блок if в методе append(). Этот подход согласуется с семантикой: обнаруживаются вещи, которые вы считаете ошибками и регистрируете их как таковые. Если позже вы рассмотрите выбранные ошибки, которые не так важны, вы просто измените уровень ведения журнала на log.warn(), и отчет не будет отправлен.
Ответ 6
В этом случае я считаю, что лучше всего написать пользовательский загрузчик классов для обработки всей загрузки классов в вашем приложении, и всякий раз, когда запрашивается класс исключения, вы возвращаете класс, который обертывает запрашиваемый класс исключений. Эта оболочка вызывает завершенное исключение, но также регистрирует событие исключения.
Ответ 7
Если вы используете веб-фреймворк, например Spring, то вы можете делегировать в свой web.xml страницу, а затем используйте контроллер для отправки электронной почты. Например:
В web.xml:
<error-page>
<error-code>500</error-code>
<location>/error/500.htm</location>
</error-page>
Затем определите /error/ 500.htm в качестве контроллера. Вы можете получить доступ к исключению из параметра javax.servlet.error.exception:
Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
Если вы просто запускаете обычную Java-программу, тогда я бы предположил, что вы застряли в публичном статическом void main (String [] args) {try {...} catch (Exception e) {}}
Ответ 8
Я предполагаю, что вы не имеете в виду какое-либо исключение, а скорее какое-то неискушенное исключение.
Если это так, эта статья на веб-сайте Sun содержит некоторые идеи. Вам нужно обернуть свой метод верхнего уровня в блок try-catch
, а также выполнить дополнительную работу для обработки других потоков.
Ответ 9
Отправка электронной почты может быть невозможной, если вы получаете исключение во время выполнения, такое как OutOfMemoryError или StackOverflow. Скорее всего, вам придется создать другой процесс и поймать любые его исключения (с помощью различных техник, упомянутых выше).