什么可以扔在Java中? [英] What can you throw in Java?

查看:97
本文介绍了什么可以扔在Java中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

传统的智慧说,您只能在Java中抛出扩展 Throwable 的对象,但是可以禁用字节码验证器,并使Java能够编译并运行任意的代码对象 - 甚至原语?



我查了JVM的 athrow ,它将弹出操作数堆栈上的第一个objref;但是会在运行时检查是否指示参考指向 Throwable

解决方案

这取决于您的JVM实现。根据Java VM规范,如果对象不是 Throwable ,则是未定义的行为。


objectref 必须是引用类型,并且必须引用一个Throwable类或Throwable子类的实例对象。


第6.1节必需的含义


如果某个约束(一个必须或必须不是)在运行时不满足Java虚拟机的行为是未定义的。


我写了一个测试程序使用 Jasmin汇编器,它相当于抛出新的Object()。 Java HotSpot Server 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 public static main([Ljava / lang / String;)V
.limit stack 2

new java / lang / Object
dup
invokenonvirtual java / lang / Object /< init&
运动

返回
.end方法

#java -jar jasmin.jar Athrow.j
生成:Athrow.class

#java Athrow
线程main中的异常java.lang.VerifyError :(类:Athrow,方法:主签名:([Ljava / lang / String;))V)只能抛出Throwable对象

禁用字节码验证器允许 athrow 执行,并且JVM似乎在尝试打印除外时崩溃离子的细节。比较这两个程序,第一个抛出异常的程序,第二个是上述测试程序,抛出一个 Object 。注意在打印输出中如何退出:

 #java -Xverify:none examples / Uncaught 
线程mainjava.lang.Exception
在examples.Uncaught.main(Uncaught.j)
#java -Xverify:none Athrow
线程main中的异常#

当然,禁用字节码验证器是危险的。虚拟机适配器被写入以假定已经执行了字节码验证,因此不必对指令操作数进行类型检查。当心:当您规避字节码验证时,您调用的未定义的行为非常类似于C程序中的未定义行为;任何事情都可能发生,包括从你的鼻子飞出来的恶魔。


Conventional wisdom says you can only throw objects that extend Throwable in Java, but is it possible to disable the bytecode verifier and get Java to compile and run code that throws arbitrary objects - or even primitives?

I looked up the JVM's athrow and it will pop the first objref on the operand stack; but would it check if said reference points to a Throwable at run time?

解决方案

It depends on your JVM implementation. According to the Java VM specification it is undefined behavior if the object is not Throwable.

The objectref must be of type reference and must refer to an object that is an instance of class Throwable or of a subclass of Throwable.

In section 6.1, "The Meaning of 'Must'":

If some constraint (a "must" or "must not") in an instruction description is not satisfied at run time, the behavior of the Java virtual machine is undefined.

I wrote a test program using the Jasmin assembler which does the equivalent of throw new Object(). The Java HotSpot Server VM throws a 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

Disabling the bytecode verifier allows the athrow to execute and the JVM appears to crash when it tries to print the exception's details. Compare these two programs, the first which throws an Exception, the second which is the above test program which throws an Object. Notice how it exits in the middle of a printout:

# 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" #

Of course, disabling the bytecode verifier is dangerous. The VM proper is written to assume that bytecode verification has been performed and therefore does not have to typecheck instruction operands. Beware: the undefined behavior that you invoke when you circumvent bytecode verification is much like the undefined behavior in C programs; anything at all can happen, including demons flying out of your nose.

这篇关于什么可以扔在Java中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆