这取决于您的JVM实现。根据Java VM规范,如果对象不是,则它是未定义的行为
Throwable。
objectref 必须 是引用类型,并且必须引用Throwable类或Throwable子类的实例的对象。
在第6.1节“必须”的含义中:
如果在运行时不满足指令描述中的某些约束(“必须”或“不得”),则Java虚拟机的行为未定义。
我使用Jasmin汇编器编写了一个测试程序,该程序等效于
thrownew Object()。Java HotSpot服务器VM抛出
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 AthrowException 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/UncaughtException in thread "main" java.lang.Exception at examples.Uncaught.main(Uncaught.j)# java -Xverify:none AthrowException in thread "main" #
当然,禁用字节码验证程序很危险。编写VM本身是为了假定已执行字节码验证,因此不必对指令操作数进行类型检查。注意:规避字节码验证时调用的未定义行为非常类似于C程序中的未定义行为;任何事情都可能发生,包括恶魔从你的鼻子里飞出来。



