2009-10-02 41 views
5

¿Cuál es, de acuerdo con usted, la forma más sencilla de interceptar todas las excepciones en una aplicación Java? ¿Se necesitaría AOP para proporcionar este tipo de funcionalidad o se puede hacer con proxies dinámicos o hay alguna otra manera? ¿La solución más simple también es una buena solución con respecto al impacto en el rendimiento de la ejecución? Me gustaría escuchar posibles soluciones de desarrolladores más experimentados, ya que estoy tratando de comprender los conocimientos técnicos sobre el tema.¿Cómo interceptarías todas las excepciones?

EDIT:

Gracias por los buenos consejos ya, pero no el consejo actual sólo se aplica a las excepciones controladas? ¿Qué sucede con las excepciones no comprobadas, como NullPointerExceptions, que no sería útil si se pudieran capturar y que la aplicación al capturarlas volcara el heap/stack para proporcionarle el contexto actual de la aplicación en el momento del bloqueo?

+0

¿qué quieres hacer con ellos? –

+3

¿Desea ver todas las excepciones * everywher *? ¿Qué bien haría eso? ¿Cómo sabrías manejar alguno de esos? –

+0

digamos que escribiría algún tipo de administrador que tome medidas específicas de acuerdo con el tipo de excepción. O algo que vuelca la pila y el montón para obtener el contexto actual de la aplicación. Francamente, no estoy planeando hacer nada con él. Estoy tratando de comprender el mejor enfoque en ese escenario. – nkr1pt

Respuesta

5

En Nate y Konamiman ... Lo que está sugiriendo que no funciona en absoluto y no responde a la pregunta de la OP.

¿Qué ocurre si el OP inicia un nuevo hilo desde el interior de su try/catch?

Por ejemplo:

public static void main(String[] args) { 
    try { 
     final Thread t = new Thread(new Runnable() { 
      public void run() { 
       System.out.println(3/Math.min(0,4)); 
      } 
     }); 
     t.start(); 
    catch(Throwable t) { 
     ... 
    } 
} 

entonces no estás agarrar la excepción.

La forma correcta de hacerlo es usar Thread.setDefaultUncaughtExceptionHandler.

+0

sí - se olvidó de eso. – Nate

+0

Como dije, no sé mucho sobre Java (entonces probablemente no debería haberlo respondido). De todos modos, es bueno aprender algo nuevo. – Konamiman

+0

(Como este no es un foro, tenga en cuenta que es posible que las respuestas no se muestren en el orden en que se publicaron). – Arjan

3
public static void main(String[] args) { 
    try { 
     ... 
    catch(Throwable t) { 
     ... 
    } 
} 
+3

La solución de Taylor L es en realidad mejor si está utilizando Java 5+: esto no puede detectar excepciones fuera del hilo principal. – Nate

+0

Estoy de acuerdo con Nate. :-) –

+0

¿Qué ocurre si se produce una excepción en un hilo diferente? –

11

¿Cuál es el propósito de usted que quiere interceptar todas las excepciones, para registrar, informar errores?

Es posible interceptar todas y cada una de las excepciones en cada línea de un programa Java, pero probablemente incurrirá en un gran golpe de rendimiento. Si es inevitable, probablemente sea mejor usar algo como AspectJ, que puede ejecutarse en tiempo de compilación (es decir, "entrelaza" en los archivos de clase) y, como tal, es mucho más rápido que los proxys dinámicos.

¡Pero es algo que trataría de evitar a toda costa! En general, diría que es mejor limitar el alcance de las excepciones que desea atrapar. También es posible que desee buscar en Thread.setDefaultUncaughtExceptionHandler, que me parece útil para mostrar cuadros de diálogo de error en aplicaciones de GUI.

0

es más importante que la simple captura de todas las excepciones es donde se captura la excepción:

  1. no coger una excepción a menos que pueda hacer algo al respecto. Si no puede hacer nada al respecto, permita que suba al siguiente nivel o tóquelo, vuelva a envolverlo como una excepción más específica y vuelva a lanzarlo.

  2. Siempre tenga un bloque de manejo de excepciones global (como en la respuesta de Nate) para detectar cualquier error que no pueda manejar en cualquier lugar para que pueda fallar un poco con gracia.

0

Si simplemente desea capturar una excepción, un bloque de prueba/captura será suficiente. Si desea evitar que sean lanzados o hacer algún registro o envoltura de la Excepción, es probable que necesite algún AOP para hacer esto. AspectJ lo manejará bastante bien, pero ten cuidado con los posibles cuellos de botella en el rendimiento.

Los proxies dinámicos solo funcionarán cuando el método esté procesado, de modo que si se lanza y se captura alguna Excepción dentro de la ejecución del objeto proxy, no hay medios para que los proxies intercepten la Excepción.

Una cosa a considerar es si está atrapando todas las excepciones, o solo las excepciones marcadas. Para captar todas las excepciones, las recomendaciones de AspectJ around throwing o after throwing tejen algunos procesos alrededor de cada método, esto implica la creación de objetos JoinPoint y métodos sintéticos en cada invocación de método. Esto no suele ser un problema a menos que el proceso esté en un círculo cerrado, donde la recolección de basura puede irse por las nubes.

9

Similar a la respuesta de Phil, aquí hay un código de muestra que muestra cómo usar el controlador de excepciones no detectadas. Esto funciona para las excepciones marcadas y sin marcar.

Editar: Se actualizó para imprimir el seguimiento de la pila en función de los comentarios actualizados en la pregunta.

import java.lang.Thread.UncaughtExceptionHandler; 

public class Test { 

    public static void main(String[] args) throws Exception { 
     Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { 

      @Override 
      public void uncaughtException(Thread t, Throwable e) { 
       e.printStackTrace(); 
      }} 

     ); 

     // throw new RuntimeException(); /* this works too */ 
     throw new Exception(); 
    } 

} 
0

Para todos aquellos questionning la necesidad de capturar todas las excepciones ...

Hay un montón de razones válidas para capturar todas las excepciones:

  • alguien mencionado que muestra un cuadro de diálogo en una aplicación GUI hablando sobre el problema
  • trabajando alrededor de errores en una API de terceros que realmente necesita
  • solucionando errores en alguna implementación de JVM
  • software de autocuración.
  • informe automático de excepción en línea.

Nota que Java hace interceptar todas las excepciones en el (hilo de eventos de Despacho) EDT y genera un nuevo EDT cuando la EDT muere. Puede considerar que es una forma de software de "autocuración". La muerte por EDT no es algo inaudito y no impide que las aplicaciones se ejecuten correctamente (por el contrario). (y, sí, Swing y AWT tienen algunos errores, solo eche un vistazo al desfile de errores de Sun;)

Se podría argumentar que cualquier software que se precie realmente debería tener en cuenta el caso de una excepción imprevista (¿todo el software que envías está libre de fallos al 100% y nunca recibe nuevos lanzamientos, lanzamientos de corrección de errores?) y haz algo inteligente cuando ocurre una excepción imprevista.

El 'algo inteligente' puede prevenir que el software se estrelle (como en el caso EDT), avisando al usuario, el envío de un informe, etc.

Respuestas questionning la necesidad de hacer tal cosa o lo que sugiere que hacerlo es una mala práctica si en mi humilde opinión se modificara.

Cuestiones relacionadas