java - retornar - throw exception c#
¿Qué puedes arrojar en Java? (3)
La sabiduría convencional dice que solo se pueden lanzar objetos que extienden Throwable
en Java, pero ¿es posible desactivar el verificador de bytecode y hacer que Java compile y ejecute código que arroje objetos arbitrarios, o incluso primitivas?
athrow
la vista hacia el athrow
la JVM y aparecerá el primer objref en la pila de operandos; pero ¿comprobaría si dicha referencia apunta a un Throwable
en tiempo de ejecución?
[...] desactivar el verificador de código de bytes [...]
La verificación de bytecode es parte de la especificación de JVM, por lo que si la desactiva (o manipula la JVM de otras formas), puede, dependiendo de la implementación, hacer casi cualquier cosa (incluidas las primitivas de lanzamiento, etc.), supongo.
Cita de la especificación de JVM:
El objectref debe ser de tipo referencia y debe referirse a un objeto que sea una instancia de la clase Throwable o de una subclase de Throwable.
Es decir, su pregunta puede interpretarse como "Si una JVM se desvía de la especificación, ¿puede hacer cosas raras como arrojar primitivas?" Y la respuesta es, por supuesto, sí.
Como se menciona en la respuesta de John, puede deshabilitar la verificación (ubicar la clase en bootclasspath también debería funcionar), cargar y ejecutar una clase lanzando una clase no Throwable
éxito.
Sorprendentemente, ¡no conduce necesariamente a un crash!
Siempre que no Throwable
métodos de Throwable
implícita o explícitamente, todo funcionará perfectamente bien:
.source ThrowObject.j
.class public ThrowObject
.super java/lang/Object
.method public <init>()V
aload_0
invokenonvirtual java/lang/Object/<init>()V
return
.end method
.method public static main([Ljava/lang/String;)V
new java/lang/Object
dup
invokenonvirtual java/lang/Object/<init>()V
BeforeThrow:
athrow
AfterThrow:
return
CatchThrow:
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "Thrown and catched Object successfully!"
invokevirtual java/io/PrintStream.println(Ljava/lang/String;)V
return
.catch all from BeforeThrow to AfterThrow using CatchThrow
.end method
Resultado:
% java -Xverify:none ThrowObject
Thrown and catched Object successfully!
Depende de su implementación de JVM. Según la especificación Java VM, es un comportamiento indefinido si el objeto no es Throwable
.
El objectref debe ser de tipo referencia y debe referirse a un objeto que sea una instancia de la clase Throwable o de una subclase de Throwable.
En la sección 6.1, "El significado de ''Must''" :
Si alguna restricción ("debe" o "no debe") en una descripción de instrucción no se cumple en el tiempo de ejecución, el comportamiento de la máquina virtual Java no está definido.
Escribí un programa de prueba utilizando el ensamblador Jasmin que hace el equivalente de throw new Object()
. La VM de Java HotSpot Server lanza un VerifyError
:
# cat Athrow.j
.source Athrow.j
.class public Athrow
.super java/lang/Object
.method public <init>()V
aload_0
invokenonvirtual java/lang/Object/<init>()V
return
.end method
.method public static main([Ljava/lang/String;)V
.limit stack 2
new java/lang/Object
dup
invokenonvirtual java/lang/Object/<init>()V
athrow
return
.end method
# java -jar jasmin.jar Athrow.j
Generated: Athrow.class
# java Athrow
Exception in thread "main" java.lang.VerifyError: (class: Athrow, method: main signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
La desactivación del verificador de athrow
de athrow
permite que el athrow
ejecute y la JVM parece bloquearse cuando intenta imprimir los detalles de la excepción. Compare estos dos programas, el primero que arroja una Exception
, el segundo que es el programa de prueba anterior que arroja un Object
. Observe cómo sale en medio de una impresión:
# java -Xverify:none examples/Uncaught
Exception in thread "main" java.lang.Exception
at examples.Uncaught.main(Uncaught.j)
# java -Xverify:none Athrow
Exception in thread "main" #
Por supuesto, desactivar el verificador de bytecode es peligroso. La VM adecuada está escrita para suponer que se ha realizado la verificación del bytecode y, por lo tanto, no es necesario que compruebe los operandos de la instrucción de tipo. Tenga cuidado: el comportamiento indefinido que invoca cuando elude la verificación del código de bytes es muy parecido al comportamiento indefinido en los programas de C; puede suceder cualquier cosa, incluidos los demonios que salen volando de tu nariz.