JVM学习05-字节码执行过程和JVM指令集
来源:互联网 发布:me3630 软件 用户手册 编辑:程序博客网 时间:2024/05/21 20:51
1. 字节码的Code部分
在执行字节码的时候,无非也就是对调用类中的函数。那么下面将介绍下字节码函数的Code部分,Code部分的代码一个可以用java自带的命令javap命令进行查看。还可以在eclipse中安装ByteCode visualizer插件查看,具体使用自行研究。
在我介绍java内存模型的时候,函数的执行过程是分配在栈内存中的,所以在执行Code部分的时候肯定会涉及到局部变量表和操作数栈,同时还会涉及到程序计数器。之前也介绍了一个小例子,下面继续先以一个小例子讲述。
2. 例子
源码:
package com.minosa.test;public class HelloClass { public int foo(){ int a = 1; int b = 2; int c = a + b; return c; }}
ByteCode visualizer查看
public int foo() { /* L6 */ 0 iconst_1; 1 istore_1; /* a */ /* L7 */ 2 iconst_2; 3 istore_2; /* b */ /* L8 */ 4 iload_1; /* a */ 5 iload_2; /* b */ 6 iadd; 7 istore_3; /* c */ /* L9 */ 8 iload_3; /* c */ 9 ireturn; /* LineNumberTable */ /* ----------+------------- */ /* start_pc | line_number */ /* ----------+------------- */ /* 0 | 6 */ /* 2 | 7 */ /* 4 | 8 */ /* 8 | 9 */ /* ----------+------------- */ /* LocalVariableTable */ /* -------+----------+--------+------------+------------------ */ /* index | start_pc | length | name_index | descriptor_index */ /* -------+----------+--------+------------+------------------ */ /* 0 | 0 | 10 | 12 | 13 */ /* 1 | 2 | 8 | 16 | 17 */ /* 2 | 4 | 6 | 18 | 17 */ /* 3 | 8 | 2 | 19 | 17 */ /* -------+----------+--------+------------+------------------ */ /* ExceptionTable (empty) */ /* max_stack: 2 max_locals: 4 */ }
上面在字节码的文件结构中讲过,每个方法中存在很多属性,例如LineNumberTable,LocalVariableTable 等等。里面的一些”_index”就是指向常量池中的索引。对于成员方法来说(非类方法),局部变量表中的第一个是this(之前有讲过)。
这里抽出最关键的Code进行讲述:
由上面的LocalVariableTable可以知道,a变量的index是1,b是2,c是3。
public int foo() { /* L6 */ 0 iconst_1; 1 istore_1; /* a */ /* L7 */ 2 iconst_2; 3 istore_2; /* b */ /* L8 */ 4 iload_1; /* a */ 5 iload_2; /* b */ 6 iadd; 7 istore_3; /* c */ /* L9 */ 8 iload_3; /* c */ 9 ireturn;}
1. int a = 1;
首先程序计数器值为0,iconst_1指令将整数1压入操作数栈中;执行istore_1,程序计数器为1,将操作数栈中的数弹出,然后赋值给索引为1的变量(即a)。
2. int b = 2;
跟 int a = 1; 基本一致。
3. int c = a + b;
这里iload指令(i表示int型,后面会列出常用的指令表)将下标为1和2,即a和b压入栈中。然后执行 idd 指令,弹出两个操作数进行相加,并将结果值压入操作数栈中。最后istore_3指令将栈中的操作数弹出并赋值给变量c。
4. return c;
这里先将c的值载入压入到栈中,然后执行ireturn指令。
这里有一个很经典的面试题,就是try中的return和finally中的return,两个return的执行流程。其实看一下反汇编的指令就一目了然了。
3. JVM指令集
具体的指令集可以参照博文:
http://blog.csdn.net/lm2302293/article/details/6713147
里面描述了指令在字节码中对应的Byte,助记符以及功能描述,下面将对常用进行描述下。
3.1 常量入栈
1. aconst_null
null对象入栈,前面的a表示对象ref。
2. iconst_m1
将 -1 压入栈中。其他的byte型和short型参照 bipush 和 sipush 指令
3. iconst_0 ~ iconst_5
将整数 0 ~ 5 压入栈中。其他的byte型和short型参照 bipush 和 sipush 指令
4. lconst_1 ~ lconst_2
将long类型常量 1或2 压入栈中,其他参照 ldc2_w 指令;
5. fconst_1 ~ fconst_2
将float类型常量 1或2 压入栈中,其他参照 ldc 指令。
6. dconst_1 ~ dconst_1
将double类型常量 1或2 压入栈中,其他参照 ldc2_w 指令。
7. bipush 和 sipush
bipush将一个byte的带符号常量压入栈中,sipush将一个short型带符号常量压入栈中
8. ldc,ldc_w和ldc2_w
ldc 将int、float或String型常量值从常量池中压入栈中。
ldc_w将int、float或String型常量值从常量池中压入栈中(宽索引)。
ldc2_w将long或double型常量值从常量池中压入到栈中(宽索引)。
3.2 局部变量操作
1. load(为i,l,f,d和a中一个)
分别将int型,long型,float型,double型以及Object ref型的局部变量压入栈中。指令后面继续跟着”0,_1,_2,_3”表示将索引为0 ~ 3的局部变量压入到栈中,大于3的索引则去掉下划线”“,如”iload_1”,”iload 4”。
2. aload(为c,b,s,i,l,f,d和a中一个)
将指定类型数组中的值压入到栈中。取值的时候先将数组的ref压入栈,然后是需要获取数据的index,然后执行*aload指令,并将获取到的值压入到栈中。这里可能会抛出数组下标越界的异常。
3. *store 和 *astore 指令
这里基本和 *load 和 *aload指令类似。
3.3 通用栈操作
1. nop
什么都不做。
2. pop
从栈顶弹出一个字长。
3. dup
赋值栈顶一个字长,复制内容压入栈中。
3.4 类型转化
i2c、i2b、i2s、i2l,i2f,l2i,l2f,l2d,f2i,f2d,d2i,d2l,d2f。
3.5 整数运算和浮点运算
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,lshl 左移 <<
ishr,lshr,iushr,lushr 有符号和无符号右移 >>和>>>
iand,land 按位与 &
ior,lor 按位或 |
ixor,lxor 按位异或 ^
iinc 指定int型变量增加指定的值
3.6 对象操作指令和方法调用指令
1. new
创建一个对象,并将引用压入栈中。
2. invokespecial 和 invokevirtual
调用构造方法,私有方法
3. invokestatic 和 invokeinterface
调用静态方法和接口方法
4. getstatic 和 putstatic
getstatic 获取指定类的静态域并将值压入栈中;putstatic为指定静态域赋值。
5. getfield 和 putfield
同上,只是针对实例域
6. return (为 i l f d a 或(为空return即void))
3.7 条件控制
ifeq,ifne,if_icmpeq 等等一些指令。详细见指令表。
- JVM学习05-字节码执行过程和JVM指令集
- JVM字节码执行模型及字节码指令集
- jvm字节码指令集
- JVM字节码指令集简介
- [JVM] 字节码指令集简介
- JVM字节码指令集简介
- JVM字节码指令集简介
- [JVM] 字节码指令集简介
- jvm探秘六:字节码指令集
- JVM学习笔记(五):根据字节码指令介绍方法执行流程
- jvm字节码指令理解
- [jvm解析系列][十三]字节码指令小节,从字节码看JVM的栈解释器执行过程。
- JVM字节码执行引擎
- JVM字节码执行引擎
- 【JVM】字节码执行引擎
- JVM字节码执行引擎
- JVM字节指令详解
- JVM学习笔记六 :虚拟机字节码执行引擎
- UNITY 5.3.1 发行说明 中文版
- 04、精灵
- 笔记:《高效能人士的七个习惯》第十一章 再论由内而外造就自己
- Gradle构建Java Web Application
- Mac系统输入英文时如何去掉自动提示
- JVM学习05-字节码执行过程和JVM指令集
- Linux 性能监控 —— 磁盘 I/O
- asfad发阿斯蒂芬
- poj 2398 Toy Storage
- 设计模式-单例模式
- ARM中的RO、RW和ZI DATA说明
- JS字符串操作
- Android Design Support Library--FloatingActionButton简析记录
- 记问题排查:java进程未正常退出