在上一次【http://www.javashuo.com/article/p-xthqgezz-dy.html】初步对异常表相关的概念进行了了解,先来回顾一下:html
其源代码也贴一下:java
下面来看一下jclasslib关于这个test()的信息:web
我们重点来看一下Code信息,以下:debug
其实也就是对应于javap -verbose看到的字节码信息,我们一行行的跟源代码进行比对一下:server
点击看一下new的助字符的官方解释:htm
实际对应源码就是:对象
查看一下官网的解释:blog
查看一下解释:ip
回到我们这句话其意思就是将常量“test.txt”推到常量池中使得能构造出FileInputStream对象。ssl
这个咱们以前了解过,这里再看一下官网的解释:
回到我们这句话意思就是调用了父类的构造方法,由于建立子类其父类确定得要先被建立才行。
也就是将"is"存到局部变量当中,因此前面的这些助记符就对应这样一个句源码,以下:
对应于
相似的下面这一行源代码其实对应的助字符差很少,以下:
下面也来瞧一下:
new一个对象:
跟以前同样,将最顶层操做数栈的值进行复制,往下:
其中sipush官网解释以下:
这里有一个细节须要注意:源代码中的999实际上是一个int类型的,以下:
可是在字节码中999实际上是属于short类型范围以内,因此是当一个short类型处理了。
调用ServerSocket的构造方法及父类的,很少说比较容易理解。
看一下它官网的解释:
也就是将引用赋给了serverSocket变量。
官网的解释:
其实对于方法的调用方式都是基于操做栈的,因此有大量的入栈和出栈的一些操做在里面的。
发现这对应于代码:
因为catch块中没有写代码,因此直接就到了finally了。
也就是finally这个关键字嘛。
调用打印实例方法。
接下来发现有大量的goto助记符:
也就是对于异常在字节码的表现形式是经过goto来将整个执行进行中断的,为了能理解这里面的goto,此时须要先分析一下异常表信息,以下:
其中能够总体看到“Catch Type”这行,恰好跟我们捕获的异常能对应上,以下:
其中还有最后一个:
其中理论依据为:
下面具体来看一下:
发现Start PC和End PC都是从0到26,先来回顾一下这两个的含义:
也就是表示:
其实对应于源代码就是try的部分,以下:
这段代码抛出任何异常都会有相应的异常表项来处理,我们一一来看一下:
也就是说若是代码发现了FileNotFoundException异常时,则会由37这个位置的Handler PC来处理异常,那37对应于哪呢?
而astore_1表示:
那如何理解呢?来看下源代码:
很明显当生成异常时会将异常对象赋值给这个ex,因此就会有这样的一个引用赋值操做,因为这个catch块中没有写任何代码,因此就立马就执行到了finally块了,也就是对应于这段助记符:
最后又有一个goto了,以下:
第一个异常的整个字节码流程分析完以后,其它两个就基本相似了,我们来过一遍:
当发生异常则会跳到49的Handler PC,以下:
接着再看第三个异常:
而后会跳到61,看一下,同样的套路:
好了对于我们本身捕获的异常的内部处理机制已经很是之清楚了,剩最后一种异常状况下,以下:
从程序角度照理应该是Exception已经包含全部能够捕获的异常了,可是从字节码角度并不这样认为,因此这也是为啥会有这么一个异常的状况出现,表示处理上面我们手动捕获的以外不可能处理的异常,这是编译器自动为咱们生成出来的,我们来看一下73是啥:
只是其中发现了一个athrow,这是个什么东东:
至此,我们就完全把异常机制相关的东东完完整整的分析完了,下面来总结一下:
Java字节码对于异常的处理方式:
一、统一采用异常表的方式来对异常进行处理。
二、在以前的JDK 1.4.2以前的版本中并非使用异常表的方式来对异常进行处理的,而是采用特定的指令方式。【了解既可】
三、当异常处理存在finally语句块时,现代化的JVM采起的处理方式是将finally语句块的字节码批接到每个catch块后面,换句话说,程序中有多少个catch块,就会在每个catch块后面重复多少个finally语句块的的字节码。从字节码就能够得知:
关于异常表就了解到这,接下来了解另一个信息,以下:
根据以前的了解,咱们也知道这个属性主要是描述字节码的位置对应源代码的行号,便于debug,以下:
下面来一一细看一下:
字节码0处对应源代码13行,瞅一下:
其中的Start PC是指代码字节码的起始位置,恰好是对应的。
继续:
字节码10对应源代码14,看一下:
彻底能对应上,继续再挑一个看,因为规则是同样的,就不必彻底一个个对了,知道个大概做用就成:
字节码49对应源代码18:
因此经过这个就能够将字节码跟源代码对应起来。
最后再来看一下它:
发现jclasslib中只有3个,而以前在javap -verbose中看到的是有4个,回忆下:
由于目前jcalsslib打开的是一个静态的class,并不知道是否抛出异常,因此静态的状况下就只能看到3个局部变量,javap -verbose上看到的是最大能够有4个局部变量,也就是一旦运行抛异常了那最终就有4个局部变量啦,没毛病的!