深入理解JVM(六)——类文件结构——code
来源:互联网 发布:windows longhorn开机 编辑:程序博客网 时间:2024/05/22 14:45
Code
Java程序中方法体中的代码经过Javac编译器处理之后,最终变成字节码指令存储在Code属性内。
Code属性出现在方法表的属性集合之中,但不是所有的方法表都必须有,譬如接口或者抽象类。
Code是Class文件中最重要的一个属性,如果把一个Java程序中的信息分为代码(Code,方法体里面的Java代码)和元数据(MetaData,包括类,字段,方法定义以及其它信息)两部分
Java虚拟机执行字节码是基于栈的体系结构
Javac编译器编译的时候会把this关键字的访问转变成一个普通方法参数的访问,只是虚拟机调用实例方法时自动传入参数而已。因此局部变量表至少会有一个指向当前对象实例的局部变量。
异常表实际上是Java代码的一部分,编译器使用异常表而不是简单的跳转命令(jsr,ret已经不用了)来实现java异常及finally处理机制。
异常处理表:有4个字段,因为较好理解所以不画表格了start_pc,end_pc,catch_pc,handler_pc
如果代码在第start_pc行到第end_pc行之间(不包括end_pc),出现了类型为catch_type或者其子类的异常(catch_type指向一个constant_class_info型常量的索引),则转到第handler_pc行继续处理。当catch_type的值为0时,代表任意异常情况都需要转向handler_pc处进行处理。
字节码指令介绍
Java虚拟机的指令由一个字节长度的,代表着某种特定操作含义的数字(操作码)以及跟随其后的零至多个代表此操作所需参数(操作数)而构成。
由于Java虚拟机采用面向操作数栈而非寄存器的架构,所以大多数的指令都不包括操作数,而只有一个操作码。
Java虚拟机的指令集中,大多数的指令都包含了其操作对应的数据类型信息。如iload指令用于从局部变量表中加载int型的数据到操作数栈中,fload则是加载float型的数据。
i代表int类型
l代表long
s代表short
b代表byte
c代表char
f代表float
d代表double
a代表reference
但是之前说过指令集的数量只有一个字节,编译器会在编译期或者运行期将byte和short类型的数据带符号扩展为相应的int类型数据,将boolean和char类型零位扩展为相应的int型数据类型。
加载和存储指令
将一个局部变量加载到操作栈:
iload,iload_< n>,
lload,lload_< n>,
fload,fload_< n>,
dload,dload_< n>,
aload,aload_< n>
将一个数值从操作数栈存储到局部变量表
istore,istore_< n>,
lstore,lstore_< n>,
fstore,fstore_< n>,
dstore.dstore_< n>,
astore,astore_< n>
将一个常量加载到操作数栈
bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_m1,
iconst_< i>,lconst_< i>,fconst_< l>,dconst_< d>
扩充局部变量表的访问索引的指令:wide
运算符指令
加法指令:iadd,ladd,fadd,dadd
减法指令:isub,lsub,fsub,dsub
乘法指令:imul,lmul,fmul,dmul
除法指令:idiv,ldiv,fdiv,ddiv
求余指令:irem,lrem,frem,drem
取反指令:ineg,leng,fneg,dneg
位移指令:ishl,ishr,iushr,lshl,lshr,lushr
按位或指令:ior,lor
按位与指令:iand,land
按位异或指令:ixor,lxor
局部变量自增指令:iinc
比较指令:dcmpg,dcmpl,fcmpg,fcmpl,lcmp
类型转化指令
虚拟机在处理窄化类型转换时,必须显示地使用转化指令
i2b,i2c,i2s,l2i,f2i,f2l,d2i,d2l,d2f
对象创建与访问指令
创建类实例的指令 new
创建数组的指令 newarray anewarray multitianewarray
访问类字段(static字段,或称为类变量),实例字段的指令:
getfield putfield getstatic putstatic
把一个数组元素加载到操作数栈的指令:baload caload saload iaload laload faload daload aalaod
将一个操作数栈的值存储到数值元素的指令:bastore castore sastore iastore lastore fastore dastore aastore
取数组的长度的指令:arraylength
检查类实例类型的指令 instanceof checkcast
操作数栈转移指令
出栈一个或两个元素 pop pop2
复制栈顶一个或两个元素并将复制值重新压入栈dup dup2 dup_x1 dup2_x1 dup_x2 dup2_x2
栈顶元素互换 swap
控制转移指令
修改寄存器的值的指令
条件分支 ifeq iflt ifle ifne ifgt ifge ifnull ifnonnull …
复合条件分支 tableswitch lookupswitch
无条件分支 goto goto_w jsr jsr_w ret
方法调用和放回指令
invokevirtual 指令调用对象的实例方法
invokeinterface 调用接口的方法
invokespecial 调用一些特殊处理的实例方法(初始化,私有方法,父方法)
invokestatic 调用类方法(static)
invokedynamic 用于运行时动态解析出调用点限定符所引用的方法,并执行该方法
异常处理指令
现在Java虚拟机中用异常处理表来完成
同步指令
monitorenter
monitorexit
通常用来支持Java语言中的synchronized关键字的语义
- 深入理解JVM(六)——类文件结构——code
- 深入理解JVM(六)——类文件结构
- 深入理解JVM六-类文件结构
- 深入理解JVM(七)——Class文件结构
- 深入理解JVM(七)——Class文件结构
- 深入理解JVM(七)——Class文件结构
- 深入理解JVM(七)——Class文件结构
- 深入理解JVM(1)—Java虚拟机基本结构
- 【深入理解JVM】:Class类文件结构
- 深入理解JVM--class类文件结构
- 深入理解JVM总结-类文件结构
- 《深入理解Java虚拟机——JVM高级特性与最佳实践》学习笔记——Java类文件结构
- 深入理解JVM(六)——JVM性能调优实战
- 深入理解JVM(六)——JVM性能调优实战
- 深入理解JVM(六)——JVM性能调优实战
- 深入理解JVM(六)——JVM性能调优实战
- 深入理解JVM—JVM内存模型
- 深入理解JVM—JVM内存模型
- APK瘦身——更全面的方案
- Monto Carlo估计动作价值(action values)
- 启动minicom时出现错误"Device /dev/ttyS0 is locked minicom"的解决办法
- 前端学习(六)回调,异步,非阻塞,事件驱动等知识
- vuex学习之路之出现的错误一
- 深入理解JVM(六)——类文件结构——code
- [模板]二维凸包(纯代码)
- 树的后序遍历方式源码
- (9)Javasript入门二
- 123
- php常见面试题
- sublime个人配置
- 方法的重载
- Android InputMethodManager 导致的内存泄露及解决方案