0、给出几个概念:
全类名: 包名+类名(例如:com.liyue.KeQin)。
全限定名:全类名的"."换成"/"(例如:com/liyue/KeQin)。
简单名称:就是字段名或者方法名(例如:"int a = 1;"中的"a","void goHome(){}"中的"goHome")。
描述符:基本数据类型用一个大写字母表示,对象类型用"L"+对象的全限定名+";"表示,";"是在紧密排列时用于区分不同描述符的,数组类型每一维度将使用一个前置的"["描述。对应如下图所示。
字段的描述符:数据类型即可。(例如:"int a = 1;" -> "I")
数组类型的描述符:几维数组就前置几个"[" + 数据类型。(例如:"int[][] as;" -> "[[I")
引用类型的描述符:"L" + 全限定名+";"(例如:"Object obj;" -> "Ljava/lang/Object;")
方法的描述符:参数列表(数量、类型、顺序) + 返回值类型
(例如:"void goHome(int a, int b,int c)" -> "(III)V")
1、存储单位、存储顺序、数据类型
class文件是一组以8字节为单位的二进制流,按照顺序紧密排列。如果某个需要存储的内容超过8字节,则将其分割为若干个8字节进行存储。
存储顺序是大端存储(即8字节中的高位字节,存储在地址的最低位,按排列顺序依次占领地址。)
数据类型,主要是两种:无符号数和表。
无符号数:基本的数据类型,可以用来描述数字、索引引用、数量值或按照UTF-8编码构成字符串值。表现形式为u1(1字节)、u2(2字节)、u4(4字节)、u8(8字节)。
表:由多个无符号数或其他表作为数据项构成的复核数据类型。命名以"_info"结尾。整个class文件本质上也可以视作一张表。如下图所示。
2、魔数与class文件版本
class文件的头4个字节就是魔数(magic number),用来作为class文件的唯一标识(即jvm加载文件进行身份验证时,扫到正确的魔数,才会认为这是个class文件),值为0xCAFFBABE(十六进制数,两位表示一个字节)。
紧跟着的4个字节是版本号,第5、6字节是次版本号(minor version),第7、8字节是主版本号(major version)。java的版本号是从45开始的,每次大版本更新主版本就加1,并且每一个新版本只能兼容老版本,jvm规范规定拒绝执行超过其版本号的class文件。例如jdk1.1支持的版本(45.0~45.65535),jdk1.8(Java8)支持的版本(45.0~52.65535)。
3、常量池
常量池主要存放字面量(literal)和符号引用(symbolic references)。
字面量:文本字符串、被声明为final的常量值等。
符号引用(自己定义的标识符):被模块导出或者开放的包(package)、类和接口的全限定名(fully qualified name)、字段名称和描述符(descriptor)、方法名称和描述符、方法句柄(method Handle)和描述符、动态调用点()和动态常量。
通俗的说,符号引用大部分都是你自己定义的各种东西的名称。(例如:"int a = 2;" 这句中"a"就叫做符号引用, "void printMyName(){}" 中,"printMyName"就是符号引用。)
4、访问标志
紧跟着常量池的2个字节代表访问标志(access_flags),16位二进制数的每一位代表一个访问标志,"1"是有,"0"就是没有。如下图所示。
5、类索引、父类索引、接口索引集合
接着就是2字节的类索引(this_class),2字节父类索引(super_class),他们都指向常量池中的某个符号引用。然后就是接口索引集合,同理集合中每个接口索引都是2字节,并且指向常量池中的某个符号引用。
6、字段表集合
字段表集合记录类中所有的类变量和实例变量信息(不包含局部变量),包括字段的访问修饰符、是不是类变量、可不可变、并发是否可见、是否可被序列化、数据类型、字段名称。
字段表集合中不会列出父类或者从父接口中继承而来的字段。
在内部类的字段表集合中,还包含一个指向外部类实例的字段。
7、方法表集合
方法表集合记录类中所有的方法信息,与字段表集合类似,如果该类没有重写父类的方法,父类的方法就不会出现在方法表中。
方法的主体主要保存在code这个属性中。
8、属性表集合
作为其他表的补充,常常出现在各个表项之后,例如code属性、ConstantValue属性、RunTimeVisibleAnnotations属性等。
本文是作者阅读《深入理解java虚拟机》一书所做的总结,如有问题,请多多包涵!(若涉及侵权请联系我删除哦!)
最后,劳逸结合是不错,但休息太多的话,事情可就做不完咯!