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

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

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

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

Какие-либо предложения?

При работе с Java 7 или новее вы можете проверить ответы на stackoverflow.com/questions/95767/…

Suma 09.01.2015 13:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
27
1
10 948
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

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

Новые хуки отладки в Java 1.5 позволяют вам это делать. Это позволяет, например, "прерывание по любому исключению" в отладчиках.

Вот конкретный Javadoc тебе нужно.

Проверьте Thread.UncaughtExceptionHandler. Вы можете установить его для каждого потока или по умолчанию для всей виртуальной машины.

Это, по крайней мере, поможет вам поймать тех, кого вы пропустили.

Если вы используете веб-фреймворк, такой как 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, то я могу представить, что вы застряли с public static void main (String [] args) {try {...} catch (Exception e) {}}

Этот пример применим к любому «веб-приложению» и не имеет ничего общего с Spring или веб-фреймворками. Это также относится только к неперехваченным исключениям, которые всплывают в базовый класс сервлета, вызывая, таким образом, статус HTTP 500 - который может (или не может) быть тем, что требуется.

Cheekysoft 16.09.2008 22:51

Ах, спасибо - у меня только опыт работы со Spring, поэтому не хотелось говорить вне очереди :)

Mat Mannion 17.09.2008 21:56

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

Если это так, у эта статья на веб-сайте Sun есть несколько идей. Вам нужно обернуть свой метод верхнего уровня в блок try-catch, а также выполнить некоторую дополнительную работу для обработки других потоков.

Ответ принят как подходящий

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

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

Зачем вам последняя строчка System.setProperty ("sun.awt.exception.handler", ExceptionHandler.class.getName ()); Он работает без этой строки. Я полагаю, что sun.awt может быть специфическим для реализации sun.

feiroox 14.12.2009 09:07

В случае, если исключение выброшено в сторону потока отправки событий. Swing / AWT EDT имеет собственный ловитель исключений в корне своего потока, и это его зацеп.

shemnon 15.12.2009 20:59

Вы уверены, что насчет бесконечного цикла? В документации UncaughtExceptionHandler.uncaughtException (...) указано: Любое исключение, созданное этим методом, будет игнорироваться виртуальной машиной Java. (см .: file: ///usr/lib/jvm/java-6-sun/docs/api/java/lang/Thread.Unc‌ aughtExceptionHandle‌ r.html)

jilles de wit 15.10.2010 18:48

Кто читает javadocs? Таким образом, это не вызовет бесконечного цикла, но это делает его полностью выразительным в коде. А до версии 1.5 это нужно было делать в ThreadGroup, которая не давала таких обещаний. Так что код и мышление унаследованы.

shemnon 19.10.2010 19:25

Я не мог заставить работать предложенный здесь метод EDT, используя 1.6 JVM. Вместо этого я последовал совету этот сайт, который отлично работает для перехвата исключений EDT. В сочетании с подходом registerExceptionHandler это улавливает все исключения времени выполнения в моем приложении Swing.

Duncan Jones 28.03.2012 12:47

Отправка электронного письма может оказаться невозможной, если вы получаете исключение времени выполнения, такое как OutOfMemoryError или StackOverflow. Скорее всего, вам придется запускать другой процесс и перехватывать любые вызванные им исключения (с помощью различных методов, упомянутых выше).

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

Cheekysoft 16.09.2008 22:54

Если вы используете java 1.3 / 1.4, Thread.UncaughtExceptionHandler недоступен. В этом случае вы можете использовать решение, основанное на АОП, для запуска некоторого кода при возникновении исключения. Spring и / или aspectJ могут быть полезны.

В моем текущем проекте я столкнулся с аналогичным требованием относительно обнаружения ошибок. Для этой цели я применил следующий подход: я использую log4j для ведения журнала в моем приложении, и везде, где обнаружено исключение, я делаю стандартную вещь: log.error("Error's 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 должен просто содержать определение нового приложения и его привязку к выбранному регистратору (в моем случае root):

log4j.rootLogger = OTHER_APPENDERS, ED
log4j.appender.ED=com.your.package.ErrorsDetectingAppender

Вы можете вызвать метод errorsOccured () объекта ErrorsDetectingAppender в какой-то важный момент в потоке выполнения ваших программ или немедленно отреагировать, добавив функциональные возможности в блок if в методе append (). Этот подход согласуется с семантикой: обнаруживаются вещи, которые вы считаете ошибками и регистрируете их как таковые. Если вы позже сочтете выбранные ошибки не столь важными, вы просто измените уровень ведения журнала на log.warn (), и отчет не будет отправлен.

Просто нет веской причины получать информацию о каждом сгенерированном исключении. Я предполагаю, что вы предполагаете, что выброшенное исключение указывает на «проблему», о которой вам «нужно» знать. Но это неправильно. Если исключение выброшено, перехвачено и обработано, все в порядке. Единственное, о чем вы должны беспокоиться, необходимость - это исключение, которое генерируется, но не обрабатывается (не обнаруживается). Но вы можете сделать это самостоятельно в предложении try ... catch.

Другие вопросы по теме