2009-04-17 15 views
6

Un colega mío en el trabajo hizo una presentación sobre los métodos estáticos de fábrica (directamente de Effective Java), y luego dio un ejemplo de su uso para obtener excepciones estáticas/singleton.¿Funcionan las excepciones singleton?

Esto activó una bandera roja para mí. ¿Las excepciones no son estables? ¿No están rellenados por la JVM para la información de seguimiento de la pila? ¿Qué ahorros obtiene realmente con esto, ya que las excepciones solo deberían ocurrir para, bueno, situaciones excepcionales?

Mi conocimiento sobre Excepciones es bastante limitado, por lo que vengo a usted con esto: ¿funcionarán las excepciones singleton, y hay alguna razón para usarlas?

Respuesta

16

Se supone que las excepciones Singleton son una optimización del rendimiento. La idea es que elimine el costo de rellenar el seguimiento de la pila al crear una excepción que generalmente es la parte más costosa de las excepciones.

Si la excepción fuera lo suficientemente exclusiva y descriptiva, y no se usaría stacktrace, entonces un singleton podría ser efectivo. Puede diseñar la aplicación de modo que un tipo de excepción específico con un mensaje específico siempre signifique una excepción orgininated de una ubicación específica. Entonces la huella de la pila sería irrelevante.

El April 22, 2003 Tech Tips article describe un caso en el que reutiliza una excepción. En este caso, están intentando jugar con el recolector de basura reduciendo la cantidad de objetos creados. Si se salta la llamada populateStackTrace(), no tendrá que preocuparse por enhebrar.

Generalmente, si el impacto en el rendimiento de una excepción está causando problemas, es un signo de que se están utilizando excepciones para la lógica de la aplicación y, en su lugar, se debe usar un código de error.

En JVMs más nuevas (1.4+, creo), esta "optimización" puede ser hecha automáticamente por la JVM cuando se ejecuta en modo "-server". Esta optimización de punto de acceso se puede controlar con la opción -XX:+OmitStackTraceInFastThrow.

Personalmente, recomendaría no utilizar el patrón de excepción singleton [anti-].

+3

Interesante respuesta. Estoy de acuerdo con tu tercer párrafo más fuertemente; las excepciones deben ser excepcionales y si se activan con la frecuencia suficiente como para causar un problema de rendimiento, debe reconsiderar su código. – Randolpho

+0

Muy interesante respuesta. –

+4

La JVM realmente comenzará a lanzar Singleton RuntimeExceptions (por ejemplo, NPE) si se lanza desde la misma ubicación varias veces, controlado por la opción '-XX: [+ -] OmitStackTraceInFastThrow' JVM. Por lo tanto, si alguien le envía un registro con un NPE y sin seguimiento, puede ser por eso :) – araqnid

1

Imagino una situación en la que desea poder detectar en sus condiciones de excepción si otra parte de su aplicación ya ha emitido una excepción; Puedo ver el uso de una excepción singleton para ese tipo de propósito; pero parece algo redundante. Básicamente, se trata de combinar la idea de un semáforo ("algo sucedió") con una Excepción ("algo me sucedió a MÍ").

3

Aunque sinceramente no estoy de acuerdo con el enfoque, Singleton Exceptions puede trabajar en un entorno de subproceso único.

Las personas que sugieren los patrones de excepción de Singleton tienden a ser utilizados para el viejo paradigma invocación/error/comprobación de errores estilo c, y quieren traducir eso en uno de esos nuevos lenguajes "orientados a objetos".

Es posible, pero yo lo llamo código olor.

+1

Las Excepciones de Singleton funcionan bien en un entorno multiproceso. La excepción solo se modifica cuando invoca fillInStackTrace(). Si usa la pila tal como está, puede lanzar un único objeto de excepción desde todos los subprocesos que pueda reunir. –

+1

También - * Estoy muy de acuerdo con el comentario al estilo C. –

+1

Java nunca es un entorno de subproceso único. –

0

Si un "método de fábrica estático" sigue devolviendo el mismo objeto, no es realmente un método de fábrica.

Incluso java.lang.Throwable tiene dos elementos de estado mutable: el seguimiento de la pila y la causa inicial, hasta que una nueva versión de Java agrega más. Cualquier Throwable compartido tendrá que o bien romper el contrato de fillInStackTrace o comportarse de manera muy extraña.Además, un Throwable reutilizado no puede razonablemente cambiar el mensaje.

Así que podrías salirte con la tuya, pero ¿te gustaría? Casi todos los problemas de rendimiento (y normalmente no deberías lanzar excepciones con demasiada frecuencia) se reducen al fillInStackTrace. Si noqueas eso, entonces hay un pequeño punto es la reutilización.

(yo prefiero la expresión "método de creación estática" a "método estático de la fábrica", porque "fábrica" ​​está demasiado sobrecargado.)