第六章 类文件结构

本文详细介绍了Java字节码的基本结构,包括魔数、版本号、常量池等组成部分,并解释了字面量与符号引用的概念。此外还概述了字节码指令的分类及其在虚拟机中的执行方式。

无关性的基石就是Class字节码文件


0~3是魔数:咖啡宝贝? 用来身份识别的;
4~7:是JDK版本号
8~9:是常量池个数

常量
常量分为两大类:字面量和符号引用,字面量就是如文本字符串,final声明的常量等.
    符号引用包括三种:
        类和接口的全限定名(例如:com/lc/test/TestDemo就是全限定名,将.换成了/,结束会加一个";"标识)
        字段的名称和描述符
        方法的名称和描述符
常量池中的每一项常量都是一个表,共有14中表.
常量前的三个点,例如:d表示u1标志位声明类型,ef表示length字节长度
因为Class文件中方法,字段等都需要引用CONSTANT_Uft8_info型常量来描述,所以其长度就是字段方法能定义的长度64k(65535)
使用命令[javap -verbose 类名]就可以打印出此类的常量
访问标志
常量结束之后紧接的两个字节代表访问标志,对应访问标志的表.

类索引,父类索引,接口索引
紧接后面的字节分别是类索引,父类索引,接口索引

对应常量表的常量

字段表集合
字段表用于描述接口或者类中声明的变量,字段包括类级变量和实例级变量
方法表集合
属性表集合
字节码指令简介
    java虚拟机的指令由一个字节长度的 , 代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作数所需的参数(称为操作数 , Operands)而构成.
由于java虚拟机采用面向操作数栈而不是寄存器的架构,所以大多数指定都不包含操作数,只有一个操作码.(一个非负字节0~255)
    因为范围的限制,java虚拟机的大部分的指令都没有支持byte , short 和char甚至没有任何指令支持boolean.操作时会转化成相应的int类型然后操作.
对于指令,可以根据用途大致分为9类
    加载和存储指令
        将局部变量加载到操作栈:iload,iload_<n>……
        将一个数值从操作数栈存储到局部变量表:istore、istore_<n>……
        将一个常量加载到操作数栈:bipush、sipush、ldc、ldc_w、iconst……
        扩充局部变量表的访问索引指令:wide
    运算指令
        加(iadd),减(isub)、乘(imul)、除(idiv)、求余(irem)、取反(ineg)、位移(ishl,ishr)、按位或(ior)、按位与(iand)、按位异或(ixor)、局部变量自增(iinc)、比较(dcmpg,dcmpl)(以及对应的其他数据类型)
        如果某个操作结果没有明确的数学定义的话,会使用NaN值来表示.
    类型转换指令
    对象访问指令
        创建实例 : new
        创建数组的指令 : newarray,anewarray,multiannewarray
        访问类字段和实例字段(非static字段)指令 : getfield,putfield,getstatic,putstatic
        把一个数组元素加载到操作数栈的指令 : baload...
        将一个操作数栈的值存储到数组元素中的指令 : bastore...
        取数组长度指令 : arraylength
        检查类实例类型的指令 : instanceof , checkcast
    操作数栈管理指令
        将操作数栈的栈顶一个或两个元素出栈 : pop , pop2
        复制栈顶一个或两个数值并将复制值或双份复制值重新压入栈顶 : dup ,dup2,dup_x1...
        将栈顶最顶端的两个数值互换 : swap
    控制转移指令(可以有条件或者无条件的从指定位置指令而不是控制转移指令的下一条指令开始执行(模型上看就是可以修改PC寄存器的值))
        条件分支 : ifeq,iflt...
        复合条件分支 : tableswitch,lookupswitch
        无条件分支 : goto , goto_w , jsr , jsr_w , ret
         各种类型的比较最终都会转化为int类型的比较操作,因此java虚拟机提供的int类型的条件分支指令是最为丰富和强大的.
    方法调用和返回指令
        invokevirtual调用实例方法
        invokestatic调用类方法(static方法)
        ireturn返回包括boolean,byte等类型时使用
        ...
    异常处理指令
        显式抛出异常由athrow指令来实现
    同步指令
        java虚拟机可以支持方法级的同步和方法内部一段指令序列的同步 , 这两种同步结构都是使用管程(Monitor)来支持的.
            方法级的同步是隐式的,无须通过字节码指令来控制,虚拟机会根据方法常量池的方法表结构中的ACC_SYNCHRONIZED访问标志(属于标志位)得知是否是同一个方法,
               调用时,调用指令会检查方法的ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,则需要先成功获取管程,然后才能执行方法.
           同步一段指令集序列通常都是synchronized语句块实现,虚拟机通过monitorenter(开始同步)和monitorexit(退出同步)两条指令来支持synchronized关键字.
javap -c -l No1

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值