java operating-system jvm virtual-machine jls

¿Qué errores y excepciones Java pueden(no) ser arrojados por "declaraciones vacías"?



operating-system jvm (3)

El compilador probablemente eliminará el código que contiene "nada" o declaraciones vacías del bytecode. El equivalente en bytecode sería exactamente similar a:

// .... A(); B(); C(); D(); E(); F(); G(); H(); I(); J(); K(); L(); // ....

Por supuesto, durante la ejecución, cualquier tipo de Error inesperado (como UnknownError ) podría ocurrir y normalmente no se espera que lo maneje en su aplicación.

El tipo más cercano de excepción que podría ocurrir en cualquier lugar (enfatizado para posiblemente cubrir el tiempo entre dos instrucciones de bytecode) es excepciones asincrónicas :

La mayoría de las excepciones se producen de forma síncrona como resultado de una acción por el hilo en el que se producen, y en un punto del programa especificado que posiblemente dé como resultado dicha excepción. Una excepción asincrónica es, por el contrario, una excepción que puede ocurrir potencialmente en cualquier punto de la ejecución de un programa.

Las excepciones asíncronas ocurren solo como resultado de:

  • Una invocación del método de stop (obsoleto) de la clase Thread o ThreadGroup .

    Los métodos de stop (obsoletos) pueden ser invocados por un subproceso para afectar a otro subproceso o a todos los subprocesos en un grupo de subprocesos especificado. Son asincrónicos porque pueden ocurrir en cualquier punto de la ejecución del otro hilo o subprocesos.

  • Un error interno o limitación de recursos en la Máquina Virtual Java que le impide implementar la semántica del lenguaje de programación Java. En este caso, la excepción asíncrona que se lanza es una instancia de una subclase de VirtualMethodError .

Pero, de nuevo, no tiene sentido preocuparse por este tipo de excepciones (subclases de VirtualMethodError ) porque representan un error grave en la ejecución de JVM. Por ejemplo, puede ser debido a una interrupción manual por parte del usuario que usa Ctrl + C. En este caso, no hay mucho que puedas hacer al respecto.

¿Qué subclase (s) de java.lang.Throwable puede ser arrojado por una declaración vacía?

Con la frase "declaración vacía", me refiero a "nada", "punto y coma" y "punto y coma":

// .... A(); B(); C(); try { // nothing } catch (java.lang.Throwable e) { // which Throwable subclass might we see? } D(); E(); F(); try { ; // semi-colon } catch (java.lang.Throwable e) { // which Throwable subclass might we see? } G(); H(); I(); try { ; ; ;; ;;;;; ; ; ;;; ;; ;; ;; ;; ; ;; ; ;; // ... semi-colons } catch (java.lang.Throwable e) { // which Throwable subclass might we see? } J(); K(); L(); // ....

Qué subclases de Throwable pueden arrojarse entre A(); y B(); o entre C(); y D(); o entre F(); y G(); o entre I(); y J(); ?

O más bien, ¿ qué subclases de Throwable están garantizados para no aparecer entre esas declaraciones?

Los que conozco hasta ahora son InternalError , OutOfMemoryError , StackOverflowError y UnknownError .


Si no ejecuta ninguna instrucción, es poco probable que la VM solicite memoria o se quede sin espacio de pila para la secuencia actual. Como las otras excepciones podrían ser arrojadas porque cualquier tipo de estado en la máquina virtual está fuera de la memoria, supongo que siempre debe esperar InternalError o UnknownError para ocurrir. Por lo tanto, no debe capturar Throwable pero Exception ya que es poco probable que pueda recuperarse del error, a menos que esté creando su propio marco, tal vez.


Esta pregunta es muy similar a la otra pregunta que publicó. Creo que trataré de abordar ambas preguntas aquí.

Ya que se refiere al JVMS, asumiré que está buscando una respuesta formal, y la respuesta formal es que su (s) pregunta (s) en realidad no tienen sentido. :-)

Preguntar cómo ejecutará la JVM un fragmento de código fuente de Java es como preguntarle a un matemático la forma correcta de calcular 10 + 10. El matemático probablemente dirá algo así como " cómo calcularlo no está definido". Del mismo modo, el JLS que define el significado del fragmento de Java no entra en detalles sobre cómo ejecutarlo.

Entonces, primero permítame formalizar su pregunta un poco: "¿Dónde en el bytecode (emitido por la implementación de referencia de javac ) correspondiente a los fragmentos de Java dados podrían ocurrir VirtualMachineErrors ?"

Esta pregunta es posiblemente mucho más simple de responder. La sección relevante de JVMS dice

Una implementación de Java Virtual Machine arroja un objeto que es una instancia de una subclase de la clase VirtualMethodError cuando un error interno o limitación de recursos impide que implemente la semántica descrita en este capítulo. Esta especificación no puede predecir dónde se pueden encontrar los errores internos o las limitaciones de recursos y no ordena con precisión cuándo se pueden informar.

Por lo tanto, la respuesta es: entre dos instrucciones de bytecode.

Ahora para volver a su pregunta original: Este fragmento, por ejemplo

try { // nothing } catch (java.lang.Throwable e) { // which Throwable subclass might we see? }

se compila en el programa vacío, que no puede arrojar razonablemente ninguna excepción.

En cuanto a su pregunta de seguimiento en un comentario:

¿Debería leer JLS 11.1.3 como "se garantiza que las subclases de Throwable no aparecerán entre bytecode a menos que sea una subclase de VirtualMachineError "?

Sí, podrías ponerlo así. Tal vez lo hubiera redactado de forma un poco diferente: cualquier instrucción puede dar lugar a

  • las excepciones especificadas por el conjunto de instrucciones JVM para la instrucción en cuestión,
  • cualquier excepción de tipo VirtualMachineError
  • y ninguna otra excepción