Teniendo en cuenta este programa:extraño entrada de la tabla de excepción producida por javac de Sun
class Test {
public static void main(String[] args) {
try {
throw new NullPointerException();
} catch (NullPointerException npe) {
System.out.println("In catch");
} finally {
System.out.println("In finally");
}
}
}
de Sun javac
(v 1.6.0_24) produce el siguiente código de bytes:
public static void main(java.lang.String[]);
// Instantiate/throw NPE
0: new #2; // class NullPointerException
3: dup
4: invokespecial #3; // Method NullPointerException."<init>":()V
7: athrow
// Start of catch clause
8: astore_1
9: getstatic #4; // Field System.out
12: ldc #5; // "In catch"
14: invokevirtual #6; // Method PrintStream.println
17: getstatic #4; // Field System.out
// Inlined finally block
20: ldc #7; // String In finally
22: invokevirtual #6; // Method PrintStream.println
25: goto 39
// Finally block
// store "incomming" exception(?)
28: astore_2
29: getstatic #4; // Field System.out
32: ldc #7; // "In finally"
34: invokevirtual #6; // Method PrintStream.println
// rethrow "incomming" exception
37: aload_2
38: athrow
39: return
Con la tabla siguiente excepción:
Exception table:
from to target type
0 8 8 Class NullPointerException
0 17 28 any
28 29 28 any
Mi pregunta es: ¿Por qué incluye esa última entrada en la tabla de excepciones?
lo que tengo entendido, que básicamente dice "si el astore_2
se produce una excepción, lo coge y vuelva a intentar la misma instrucción".
Dicha entrada se produce incluso con vacío try/catch/finally cláusulas tales como
try {} catch (NullPointerException npe) {} finally {}
Algunas observaciones
- Eclipse compilador no produce ninguna entrada tales tabla de excepciones
- La especificación de JVM no documenta ninguna excepción de tiempo de ejecución para the
astore
instruction. - Sé que es legal que la JVM arroje
VirtualMachineError
para cualquier instrucción. Supongo que la entrada peculiar evita que dichos errores se propaguen desde esa instrucción.
Voy a publicar esto como un comentario, ya que no he logrado entender este concepto. Hay una entrada sobre este tema, sobre por qué se genera la última entrada en [un blog] (http://cliffhacks.blogspot.com/2008/02/java-6-tryfinally-compilation-without.html). Aparentemente, el comportamiento del compilador para compilar el bloque finally, como se especifica en la especificación de la VM, está un poco fuera de lugar, en lo que respecta al compilador de Sun/Oracle. La última entrada de la tabla de excepciones está en su lugar para proteger el "controlador de excepciones generado". No descubrí cómo funciona la guardia y por qué debería funcionar de esa manera. –