文章目录
- 1.无关性的基石
- 2.Class文件的结构
- 2.1 无符号数
- 2.2 表
- 2.3 解读字节码文件
- 2.3.1魔数
- 2.3.2副版本号
- 2.3.3主版本号
- 2.3.4常量池计算器
- 2.3.5常量池项目类型
- 解析常量池第一项(CONSTANT_Methodref_info)
- 解析常量池第二项(CONSTANT_Fieldref_info)
- 解析常量池第三第四项( CONSTANT_Class_info)
- 解析常量池中的第5项(CONSTANT_utf8_info)
- 常量池剩余内容解析
- 解析工具
1.无关性的基石
各种不同平台的虚拟机都使用同一的程序存储格式-字节码(ByteCode),这是构成平台无关性的基石,目前已经有很多能够运行在java虚拟机上的语言,如Groovy、Scala、JRuby、Jython等,实现语言无关性的基础仍然是虚拟机和字节码存储格式。
2.Class文件的结构
class文件中各数据项严格按照顺序紧凑的排列在class文件中,没有空隙存在,各项的排列顺序如图。
*表1*
*记忆口诀:模板常常问类父,计数集合顺序数,接口字段方法加,简简单单记住啦*
这种数据结构只有两种类型:无符号数和表
2.1 无符号数
无符号数是属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量或者按照UTF-8编码构成字符串值。
2.2 表
表是由多个无符号数或者其他表作为数据项构成的复合数据类型。表用于描述有层次关系的复合数据类型。
2.3 解读字节码文件
我们以下边这个类为范例讲解下类的字节码解析过程
public class Simple {
int a=1;
int add(int b){
return a+b;
}
}
使用javac编译完成用notepad++打开,选择HEX插件中的第一项
2.3.1魔数
表中第一项为4字节长度的魔数,魔数它的作用类似与文件的拓展名,但是拓展名可以更改,魔术不可以随意改动,可以用来表示是否为java的字节码文件。
java文件的魔术为cafebabe
2.3.2副版本号
接下来是一个两位的副版本号,本例的副版本号为0
2.3.3主版本号
接着是两位的主版本号
本例中的主办版号16进制为34,十进制为52,即jdk1.8,具体对应关系如下
2.3.4常量池计算器
常量池的长度是不固定的,因此常量池前有个两位长度的u2类型的数据来记录常量池的长度,本例中的16进制值是13,换算成10进制为19,说明有18项常量,常量计数器是从1开始的
2.3.5常量池项目类型
常量池中主要存放两种类型常量:字面常量和符号引用
字面常量:
接近于Java语言层面的常量,如文本字符串、声明为final的常量值等。
符号引用:
符号引用偏向与编译原理方面的概念,包含如下三类常量
■类和接口的全限定名
■字段名称和描述符
■方法名称和描述符
常量池每个项目都是一个表,有14中不同的项,具体如图
*表2*
这里的每一项都有自己的数据结构,具体参考下图
*表3*
这14种表有个共有的特点就是,表中的第一项为一个长度为u1的标志为来表示它属于那种类型,也就是对应表种的标志(顺序码)
ps:不用记住这里的项,只要会找就行,下边会列出具体步骤
解析常量池第一项(CONSTANT_Methodref_info)
上边说过常量池中每个表的第一项都是一个u1的标志位来表示此项的类型,本例中第一项的标志位值是0a,十进制位10,查表3找出顺序码位10的项(CONSTANT_Methodref_inf),CONSTANT_Methodref_inf中的第一项是标志位,也就是刚看的0a
接下来看CONSTANT_Methodref_info表中的第二项,是一个u2的项,其值位04,表示指向常量池第四项索引(看描述列推断第4项类型为CONSTANT_Class_info)
接下来看CONSTANT_Methodref_info表中的第三项,此项16进制为0f,十进制为15,表示执行常量池中第15项索引(看描述列推断第15项类型为12 CONSTANT_NameAndType_info)
至此为止常量池中的第一项解析完毕;
解析常量池第二项(CONSTANT_Fieldref_info)
有了第一项的解析经验,解析第二项就简单多了,常量池中的第二项,u1的标志位值为09,查表找出顺序码为09的项,也就是CONSTANT_Fieldref_info类型的项
CONSTANT_Fieldref_info的第二项表示指向常量池中第3项索引(看描述列推断第三项类型为7 CONSTANT_Class_info);CONSTANT_Fieldref_info的第三项表示指向常量池中第15项(16进制位10)索引(看描述列推断第15项类型为12 CONSTANT_NameAndType_info);
关联过程如下图
解析常量池第三第四项( CONSTANT_Class_info)
常量池中的第三项u1的标志位值为07,查表找出顺序码为07的项,类型为CONSTANT_Class_info(与上方第二项分析中的括号部分一致),CONSTANT_Class_info第二项是长度为u2的指向常量项的索引;分析发现第四项也是07(与上方第一项括号中分析的一致),具体分析过程如下图
经上图分析得出,常量池中第11和第12项类型为1 CONSTANT_utf8_info
解析常量池中的第5项(CONSTANT_utf8_info)
通过上边已经分析完常量池中的前四项,接下来分析第五项,第五项的标志位为01,查表找出顺序码为01的项,类型为CONSTANT_utf8_info;还是老规矩第一位为标志位,第二位为一个u2长度的项,表示后边跟随的字符的长度,本例中表示后边一位为字符的内容。
常量池剩余内容解析
上边说了常量池中前五项内容的解析,涉及四种类型,其他类型解析方法与上述一致,自己参考表3即可解析,由于项比较多就不一一解读,下边给出整个常量池的解析内容,其中绿色代表一行没放下的项,有折行;紫色代表一行可以放下的项。
解析工具
使用javap -verbose Simple.class可以帮助解析出来,如下图
每天5分钟,您看着不累!剩余部分解析内容下节分享!