Записывать исключения во время выполнения в Java, используя log4j - PullRequest
20 голосов
/ 26 февраля 2010

В настоящее время я создаю приложение с использованием Tomcat, Spring и JAVA. Я использую Log4J в качестве библиотеки логов. В настоящее время я записываю все в текстовый файл. Одна из проблем, с которыми я сталкиваюсь, заключается в том, что RuntimeExceptions не регистрируется ни в каких файлах. Мне было интересно, есть ли способ записать все RuntimeExceptions, которые могут быть выброшены в файл журнала моего приложения. Если нет, то возможно ли сделать так, чтобы он регистрировался в другом файле журнала? Есть ли стандартный способ сделать это? Если да, есть ли стандартный способ сделать это при запуске приложения в Tomcat?

Заранее благодарю за помощь!

Ответы [ 3 ]

22 голосов
/ 27 февраля 2010

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

По умолчанию «обработчик необработанных исключений» просто вызывает printStackTrace() на Throwable, чтобы напечатать трассировку стека до System.err. Однако вы можете заменить на свой UncaughtExceptionHandler, который вместо этого регистрирует исключение в log4j:

class Log4jBackstop implements Thread.UncaughtExceptionHandler {

  private static Logger log = Logger.getLogger(Log4jBackstop.class);

  public void uncaughtException(Thread t, Throwable ex) {
    log.error("Uncaught exception in thread: " + t.getName(), ex);
  }

}

Если вы используете платформу executor, в которую передаете объект Runnable, его потоки, вероятно, имеют свой собственный блок catch, который предотвращает попадание исключений в обработчик необработанных исключений. Если вы хотите перехватить Runtime исключений, один из способов сделать это - обернуть каждую задачу в оболочку регистрации, например:

class Log4jWrapper {

  private final Logger log;

  private final Runnable target;

  Log4jWrapper(Logger log, Runnable target) { 
    this.log = Objects.requireNonNull(log);
    this.target = Objects.requireNonNull(target); 
  }

  public void run() {
    try {
      target.run();
    } catch(RuntimeException ex) {
      log.error("Uncaught exception.", ex);
      throw ex;
    }
  }

}

...

Runnable realTask = ...;
executor.submit(new Log4jWrapper(Logger.getLogger(Whatever.class), realTask));
13 голосов
/ 26 февраля 2010

Один из способов регистрации необработанных исключений RuntimeException (или любых неперехваченных Throwables по этому вопросу) состоит в создании класса, реализующего Thread.UncaughtExceptionHandler . Метод uncaughtException() этого класса просто записывает подробности исключения в журнал. Вы можете заставить JVM вызывать этот обработчик исключений всякий раз, когда необработанное исключение RuntimeException завершает поток, добавляя строку

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());

к вашему коду.

2 голосов
/ 26 февраля 2010

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

Этот пост в блоге дает краткое изложение того, как выполнить перенаправление в FileHandler, который находится отдельно от вашего регистратора.

https://blogs.oracle.com/nickstephen/entry/java_redirecting_system_out_and

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