深入理解Java之java虚拟机干净利落的规范总结 下

时间:2021-07-16 | 标签: | 作者:Q8 | 来源:网络

小提示:您能找到这篇{深入理解Java之java虚拟机干净利落的规范总结 下}绝对不是偶然,我们能帮您找到潜在客户,解决您的困扰。如果您对本页介绍的深入理解Java之java虚拟机干净利落的规范总结 下内容感兴趣,有相关需求意向欢迎拨打我们的服务热线,或留言咨询,我们将第一时间联系您!

  

        要去正确地实现一台Java虚拟机,就需要正确地读取class文件中每一条字节码指令并且能正确执行这些指令所蕴含的操作即可。
  由Java虚拟机执行的每个方法都会配有零到多个异常处理器。异常处理器描述了其在方法代码中的有效定位类型作用范围(通过字节码偏移量范围来描述)、能处理的异常类型以及处理异常的代码所在的位置。要判断某个异常处理器是否可以处理某个具体的异常,需要同时检查一场出现的位置是否在异常处理的有效作用范围内,以及出现的异常是否是异常处理器声明可以处理的异常类型或其子类型。当抛出异常时,Java虚拟机搜索当前方法包含的各个异常处理器,如果能找到可以处理该异常的异常处理器,则将代码控制权转向异常处理器中描述的处理异常的分支之中。
  首先简单介绍一下main方法中各条字节码指令所代表的意思:
  0 : 将int类型的常量i压入操作数栈中,iconst_0后面跟的那个0代表常量的值为0;
  1:将一个int类型数据由保存到本地变量表,istort_1后面的1代表的是指向当前栈帧中局部变量表的索引值;
  2:将一个值为3的int类型的常量压入操作数栈中。在这里指的是被除数3;
  3:从局部变量表加载一个int类型值到操作数栈中,这里指的是除数i;
  4:对两个int类型的数据做除法;
  5:将两数相除之后所得到的int类型数据保存到本地变量表;
  6:假如没有发生异常的话,那么执行完goto到第14条语句,函数正常返回;
  9:假如发生了除零异常,就执行这条指令,将异常对象保存到局部变量表中;
  10:从局部变量表舆情的报告中加载刚才的那个异常对象到操作数中;
  11:调用异常对象的printStackTrace方法
  14:不管是正常完成还是异常完成,最终都会返回。
  在字节码下方可以看到一个Exception table。那么它是什么东西呢?其实我们很容易能够理解它就是异常表,也就是前面我们提过的异常处理器。我们可以明显地观察出,其实try-catch代码块编译之后似乎没有生成任何指令。那么Java语言中的try-catch放到字节码当中对应什么东西呢?其实就是对应这个异常处理器。下面我们来解读一下异常处理器:
  在try语句块的执行过程中如果没有抛出异常,那么这个异常处理器不会起作用。异常处理器的作用范围是从字节码的第2行到第6行,也就是from-to标明的范围。假如编译好的代码里面第2~6句之间有一个类型为java.lang.ArithmeticException的异常实例被抛出,那么操作将转移至第9句继续执行,即进入catch语句块的实践步骤。假如说抛出的异常不是ArithmeticException实例,那么异常处理器就不能处理该异常,这个异常将返回给上一级的调用者。
  那假如try语句块包含多个catch语句块,在编译好的代码中会出现什么样的结果呢?
  如果给定的try语句块包含多个catch语句块,那么在编译好的代码中,多个catch语句块的内容将会连续排列,在异常表中也会有对应的连续排列的成员,它们的排列顺序和源码中catch语句块的出现顺序一致。main方法在执行时,如果try语句块中抛出了一个异常,这个异常将会被多个catch语句块捕获。假如第一个catch不能捕获异常(当然这里的第一个catch语句块肯定是能处理ArithmeticException,我只是举个例子),那么异常将交由第二个异常处理器来进行处理,这很容易理解。因为我在第二个catch语句块中选择的是将捕获的异常抛出,所以在字节码的第26行可以看到有一个athrow指令,在前面的学习当中我们知道它是抛出异常的意思,其实也就是对应着Java代码中的throw new Exception()。在这里,我还要顺便介绍一下Java创建一个对象的代码在编译之后会产生怎样的字节码。
  其实,刚才我所说的throw new Exception()对应athrow字节码指令只说对了一半,它在编译之后不仅仅只产生athrow这一条字节码指令。因为它还对应着一个操作,也就是new一个Exception对象。Java语言实例化一个Exception对象将会产生三条字节码指令,即上图中19,22,23三行:
  为什么会有三条指令呢?dup是做什么的?我们下面一起来学习一下
  由于讨论的是创建对象,所以在代码throw new Exception()中我们不看throw,只看new Exception()这一部分代码。
  new Exception()表达式的作用是:
  创建并默认初始化一个Exception对象;
  调用Exceptioon类的signature为()V的构造器;
  表达式的值为一个指向这个对象的引用
  对应字节码,我们可以看到:
  new Exception()对应上面的1
  invokespecial Exception.()V对应上面的2
  那么3是怎么来的?
  回归到字节码,我们可以看到new字节码指令的作用是创建指定类型的对象实例、对其进行默认初始化,并将指向该实例的一个引用压入操作数栈顶;
  然后因为invokespecial会消耗操作数栈顶的引用作为传给构造器的"this"参数,所以如果我们希望在invokespecial调用后在操作数栈顶还维持有一个指向新建对象的引用,就得在invokespecial之前先“复制”一份引用----这就是dup的来源。
  以上,就是对创建一个对象编译之后产生的字节码的解释
  编译finally语句块
  刚才我们介绍了异常处理在字节码层面的细节,但是我们还需要注意的是----由于finally能够保证不管发生任何情况,都能够执行语句块中的代码,所以在日常编码过程中我们在可能发生异常的地方(或者是不会发生异常的地方)经常使用finally来释放某些资源。
  下面我们从虚拟机层面来看看如何保证finally语句块中的代码一定会执行
  可以看到,其实编译器是通过在每个分支后面增加冗余代码的形式来保证finally语句块中的代码一定会被执行。这里和书上讲的有点出入,书上在讲解这一块的时候还是用jsr、jsr_w、ret等程序控制转移指令来解释的,但是javac在很早之前就不再为finally语句生成jsr和ret指令了。
  如果程序在try语句块中执行了return,那么代码的行为如下:
  如果有返回值,将返回值保存在局部变量表;
  执行跟在后面的冗余finally语句块中的代码;
  在finally执行完之后,将事先保存在局部变量表中的返回值压入操作数栈中之后返回。
  如果在try语句中抛出异常,那么代码的行为如下:
  将异常保存在局部变量表中
  执行finally语句块中的代码
  在执行完finally语句块中的代码后,重新抛出这个事先保存好的外卖平台代运营公司异常。
  Java虚拟机中的同步(synchronization)使用monitor的进入和退出来实现的。无论显式同步(有明确的monitorenter和monitorexit指令),还是隐式同步(依赖方法调用和返回指令实现)都是如此。
  在Java语言中,同步用得最多的地方可能是经synchronized所修饰的同步方法。同步方法并不是用monitorenter和monitorexit来实现的,而是由方法调用指令读取运行时常量池中方法的ACC_SYNCHRONIZED标志来隐式实现的。
  monitorenter和monitorexit指令用于编译同步语句块
  编译器必须确保无论方法以何种方式完成(正常结束或者是异常结束),方法中调用过的每条monitorenter指令都必须有对应的monitorexit指令得到执行。为了确保在方法异常完成时,monitorenter和monitorexit指令依然可以正确配对执行,编译器会自动生成一个异常处理器,这个异常处理器宣称自己可以处理所有异常,它的代码用来执行monitorexit指令。
  到这里深入理解Java之java虚拟机干净利落的规范总结就结束了,不足之处还望大家多多包涵!!觉得收获的话可以点个关注收藏转发一波喔,谢谢大佬们支持。
 
深入理解Java之java虚拟机干净利落的规范总结  下

上一篇:你离网管还有多远?DIY虚拟机(CentOS7)网络配置
下一篇:深入理解Java之java虚拟机干净利落的规范总结 上


版权声明:以上主题为“深入理解Java之java虚拟机干净利落的规范总结 下"的内容可能是本站网友自行发布,或者来至于网络。如有侵权欢迎联系我们客服QQ处理,谢谢。
相关内容
扫码咨询
    深入理解Java之java虚拟机干净利落的规范总结  下
    打开微信扫码或长按识别二维码

小提示:您应该对本页介绍的“深入理解Java之java虚拟机干净利落的规范总结 下”相关内容感兴趣,若您有相关需求欢迎拨打我们的服务热线或留言咨询,我们尽快与您联系沟通深入理解Java之java虚拟机干净利落的规范总结 下的相关事宜。

关键词:深入理解Java之java虚拟机干

关于 | 业务 | 案例 | 免责 | 隐私
客服邮箱:545321@QQ.com
电话:400-021-1330 | 客服QQ:545321
沪ICP备12034177号 | 沪公网安备31010702002418号