小编典典
这取决于您的JVM实现。根据Java VM规范,如果对象不是,则它是未定义的行为Throwable。
objectref 必须 是引用类型,并且必须引用Throwable类或Throwable子类的实例的对象。
如果在运行时不满足指令描述中的某些约束(“必须”或“不得”),则Java虚拟机的行为未定义。
我使用Jasmin汇编器编写了一个测试程序,该程序等效于throw
new Object()。Java HotSpot服务器VM抛出VerifyError:
# cat Athrow.j
.source Athrow.j
.class public Athrow
.super java/lang/Object
.method public ()V
aload_0
invokenonvirtual java/lang/Object/()V
return
.end method
.method public static main([Ljava/lang/String;)V
.limit stack 2
new java/lang/Object
dup
invokenonvirtual java/lang/Object/()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
禁用字节码验证程序将允许athrow执行,并且JVM在尝试打印异常的详细信息时似乎崩溃了。比较这两个程序,第一个程序抛出Exception,第二个程序是上面的测试程序抛出Object。注意它如何在打印输出的中间退出:
# 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" #
当然,禁用字节码验证程序很危险。编写VM本身是为了假定已执行字节码验证,因此不必对指令操作数进行类型检查。注意:规避字节码验证时调用的未定义行为非常类似于C程序中的未定义行为;任何事情都可能发生,包括恶魔从你的鼻子里飞出来。
2020-09-24