JVM指令集
2016-10-01 11:21
148 查看
JVM指令可以分为如下几类:
(1)加载和存储指令
加载指令(将局部变量表中数据,或者常量值,及 常量池中数据加载到操作数栈中)
存储指令(将操作数栈顶的数据加载到局部变量表中)
(2)运算指令
(3)类型转换指令
(4)操作数栈管理指令
(5)控制转移指令
(6)对象创建以及方法、’属性调用指令
扩展操作:
(7)三种循环(while,for,do..while)的调用指令
(8)switch语句,及break,continue的操作指令
java虚拟机的tablewitch和lookupswitch指令用于支持switch条件,当switch语句中的case分支的条件值比较稀疏时,使用lookupswitch代替tablewitch
(9)异常的操作指令
athrow 指令
学习指令集能解决常用问题:
(1) String a="123"; String b="1"+"23"; String c="1"+new String("23"); 比较a是否与b,c相同,这是通过javap查看 常量数据的存储,以及 +号运算原理,对字符串的理解
(2)a=1; a=a++; a=a++; a=a++; 运算完a的值是多少?只能通过javap反编译查看内部运行原理
(3)java定义枚举类型,javap查看编译器给我们生成的代码
(4)java实现装箱拆箱的原理
以上种种都需要我们会看JVM指令集,才能去体会java内部运行结构,从本质上去理解代码,有助于我们加深对java的理性认识!
(1)加载和存储指令
加载指令(将局部变量表中数据,或者常量值,及 常量池中数据加载到操作数栈中)
将一个常量加载到操作数栈: aconst_null 将null加载到操作数栈 iconst_m1 将-1 加载到操作数栈顶 iconst_0, iconst_1,iconst_2,.........,iconst_5 将int型对应的1-5加载到栈顶 lconst_0,lconst_1 将long型0,1推送到栈顶 fconst_0,fconst_1,fconst_2 将float型0,1,2推送至栈顶 dconst_0,dconst_1 将double型0,1推送至栈顶 bipush 将常量值-128-127整形数据(除去iconst_m加载的几个数据)推送至栈顶 sipush 将一个短整形 -32768-32767(除去bipush,iconst_m加载数据)推送至栈顶 ldc 加载(除去 iconst_m,bipush,sipush)的整形数据推送至栈顶,这个数据是从常量池中拿到的 ldc_w 加载 float 类型数据(除去fconst_m)推送至栈顶 ldc_2w 加载long和double型数据(除去lconst_m和dconst_m) 将局部变量表中的数据加载到操作数栈: iload_0,iload_1,iload_2,iload_3 将第四个int型局部变量表中的值推送到栈顶 lload_0,...................................lload_3 long fload_0,,. ................................fload_3 float dload_0...................................dload_3 double aload_0....................................aload_3 引用型 注意:int,long,float型数据都只是设置四个,其他的用iload x,指定位置 eg: iload 6 将局部变量表中第七个int类型的变量值推到栈顶
存储指令(将操作数栈顶的数据加载到局部变量表中)
istore_0,istore_1..........istore_3 将整形数值存入第i个本地变量 dstore_0..........................dstore_3 double型,还有fstore_0,astore_0........... 若局部变量的个数多于4个时,用istore m 将栈顶的元素送入到局部变量表中第m+1个元素的位置 eg: astore 7 将操作数栈顶的数据存储到局部变量表中的第8个引用类型的变量中
(2)运算指令
加法指令: iadd、ladd、 fadd、dadd 将 栈中栈顶和下面紧挨着栈顶的数相加,并将相加的结果值压进栈顶 减法指令 : isub、lsub、fsub、dsub 乘法指令:imul、lmul、fmul、dmul 除法指令:idiv、ldiv、fdiv、ddiv 求余指令:irem、lrem、frem、drem 取反指令:ineg、lneg、fneg、dneg 位移指令:ishl、ishr、iushr、lshl、lshr、lushr 按位或指令:ior、lor 按位与指令:iand、land 按位异或指令:ixor、lxor 局部变量自增指令:iinc iinc 后面跟两个值,将指定int型变量增加指定的值(如i++,i--.i+=2) eg:iinc 3,1 表示的为局部变量表中的第四个变量(从0开始)加上1,等价于 a++,a+=1,(a为第四个变量) 注意:a=a+1,a++两者使用的指令的区别
(3)类型转换指令
i2l 将栈顶int型数值强制转换成long型数值并将结果压入栈顶 i2f 将栈顶int型数值强制转换成float型数值并将结果压入栈顶 i2d 将栈顶int型数值强制转换成double型数值并将结果压入栈顶 l2i 将栈顶long型数值强制转换成int型数值并将结果压入栈顶 l2f 将栈顶long型数值强制转换成float型数值并将结果压入栈顶 l2d 将栈顶long型数值强制转换成double型数值并将结果压入栈顶 f2i,f2d,d2i,d2l,d2f,i2b,i2c(int 到char),i2s(int到short)
(4)操作数栈管理指令
pop 将栈顶数值弹出(数值不能使long或double型),1个字节大小 pop2将栈顶的(double或long)弹出,2个字节大小 dup/dup2 复制栈顶1/2个字节的数值,并将复制值压入栈顶 dup_x1:表示复制堆顶偏移1个位置的1个字节的内容,并入到顶栈 eg:操作数栈word1, word2,word1是栈顶,执行后变成word2,word1,word2 dup_x2 表示复制堆顶偏移2个位置的1个字节的内容,并入到顶栈 eg:操作数栈 word1, word2,word3,word1是栈顶,执行后变成word3,word1,word2,word3 dup2_x1 表示复制堆顶偏移1个位置的2 个字节的内容,并入到顶栈 eg:操作数栈 word1, word2,word3,word1是栈顶,执行后变成word2,word3,word1,word2,word dup2_x2 表示复制堆顶偏移 2个位置的2个字节的内容,并入到顶栈 eg:操作数栈 word1, word2,word3,word4,word1是栈顶,执行后变成word3,word4,word1,word2,word3,word4
(5)控制转移指令
(6)对象创建以及方法、’属性调用指令
创建类实例的指令: new 创建数组的指令:newarray、anewarray 注意: newarray 创建的为基本类型数组(int,char等),anewarray创建的为引用类型的数组(String等) 访问或赋值类字段和实例字段:getstatic,getfield,putstatic,putfield 将一个操作数栈的值存储到数组元素中的指令:bastore,castore,sastore,iastore,fastore,dastore,aastore eg: int a[]=new int[5]; a[0]=1; 指令如下: iconst_5 newarray int //创建5个长度的int数组 astore_1 //赋值给 数组a aload_1 iconst_0 iconst_1 iastore 可以看到 aload_1,iconst_0,iconst_1,iastore 四步是a[0]=1的执行过程, 栈中从下到上依次为 数组a,0,1,iastore指令,可以看出 iastore指令的操作过程,将a[0]=1 取数组的长度: arraylength 方法调用指令和返回指令: invokevirtual 用于调用对象的实例方法 invokeinterface 用于调用接口方法,他会在运行时搜索一个实现了该接口方法的对象,并调用该方法 invokespecia用于调用 实例初始化方法,私有方法和父类方法 invokestatic 调用类方法 返回指令: ireturn(当返回值是boolean,byte,char,short和int型),lreturn,freturn,dreturn,areturn
扩展操作:
(7)三种循环(while,for,do..while)的调用指令
(8)switch语句,及break,continue的操作指令
java虚拟机的tablewitch和lookupswitch指令用于支持switch条件,当switch语句中的case分支的条件值比较稀疏时,使用lookupswitch代替tablewitch
(9)异常的操作指令
athrow 指令
学习指令集能解决常用问题:
(1) String a="123"; String b="1"+"23"; String c="1"+new String("23"); 比较a是否与b,c相同,这是通过javap查看 常量数据的存储,以及 +号运算原理,对字符串的理解
(2)a=1; a=a++; a=a++; a=a++; 运算完a的值是多少?只能通过javap反编译查看内部运行原理
(3)java定义枚举类型,javap查看编译器给我们生成的代码
(4)java实现装箱拆箱的原理
以上种种都需要我们会看JVM指令集,才能去体会java内部运行结构,从本质上去理解代码,有助于我们加深对java的理性认识!
相关文章推荐
- Java 6 JVM参数选项大全(中文版)
- 深入解析JVM对dll文件和对类的装载过程
- JVM Tomcat性能实战(推荐)
- Java虚拟机JVM性能优化(二):编译器
- Java程序员必须知道的5个JVM命令行标志
- 学习JVM之java内存区域与异常
- 浅谈jvm中的垃圾回收策略
- Java虚拟机JVM性能优化(三):垃圾收集详解
- 简单谈谈JVM、JRE和JDK的区别与联系
- 解析Java虚拟机中类的初始化及加载器的父委托机制
- windows命令行中java和javac、javap使用详解(java编译命令)
- JAVA中JVM的重排序详细介绍
- 每天学Java!一分钟了解JRE与JDK
- 浅谈Java的虚拟机结构以及虚拟机内存的优化
- JVM角度调试优化MyEclipse
- Java虚拟机JVM性能优化(一):JVM知识总结
- Android Studio 报错failed to create jvm error code -4的解决方法
- 解析Linux系统中JVM内存2GB上限的详解
- 了解Java虚拟机JVM的基本结构及JVM的内存溢出方式
- Java堆空间占满的gc日志实例