2012-01-04 18 views
12

Vine a Java desde C++. En el mundo de C++ prestamos atención a la seguridad de las excepciones, y notamos que los mutadores pueden proporcionar diferentes garantías frente a las excepciones lanzadas por el propio mutador o un método al que delega (mínimo, fuerte, sin lanzamiento). La implementación de un método que tiene una fuerte garantía de excepción requiere que algunas operaciones básicas estén garantizadas para no arrojar nunca una excepción. El JLS realiza afirmaciones sobre qué operaciones pueden arrojar qué tipos de excepciones, pero el error VirtualMachineError presenta un problema. Dijo el JLS:No-throw VirtualMachineError garantiza

una limitación de error o un recurso interno impide que la máquina virtual de Java de la implementación de la semántica de programación Java idioma; en este caso, se lanza una instancia de una subclase de VirtualMachineError.

El JLS dice no más sobre VirtualMachineError. Un "error interno" significa un error en la JVM, por lo que no estoy interesado en ese caso: a pesar de los errores en la JVM, todas las apuestas están desactivadas. Pero, ¿qué pasa con el caso de "limitación de recursos"? ¿Hay alguna operación que garantice que nunca fallará debido a una limitación de recursos?

+0

Lo más parecido a una respuesta sería 'try {...} catch (Throwable t) {}'. Por supuesto, si la memoria se agota, cualquier continuación resultará ser casi imposible. Ahora eso no es diferente en C++. –

+2

Estoy respondiendo mi propia pregunta. Las preguntas frecuentes incluso eculra esto. – Raedwald

Respuesta

12

Dijo el Java Virtual Machine Specification:

Esta especificación no puede predecir dónde se pueden encontrar errores internos o recursos limitaciones y no obliga precisamente cuando que se puede informar. Por lo tanto, cualquiera de los VirtualMachineError subclases definidos a continuación puede ser lanzado en cualquier momento durante la operación de la máquina virtual Java :

En Java, por lo tanto no hay garantías de excepción pueden hacerse con respecto a VirtualMachineError excepciones. Todas las garantías de excepción deben estar sujetas a la calificación "... pero no si se arroja un VirtualMachineError". Esta es una de las formas en que Java es diferente de C++.

Esto también sugiere que no tiene mucho sentido detectar una excepción VirtualMachineError, porque el programa está en un estado indefinido si se ha lanzado. Eso lamentablemente incluye OutOfMemoryError excepciones. Desafortunado, porque si una de varias tareas falla porque necesita demasiada memoria, es posible que deseemos continuar con las otras tareas.

+0

¿Está respondiendo su propia pregunta o simplemente está agregando algo? – skaffman

+1

Estoy respondiendo mi propia pregunta. – Raedwald

+0

Tanto VirtualMachineError como OutOfMemoryError son errores. En lugar de simplemente bloquear, Java arroja un error en algunas condiciones anormales. Dicho esto, ninguna de las subclases de Error está destinada a ser capturada por la mayoría de los programas. Los errores se pueden distinguir de Excepciones, que pueden ser atrapadas. Las garantías de excepción promovidas por Herb Sutter se pueden aplicar también a Java, para Excepciones normales. –

1

Si se trata de limitación de recursos, en primer lugar, no se realizan operaciones. Aquí hay un enlace para obtener el ejemplo perfecto para tener VirtualMachineError. Virtual machine error

Este error no es algo así como OutofMemoryError, donde en ese momento algunas operaciones podrían estar en progreso.

+0

" no se llevan a cabo operaciones ". Esa sería la "fuerte excepción de garantía". Pero no se hace tal garantía. – Raedwald

+0

Si mi interpretación es correcta, basándome en el ejemplo anterior, antes de iniciar la VM, estaba buscando recursos definidos como los parámetros -Xmx y no podía encontrar el tamaño definido de la memoria y arrojar un error. Estoy de acuerdo con su punto de que no hay garantía, pero no sé por qué. – kosa

1

Veo que ha respondido a su propia pregunta y puedo entender por qué esto sería ligeramente sorprendente para usted, que proviene de un estricto fondo de C++. Esta es solo la realidad de las máquinas de memoria administrada (virtual) y no está limitada a solo Java. La memoria puede agotarse, ya que la JVM está limitada a la cantidad de almacenamiento que puede usar (configurable en la línea de comandos de Java).

Algo similar, pero no equivalente, en el mundo C++/código de máquina sería un GENERAL_PROTECTION_FAULT (o SEGMENTATION_FAULT si estás en * NIX) que obtendrías al intentar direccionar la memoria que no se ha asignado o es fuera de su espacio de direcciones virtuales.Proporcionar una "fuerte garantía de excepción" frente a ese escenario es igualmente difícil ya que la causa puede ser un error en el código o completamente fuera del control del programa.

+0

Un SEGV indica un error en el programa. Su analogía en Java es 'NullPointerException'. – Raedwald

+0

No veo cómo esta es una característica general de una máquina virtual administrada. El JVMS permite lanzar 'OutOfMemoryError' incluso cuando no estés usando' new' o intentando cargar una clase. – Raedwald

+0

@Raedwald solo obtendrá un NPE cuando intente hacer referencia a 'null'. Solo obtendrá OutOfMemoryError después de intentar asignar más memoria (o si llama a un método que sí lo hace) y se haya ejecutado el GC y no se haya liberado suficiente memoria. –

0

En Java, puede llamar a Thread.stop() o detener (Throwable) en cualquier momento. La mayoría de los errores se consideran tan críticos que no deberías tratar de manejarlos a menos que realmente sepas lo que estás haciendo.

Después de haber desarrollado la aplicación Java del lado del servidor durante 12 años, puedo decir que nunca he oído que nadie se preocupe por las excepciones al azar que se lanzan. Sospecho que no es un problema del que debas preocuparte con Java.

¿Puede dar un ejemplo de por qué cree que necesita una garantía, ya que es probable que haya otra forma de resolver el problema?

+2

La excepción 'OutOfMemoryError' es el caso más interesante. Como digo en mi propia respuesta: desafortunado, porque si una de varias tareas falla porque necesita demasiada memoria, es posible que deseemos continuar con las otras tareas. Pero si la JVM puede arrojar un 'OutOfMemoryError', no podemos confiar en que nuestro programa esté en un estado válido cuando detectamos un' OutOfMemoryError'. Esto hace que el enfoque try-catch-discard sea poco confiable. – Raedwald

+0

Agregó "NO" que falta antes de "tratar de manejarlos". –

+2

@Raedwald Tienes razón en que descartar el OOME no es confiable.Lo que tiene que hacer es definir la memoria máxima en la que esperaría que falle toda la JVM (no solo un límite flexible) y evitar realizar operaciones que podrían fallar porque no tiene idea de cuánta memoria usan. En el peor de los casos, debe usar un proceso separado que se puede reiniciar si es necesario. (Esto también protege contra errores en las bibliotecas JNI) –

Cuestiones relacionadas