67194卷向字节码-Java异常到底是怎么被处理的?

既然是看了我的文章带来的进一步思考,恰巧呢,我又刚好知道。

===《点=我=立=即=进=入》===icon-default.png?t=L892http://blog.csdn.net.6m86.com

尽管这类文章看的人少,67194可是我仍是来填个坑。

害,真是暖男石锤了。

反常怎样被抛出的。

先上一个简单代码片段:

运行成果咱们都是非常的了解。

光看这仅有的几行代码,咱们是探索不出来什么有价值的东西。

咱们都知道运行成果是这样的,没有任何毛病。

这是知其然。

那么所以然呢?

所以然,就藏在代码背面的字节码里面。

经过 javap 编译之后,上面的代码的字节码是这样:

咱们首要重视下面部分,字节码指令对应的意义我也在后面注释一下:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1 //将int型的1推送至栈顶
       1: iconst_0 //将int型的0推送至栈顶
       2: idiv     //将栈顶两int型数值相除并将成果压入栈顶
       3: istore_1 //将栈顶int型数值存入第二个本地变量
       4: return   //从当时办法回来 void

别问我怎样知道字节码的意义的,翻表就行了,这玩意谁背得住啊。

经过字节码,好像也没看出什么玄机来。

可是,67194你先记着这个样子,马上我给你表演一个变形:

public class MainTest {

    public static void main(String[] args) {
        try {
            int a = 1 / 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

用 try-catch 把代码包裹起来,捕获一下反常。

再次用 javap 编译之后,字节码变成了这个样子:

能够显着的看到,字节码发生了变化,至少它变长了。

首要仍是重视我框起来的部分。

把两种情况的字节码拿来做个对比:

对比一下就很清楚了,参加 try-catch 之后,原有的字节码指令一行不少。

没有被框起来的,便是多出来的字节码指令。

而多出来的这部分,其中有个叫做 Exception table 尤为显着:

反常表,这个玩意,便是 JVM 拿来处理反常的。

至于这儿每个参数的意义是什么,咱们直接绕过网上的“二手”材料,到官网上找文档:

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.3

看起来英文很多,很有压力,可是不要怕,有我呢,我挑关键的给你 say:

首先 start_pc、end_pc 是一对参数,对应的是 Exception table 里面的 from 和 to,表明反常的掩盖规模。

比如前面的 from 是 0 ,to 是 4,代表的反常掩盖的字节码索引便是这个规模:

0: iconst_1 //将int型的1推送至栈顶 1: iconst_0 //将int型的0推送至栈顶 2: idiv     //将栈顶两int型数值相除并将成果压入栈顶 3: istore_1 //将栈顶int型数值存入第二个本地变量

有个细节,不知道你留意到了没有。

规模不包括 4,规模区间是这样的 [start_pc, end_pc)。

而至于为什么没有包括 end_pc,这个就有点意思了。

拿出来讲讲。

The fact that end_pc is exclusive is a historical mistake in the design of the Java Virtual Machine: if the Java Virtual Machine code for a method is exactly 65535 bytes long and ends with an instruction that is 1 byte long, then that instruction cannot be protected by an exception handler. A compiler writer can work around this bug by limiting the maximum size of the generated Java Virtual Machine code for any method, instance initialization method, or static initializer (the size of any code array) to 65534 bytes.

不包括 end_pc 是 JVM 规划过程中的一个历史性的错误。

因为假如 J67194VM 中一个办法编译后的代码正好是 65535 字节长,并且以一条 1 字节长的指令完毕,那么该指令就不能被反常处理机制所保护。

编译器作者能够经过约束任何办法、实例初始化办法或静态初始化器生成的代码的最大长度来处理这个错误。

上面便是官网的解释,横竖便是看的似懂非懂的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值