深入JVM学习笔记 JVM指令介绍
JVM指令介绍
栈和局部变量操作
1、常量入栈操作
--入栈操作三种方式指明常量的值:常量值隐式包含在操作码内部,常量值在字节码流中如同操作数一样紧随在操作码之后,或者从常量池中取出常量
--Java栈中每一个位置的长度都是一个字长(至少32位宽)
--Java源代码中所有的字符串文字最终都作为入口存储与常量池中。如果同一个应用程序的多个类都使用同样的字符串文字,按摩此字符串文字将在使用它的所有类的class文件中出现。但Java虚拟机会把所有具有相同字符顺序的字符串文字处理为同一个String对象,只会创建一个相应的String对象来表示所有的字符串文字。
备注:要深刻理解源代码中字符串文字与JVM生成的String对象的差别。
--wide指令:跳转指令并不允许直接跳转到被wide指令修改过的操作码。
类型转换
1、设计 byte short和char类型的运算操作首先会把这些值转换为int类型,然后对int类型值进行运算,最后得到int类型的结果。
整数运算
--取余运算 irem 取反运算 ineg
逻辑运算
-- "<<" ishl 向左移位
">>" ishr 向右移位
">>>" iushr 逻辑移位
浮点运算
1、在Java虚拟机中,浮点运算基于32位float类型和64位double类型进行。浮点数由符号、尾数、基数和指数四部分组成。
2、float类型的格式如下,符号位表示为s,指数位表示为e,尾数位表示为m:指数占8位,double类型中占11位
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
指数位的解释有三种方式:
指数位全为1,表示该数为乘法或者减法所产生的特殊值之一——无穷大或者非数字(NaN),NaN是某种特殊操作,诸如0除以0的结果。
指数位全是0,表示该数是一个非规范化浮点数。
其他类型的指数位表示该数十一个规范化的浮点数。
3、float类型的特殊值
指数位全为1而且尾数位全为0,表示无穷大
指数位全为1,尾数位不全为0,表示该数为"NaN":Java虚拟机总是为NaN产生同样的尾数,除了尾数中最高有效位为1外,其余全为0
4、2的幂指数的确定
指数位既不全为0,也不全为1,该数即为规范化的浮点数。可以通过把指数看成一个整数,然后减去一个偏移量来确定2的幂指数。对于float类型,偏移量是127,double类型是1023
浮点数表示参考文章:http://apps.hi.baidu.com/share/detail/30212277
对象和数组
1、只有对象引用和基本类型可以在Java的栈中以局部变量形式存在,Java栈中不能容纳对象。
2、针对数组的操作码
--newarray操作码用来创建基本类型的数组
--anewarray/multianewarray操作码用来创建对象引用的数组
finally子句
--jsr指令是使Java虚拟机跳转到微型子例程的操作码。
--ret指令的功能是执行从子例程中返回的操作。
jsr指令会把返回地址压入栈,在执行子例程开始时又会把返回地址弹出栈,然后存入局部变量中。当finally执行结束后(此结束是指finally执行到了最后一条语句正常执行完毕,不包括抛出异常,或执行return、continue、break等情况),ret指令从局部变量里取出返回地址,然后返回。如果finally子句非正常结束,则根本不会执行ret指令,这也是为什么返回地址要从栈中弹出并存到局部变量的原因,否则如果ret指令不执行该地址将存在在栈中而不会被用到。
--Java虚拟机在finally子句执行完毕钱返回一个值的方式:
public class Test4 {public int test(){int i = 0;try{i = 1;return i;}finally{i = 2;}}public static void main(String[] args) {Test4 t = new Test4();System.out.println(t.test());}}--------------------- i = 1public class Test4 {public int test(){int i = 0;try{i = 1;}finally{i = 2;return i;}}public static void main(String[] args) {Test4 t = new Test4();System.out.println(t.test());}}--------------------- i = 2

public class SuperClass{ private void speakHi(){ System.out.println("super class say hi"); } void sayHi(){ speakHi(); } } public class SubClass extends SuperClass{ void speakHi(){ System.out.println("sub class say hi"); } public static void main(String[] args){ SubClass ins = new SubClas(); ins.sayHi(); } } public class SuperClass{ private void speakHi(){ System.out.println("super class say hi"); } void sayHi(){ speakHi(); } } public class SubClass extends SuperClass{ void speakHi(){ System.out.println("sub class say hi"); } void sayHi(){ speakHi(); } public static void main(String[] args){ SubClass ins = new SubClas(); ins.sayHi(); } }