2010-02-26 12 views
19

Aktualnie buduję aplikację przy użyciu Tomcat, Spring i JAVA. Używam Log4J jako mojej biblioteki logowania. Obecnie rejestruję wszystko w pliku tekstowym. Jednym z problemów, które mam, jest to, że RuntimeExceptions nie są rejestrowane w żadnych plikach. Zastanawiam się, czy istnieje sposób, aby zalogować wszystkie RuntimeExceptions, które mogą być wyrzucane do mojego pliku dziennika aplikacji. Jeśli nie, to czy możliwe jest zapisanie go w innym pliku dziennika? Czy istnieje standardowy sposób, aby to zrobić? Jeśli tak, czy istnieje standardowy sposób, aby to zrobić podczas uruchamiania aplikacji w Tomcat?Wyjątki w środowisku wykonawczym dziennika w języku Java przy użyciu log4j

Z góry dziękujemy za pomoc!

+2

Czy masz na myśli „przechwycone” RuntimeExceptions? –

+0

Tak Mam na myśli "nieprzechwycony" Wyjątki RuntimeEvents – DkS

Odpowiedz

21

Nie jestem pewien, czy to jest to, czego szukasz, ale istnieje procedura obsługi wyjątków, które kończą wątki. Jest to procedura obsługi dla każdego wyjątku, który nie jest przechwytywany bezpośrednio przez cel wątku.

Domyślny "brak obsługi wyjątku" po prostu wywołuje printStackTrace() na Throwable, aby wydrukować ślad stosu do System.err. Jednakże, można replace to z własnego UncaughtExceptionHandler że rejestruje wyjątek LOG4J zamiast:

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); 
    } 

} 

Jeśli używasz ramy Executora, do której przechodzą Runnable obiektu, jego wątków prawdopodobnie mają własne catch blok, który zapobiega wyjątki od osiągnięcia nieprzechwyconego modułu obsługi wyjątku. Jeśli chcesz złapać Runtime wyjątków tam, jednym ze sposobów na to jest owinąć każdego zadania w opakowaniu logowania, na przykład:

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)); 
+0

Czy to jest zwykle sposób, w jaki ten RuntimeExceptions są obsługiwane w aplikacjach? Chyba zastanawiam się, czy to jest standardowy sposób radzenia sobie z tym. – DkS

+0

Również używam ThreadPoolTaskExecutor ze Spring API, czy to nadal coś, co można zrobić za pomocą tej klasy? – DkS

+0

Działa to świetnie, jeśli istnieje RuntimeException na Runnable, ale co jeśli jest wyjątek z ThreadPoolTaskExecutor? Powiedzmy, że rzuca wyjątek RunTimeException, ponieważ puli został skonfigurowany poprawnie .... to nadal będzie drukować do konsoli i nie być zalogowany .... żadnych sugestii? – DkS

12

Jednym ze sposobów, aby zalogować niezłapane RuntimeExceptions (lub jakiekolwiek niezłapane Throwables dla tej sprawy) jest utworzenie klasy, która implementuje Thread.UncaughtExceptionHandler. Ta metoda klasy uncaughtException() po prostu zapisałaby szczegóły wyjątku w dzienniku. Można nawiązać połączenie JVM tej obsługi wyjątku ilekroć nieprzechwycony RuntimeException kończy wątek dodając linię

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler()); 

do kodu.

Powiązane problemy