Java 类文件结构是一个二进制字节流,由 Java 虚拟机解释。
编译后的class文件用编辑器16进制打开,类似下图的样子,1个16进制是4位,2个16进制是1个字节。
前几位一般都一样,CA FE BA BE,为魔术值 Magic Number,占四个字节。
第二部分为版本号,Minor Version 两个字节,Major Version 两个字节,例子里的34换成10进制为52,表示JDK8。
第三部分为常量池中个数, constant_pool_count,008D(141),两个字节,存储(141-1)个数据;紧接着个数,就是具体的常量池中存储的内容,占用字节个数完全由常量个数和每个常量代表的类型决定。
access_flag,当前类 class 的访问修饰符,例如 public 或者 private,两个字节。
this_class,当前这个类是什么,存在常量池中。
super_class,父类是什么,存在常量池中。
interface_count,实现的接口的个数。
interfaces,具体的实现接口。
fields_count,属性个数。
fields,具体的属性。
method_count,方法个数。
method_info,方法。
attribute_count,附加属性个数。
attribute,附加属性。
可以使用javap -v classfile_full_path java自带命令查看,或者安装 IDEA插件,JClassLib 来分析 class文件内容,使用后者查看更清晰,效果是这样的:
General Information 给出了概要信息,存储各项内容的数量,展开各个节点,左侧各节点里面的存储内容和右侧给的数量是一致的。
用这个结合之前的编辑器16进制查看字节码,更容易读懂字节码。
1、常量池阅读方法,字节码中008D,表示常量池中存储140个数据,对比IDEA中显示的内容:
省略部分常量池内容,一直拖到最后,
看常量池中第一个内容,
class name 占位常量池中28号,name and type占位74号,对比字节码中内容:
0A(10)为标志位,001C(28);004A(74)
继续往后看字节码,依旧是0A,对应Constan Pool中的第二项:
[002] CONSTANT_Mehotdref_info。
读懂常量池的关键点在于标志位对应的存储数据类型和长度,这个可以从jvms- java 虚拟机规范中找到说明,如下图,标志位1个字节,左边一列表示类型,右列为对应的10进制数值。
2、methods 的阅读方法
method_info 结构格式如下,方法修饰符,名字索引,描述符索引,附加属性:
对比 JclassLib 解释:
附加属性,最重要的一项是Code,代码实现,右侧的Bytecode为代码编译后的字节码指令组成,如下图,可以参考指令说明进一步理解。
参考指令说明,找到字节码对应位置:
还有好多内容,后面有时间再记录。