标签:相对 产生 duplicate pass obj 引用类型 created row erro
javac为remainder ()方法产生下列字节码序列:
// The main bytecode sequence for remainder ();
// Push local variable 0 {arg passed as
0 iload_0 // dividend)
// Push the minimum integer value
1 ldc #1 <Integer -2147483648>
// If the dividend isn‘t equal to the minimum
// integer, jump to the remainder calculation
3 if_icmpne 19
// Push local variable 1 (arg pased as
6 iload_l // divisor)
// Push -1
7 iconst_ml
// If the divisor isn‘t equal to -1, jump
// to the remainder calculation
8 if_icmpne 19
// This is an overflow case, bo throw an
// exception. Create a new OverflowException,
// push reference to it onto the stack
11 new #4 <ClaBS OverflowException>
14 dup //make a copy of the reference
//Pop one copy of the reference and invoke
// the <init> method of new OverflowException
// object
15 invokeapecial #10 <Method OverflowException()>
// Pop the other reference to the
// OverflowException and throw it
18 athrow
// Calculate the remainder
// Puab local variable 0 (arg passed as
19 iload_0 // dividend)
// Push local variable 1 (arg passed as
20 iload_l // divisor)
// Pop divisor; pop dividend; calculate,push
21 irem // remainder
22 ireturn // Return int on top of stack (the remainder)
// The bytecode sequence for the
// catch (ArithmeticBxception) clause:
// Pop the reference to the
// ArithmoticException because it isn‘t used
23 pop //by this catch clause.
24 new #2 <Class DivideByZeroException>
// Create and push reference to new object of
// class DivideByZeroException.
// Duplicate the reference to the new object
// on the top of the stack because it must be
// both initialized and thrown. The
// initialization will consume the copy of the
27 dup // reference created by the dup,
// Call the no-arg <init> method for the
// DivideByZeroException to initialize it.
// This instruction will pop the top reference
// to the object.
28 invokespecial #9 <Method DivideByZeroException()>
// Fop the reference to a Throwable object, in
// this case the DivideByZeroException,
31 athrow // and throw the exception.
方法remainder ()的字节码序列包含两个部分:第一部分是方法的正常执行路径,该部分指的是pc指针偏移量0到22;第二部分是catch子句,该部分指的是pc指针偏移量23到31。
// Overflow can occur in division when dividing
// the negative integer of the largest possible
// magnitude (Integer.MIN_VALUE) by -1, because
// this would Juat flip the sign, but there is no
// way to represent that nunber in an int.
if((dividend Integer.MIN_VALUE> &&(divisor==-1)){
throw new OverflowException();
}
所有作为Error和RuntimeException的子类的异常都是未检验的。
17.2异常表
主字节码序列中的指令irem可能会抛出ArithmeticException异常。如果发生这种情况,Java 虚拟机将在表中査找异常,然后跳转到实现catch子句的字节码序列。每个捕获异常的方法都与异常表相关联,该异常表与方法的字节码序列一起送到Class文件中。每一个被try语句块捕获的异常都与异常表中的一个入口(项)相对应。异常表中的每个入口都包括四部分信息:
•起点。
•终点。
•将要跳转到的字节码序列中的pc指针偏移量。
•被捕获的异常类的常量池索引。
下面是NitPickyMath类的remainder ()方法的异常表:
Exception table:
from to target type
I9 23 23 <Class java.lang.ArithmeticException>
上述异常表说明,ArithmeticException异常在pc指针偏移量19到22 (含)中被捕获。try语句块的终点值在“to”栏中列出。这个终点值总是比捕获异常位置的pc指针偏移量的最大值还要大1。在这个例子中,终点值为23,但捕获异常位置的pc偏移量最大值为22。偏移量19到22 (含)之间的语句对应于实现remainder ()内try语句块代码的字节码序列。上述表格中列出的target栏指出了如果ArithmeticException异常在pc指针偏移量19到22 (含)之间抛出,pc指针偏移量将要跳转到的位置。
如果异常在方法执行时抛出,Java虚拟机将会在整个异常表中搜寻相匹配的项。如果当前程序计数器在异常表入口所指定的范围内,而且所抛出的异常类是该入口所指向的类(或为指定类的子类),那么该入口即为所搜寻的入口。Java虚拟机按照每个入口在表中出现的顺序进行检索。当遇到第一个匹配项时,虚拟机将程序计数器设为新的pc指针偏移量位置,然后从该位置 继续执行。如果没有发现相匹配的项,虚拟机将当前栈帧从栈中弹出,再次抛出同样的异常。 当Java虚拟机弹出当前栈帧时,虚拟机马上终止当前方法的执行,并且返回至调用本方法的方法 中,但是并非继续正常执行该方法,而是在该方法中拋出同样的异常,这就使得虚拟机在该方 法中再次执行同样的搜寻异常表的操作。
Java程序员可以使用throw语句抛出异常,正如remainder ()方法中的catch ( Arithmetic Exception)子句,这里创建了异常DivideByZcjroExceplion,并将其抛出。执行抛出异常操作的 字节码如表17-1所示。
指令athrow从栈顶端弹出宇,并假设它是一个对象的引用,该对象为Throwable类的子类的实例(或者就是Throwable类的实例)。所抛出异常的类型由弹出的对象引用类型决定。
标签:相对 产生 duplicate pass obj 引用类型 created row erro
原文地址:https://www.cnblogs.com/mongotea/p/11980084.html