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

Как я могу обнаружить, когда исключение было выбрано глобально в Java?

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

Я пытаюсь автоматически настроить отправку электронной почты всякий раз, когда исключение выбрасывается в любом месте приложения Java Desktop. Я полагаю, что я могу быть более активным.

Я знаю, что могу просто явным образом регистрировать и уведомлять себя всякий раз, когда возникает исключение, но мне придется делать это повсюду, и я мог бы (скорее всего) пропустить пару.

Любые предложения?

4b9b3361

Ответ 1

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

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