3.12 抛出和处理异常 在程序中使用throw关键字来抛出异常.编译结果很简单. void cantBeZero(int i) throws TestExc { if (i == 0) { throw new TestExc(); } } 编译为: Method void cantBeZero(int) iload_1 // (i) ifne // If i==, allocate instance and throw new # // Create instance of TestExc d…
本文翻译自:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html 第二章 虚拟机结构 本文档描述了一个抽象的虚拟机规范,并不描述某个特定的虚拟机实现. 要正确实现一个Java虚拟机,你只需要能够读取class文件的格式并正确执行其中指定的操作.具体的实现并不是java虚拟机规范的一部分,因为它们会限制实现者的创造力.比如,运行时数据区域的内存布局,垃圾回收使用的算法,以及任何的java虚拟机指令的内部优化(如:转换为机器码)…
2.5 运行时数据区域 java虚拟机定义了多个用于程序执行期间的运行时数据区域.这些数据区域中一些随着java虚拟机的启动而创建,随着虚拟机的退出而销毁.其他的数据区域时和线程相关的.线程相关数据区域随着线程的创建而创建,随着线程的退出而销毁. 2.5.1 pc寄存器 java虚拟机支持多个线程同时执行.每个线程拥有自己的pc(program counter)寄存器.在任何时刻,一个线程只会执行一个方法,即线程的当前方法.如果执行的方法不是本地(native)方法,pc寄存器包含当前正在执行的…
2.11 指令集简介 java虚拟机指令由一个字节的操作码,接着时0个或多个操作数组成,操作码描述了执行的操作,操作数提供了操作所需的参数或者数据.许多指令没有操作数只包含一个操作码. 如果忽略异常处理,那java虚拟机使用下面的伪代码循环即可有效工作: do{ 自动计算pc然后获取pc中的操作码; if (存在操作数) 获取操作数; 执行这个操作码定义的操作 }while(是否有更多需要执行); 操作数的数量和大小都有操作码决定.如果一个操作数大于一个字节,那么它将以大端顺序存储——高位在前.…
本文翻译自:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html 第三章 java虚拟机的编译 java虚拟机是设计用来支持java编程语言的.Oracle的JDK软件包含了一个将Java源代码编译成java虚拟机指令集的编译器,以及一个用于java虚拟机本身的运行时系统.了解编译器如何使用java虚拟机对编译器作者来说是有用的,同样也有助于理解java虚拟机本身.本章中编号的部分不是规范性的. 注意,术语“编译器”有时用于…
3.6 接受参数 如果n个参数传给一个实例的方法,按照约定,它们被接受并放在这个新方法创建的栈帧中的局部变量表里,在局部变量表中的序号从1到n.这些参数按照它们传递过来的顺序存放.例如: int addTwo(int i, int j) { return i + j; } 编译为 Method int addTwo(int,int) iload_1 // (i) iload_2 // (j) iadd // Add; leave int result on operand stack iretu…
3.3 算术运算 java虚拟机通常在操作数栈上进行算术运算(例外情况是iinc指令,它直接增加一个局部变量的值).例如下面的align2grain()方法,它的作用是将int值对齐到2的指定次幂: int align2grain(int i, int grain) { return ((i + grain-1) & ~(grain-1)); } 算术运算的操作数是从操作数栈中弹出的,运算结果会压回操作数栈.因此,算术子计算的结果可以作为嵌套计算的操作数.例如.~(grain-1)的计算结果就是…
2.7 对象的表示 java虚拟机并不要求对象满足任何特定的内部结构. 在Oracle的一些Java虚拟机实现中,对类实例的引用是指向句柄的指针,该句柄本身是一对指针:一个指向包含对象方法的表和指向表示Class对象的指针对象的类型,另一个是从堆为对象数据分配的内存. 2.8 浮点算法 Java虚拟机包含IEEE二进制浮点运算标准(ANSI / IEEE Std.754-1985,New York)中规定的浮点运算的子集. 2.8.1 Java虚拟机浮点算法和IEEE 754 Java虚拟机支持…
2.6. 栈帧 栈帧用于存储数据和部分结果,同样也用于执行动态链接,返回方法的值和分派异常. 当方法被调用的时候会创建一个新的栈帧.当一个方法调用结束时,它对应的栈帧就被销毁了,不管是正常调用结束还是意外结束(抛出了未被捕获的异常).栈帧分配在线程创建的虚拟机栈中.每个栈帧都有自己的局部变量表,操作数栈,以及当前方法的类的运行时常量池的引用. 可以使用附加的特定于实现的信息来扩展帧,例如调试信息 局部变量表和操作数栈在编译时期就确定了,并且通过栈帧关联的方法的code提供.因此栈帧的大小仅仅取决…
2.10 异常 java虚拟机中的异常用Throwable类或者它的子类的实例来表示.抛出一个异常会导致立即非本地(an inmediate nolocal)的控制转移,从发生异常的地方跳到处理异常的地方. 大多数异常是在当前线程执行某些操作时同步发生的.对应的,非同步异常可能发生在程序执行的任何阶段.java虚拟机会由于下面三个原因中的一个抛出异常: 执行athrow指令 java虚拟机同步检测到非正常的执行情况.这些异常不是在程序中的任意点抛出的,而是在执行以下指令后同步抛出: 指明异常作为…