2012-06-13 14 views
17

He oído que la captura de java.lang.Error se considera una mala práctica. Actualmente estoy cargando un archivo .dll que no se garantiza que esté en la RUTA, y me gustaría cambiar a una ubicación configurada por el usuario en el caso de que no lo esté.Captura de errores de Java

try { 
    System.loadLibrary("HelloWorld"); 
} catch(UnsatisfiedLinkError ule){ 
    System.load("C:/libraries/HelloWorld.dll"); 
} 

¿Hay una manera mejor de hacer esto? ¿O está aceptando el UnsatisfiedLinkError aquí como aceptable?

+5

No hay idea sobre la conveniencia correcta aquí, pero podría probar si el archivo existe antes de intentar ... ['new File (" ruta/helloworld.dll ") .exists()'] (http: // docs. oracle.com/javase/7/docs/api/java/io/File.html#exists%28%29) .... (corregir: sugerencia incorrecta, leí mal el código) –

+5

Lo consideraría una solución aceptable. –

+0

@Slanec Tendría que buscar todos los directorios en 'java.library.path' –

Respuesta

16

Además de dar consejos sobre cómo superar técnicamente el problema, me gustaría tomar un momento y explicar por qué se considera una "mala práctica" en primer lugar.

Comencemos por aclarar qué es la clase Error.


en Java, errores y excepciones (que son los principales tipos) se tiran. Lanzar uno de los anteriores se realiza utilizando la palabra clave throw. Se puede lanzar cualquier clase que extienda el java.lang.Throwable básico.

Hay dos clases que heredan de la clase básica Throwable: Exception y Error. La diferencia entre los dos es explicado en sus documentaciones:

Un error es una subclase de Throwable que indica graves problemas que una aplicación razonable no debe tratar de atrapar. La mayoría de los tales errores son condiciones anormales. [...]

Source

La clase Excepción y sus subclases son una forma de Throwable que indica que las condiciones de una aplicación razonable podría querer para coger .

Source


Como se explicó anteriormente, los errores y excepciones se separan debido a sus diferentes orígenes. Un Error normalmente indica un problema, que la aplicación no puede recuperar desde. Por lo tanto, no deberían ser atrapados.

Lo mismo ocurre con un RuntimeException, pero se utiliza para indicar un problema con una capa de alto nivel (por ejemplo, métodos). Mientras que el Error indica un problema de bajo nivel (por ejemplo, el tiempo de ejecución).


Así que, ahora que entiende que solo podrán capturar las excepciones y errores que son capaces de recuperarse de, la respuesta a su pregunta debe ser clara.

Sí, es perfectamente razonable detectar UnsatisfiedLinkError, porque su aplicación puede recuperarse de ella.


I cubrió el anterior (con más detalle y con ejemplos) y algunos datos extendidos en una article on my Blog.

+0

Una vez tuve que violar este paradigma cuando tuve que arrojar un error normal a través de una clase de la que provenía que no especificaba ninguna excepción. Así que obtuve de 'RuntimeException' para evaluar los requisitos de idioma. Todavía desearía que hubiera una mejor manera de hacer esto. – djechlin

+0

Si la aplicación no puede recuperarse de un error, no está peor si la detecta, ¿verdad? – simon

+0

@simon si realmente no puede recuperarse del error, ¿qué va a hacer cuando lo atrape? Si la aplicación ya no funciona, ¿por qué seguir funcionando? –

0

loadLibrary llama a findLibrary() que sería útil pero está protegido, su mejor opción es escribir su propia clase extendiendo ClassLoader. El cargador de clases tiene un método protegido llamado findLibrary() que devolverá la ruta a una biblioteca o null si no existe. De esta forma, puede verificar nulo en lugar de detectar errores. No estoy seguro de si esto es realmente "mejor", pero eliminará su necesidad de intentar capturar;

+0

La biblioteca podría eliminarse después de la verificación y antes de la carga, por lo que la captura de prueba aún es probablemente necesaria. –

0

Si está codificando a la defensiva y puede recuperarse de un problema, entonces no es un Java Error. Si tal problema no es muy probable, entonces crea una subclase de Exception y tira y atrapa eso. Si tal problema es probable, entonces ni siquiera debería arrojar un Exception; pero, debe ser parte del flujo de código regular.

try { 
    if (config.hasCustomDLL()) { 
    System.load(config.getCustomDLL()); 
    } else { 
    System.loadLibrary(Config.DEFAULT_DLL); 
    } 
} catch (UnstatisfiedLinkError e) { 
    System.out.println("Error loading DLL: " + e); 
} 

Errors están diseñados para muy malas fracasos, "fallos" no recuperables que en realidad no son ni siquiera los fallos si hay una solución adecuada. No sobrecargue el sistema diseñado para manejar fallas con lo que equivale a la capacidad de configurar el sistema de múltiples maneras.

0

Solo debe detectar errores en casos muy específicos. Solo capturas y errores si ha explorado todas las demás posibilidades. Estoy completamente de acuerdo con todo lo que dijo Lukas Knuth. Pero tengo una pequeña adición. En caso de que detecte cualquier tipo de error, asegúrese de detectar los errores desde un alcance tan limitado como sea posible. Además, si es posible, asegúrese de que los métodos en los que detecta errores estén declarados como definitivos. La razón es que la captura de errores generalmente puede llevar a algunos programas muy inestables. Considere que detecta un error en un método que luego se amplía para llamar a otros métodos, todos estos métodos subyacentes ahora también tendrán errores capturados (involuntariamente) por la captura suprayacente.

Si necesita detectar un error, hágalo en un fasion estrecho y controlado.

Cuestiones relacionadas