2010-02-26 6 views
19

Actualmente estoy compilando una aplicación usando Tomcat, Spring y JAVA. Estoy usando Log4J como mi biblioteca de registro. Actualmente estoy registrando todo en un archivo de texto. Uno de los problemas que tengo es que RuntimeExceptions no se registran en ningún archivo. Me preguntaba si hay una forma de registrar todos los RuntimeExceptions que tal vez arrojaron a mi archivo de registro de la aplicación. Si no, ¿es posible hacer que se registre en otro archivo de registro? ¿Hay una manera estándar de hacer esto? Si es así, ¿existe una forma estándar de hacerlo cuando ejecuta su aplicación dentro de Tomcat?Excepciones de tiempo de ejecución de registro en Java usando log4j

Gracias de antemano por su ayuda!

+2

¿Quieres decir RuntimeExceptions "sin capturar"? –

+0

Sí, quiero decir "no capturado" RuntimeExceptions – DkS

Respuesta

21

No estoy seguro de si esto es lo que está buscando, pero hay un controlador para las excepciones que terminan los hilos. Es un controlador para cualquier excepción que no sea capturada explícitamente por el destino del hilo.

El controlador de excepción no capturado predeterminado simplemente llama al printStackTrace() en el Throwable para imprimir el seguimiento de la pila al System.err. Sin embargo, usted podría replace esto con su propio UncaughtExceptionHandler que registra la excepción a LOG4J lugar:

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

} 

Si está utilizando un marco ejecutor a la que se pasa un objeto Runnable, sus hilos probablemente tendrá su propio catch bloque que impiden excepciones de llegar al controlador de excepciones no detectadas. Si se desea capturar Runtime excepciones allí, una forma de hacerlo es envolver cada tarea en un envoltorio de registro, así:

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

¿Es así normalmente cómo se manejan estas RuntimeExceptions en las aplicaciones? Supongo que me pregunto si esta es una forma estándar de lidiar con esto. – DkS

+0

También estoy usando ThreadPoolTaskExecutor de Spring API, ¿esto todavía se puede hacer usando esta clase? – DkS

+0

Esto funciona muy bien si hay una RuntimeException en Runnable, pero ¿qué pasa si hay una excepción con ThreadPoolTaskExecutor? Digamos que arroja una RunTimeException porque el Pool se configuró correctamente ... esto aún se imprimirá en la consola y no se registrará ... ¿Alguna sugerencia? – DkS

1

Puede intentar redireccionar el StdErr para usar su registrador. Esto debería generar el resultado de cualquier cosa que se escriba en su std err (que debería incluir excepciones no controladas)

Esta publicación de blog brinda un buen resumen de cómo hacer la redirección a un FileHandler que está separado de su registrador.

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

12

Una forma de conectarse RuntimeExceptions sin capturar (o cualquier Throwables no capturadas para el caso) es crear una clase que implementa Thread.UncaughtExceptionHandler. El método uncaughtException() de esta clase simplemente escribiría los detalles de la excepción en el registro. Puede realizar la llamada JVM este gestor de excepciones siempre que un RuntimeException no detectada termina un hilo mediante la adición de la línea

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler()); 

a su código.

Cuestiones relacionadas