文章目录

  • 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等,实现语言无关性的基础仍然是虚拟机和字节码存储格式。

java 查看文件生成时间怎么看_常量池

2.Class文件的结构

  class文件中各数据项严格按照顺序紧凑的排列在class文件中,没有空隙存在,各项的排列顺序如图。

java 查看文件生成时间怎么看_常量池_02


*表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插件中的第一项

java 查看文件生成时间怎么看_java 查看文件生成时间怎么看_03

2.3.1魔数

  表中第一项为4字节长度的魔数,魔数它的作用类似与文件的拓展名,但是拓展名可以更改,魔术不可以随意改动,可以用来表示是否为java的字节码文件。

java 查看文件生成时间怎么看_版本号_04


java文件的魔术为cafebabe

2.3.2副版本号

  接下来是一个两位的副版本号,本例的副版本号为0

java 查看文件生成时间怎么看_无符号数_05

2.3.3主版本号

  接着是两位的主版本号

java 查看文件生成时间怎么看_常量池_06

本例中的主办版号16进制为34,十进制为52,即jdk1.8,具体对应关系如下

java 查看文件生成时间怎么看_java 查看文件生成时间怎么看_07

2.3.4常量池计算器

  常量池的长度是不固定的,因此常量池前有个两位长度的u2类型的数据来记录常量池的长度,本例中的16进制值是13,换算成10进制为19,说明有18项常量,常量计数器是从1开始的

java 查看文件生成时间怎么看_java 查看文件生成时间怎么看_08

2.3.5常量池项目类型

  常量池中主要存放两种类型常量:字面常量和符号引用

字面常量:
  接近于Java语言层面的常量,如文本字符串、声明为final的常量值等。
符号引用:
  符号引用偏向与编译原理方面的概念,包含如下三类常量
    ■类和接口的全限定名
    ■字段名称和描述符
    ■方法名称和描述符
  常量池每个项目都是一个表,有14中不同的项,具体如图

java 查看文件生成时间怎么看_常量池_09

*表2*



这里的每一项都有自己的数据结构,具体参考下图

java 查看文件生成时间怎么看_无符号数_10

*表3*


  这14种表有个共有的特点就是,表中的第一项为一个长度为u1的标志为来表示它属于那种类型,也就是对应表种的标志(顺序码)
ps:不用记住这里的项,只要会找就行,下边会列出具体步骤

解析常量池第一项(CONSTANT_Methodref_info)

  上边说过常量池中每个表的第一项都是一个u1的标志位来表示此项的类型,本例中第一项的标志位值是0a,十进制位10,查表3找出顺序码位10的项(CONSTANT_Methodref_inf),CONSTANT_Methodref_inf中的第一项是标志位,也就是刚看的0a

java 查看文件生成时间怎么看_无符号数_11

  接下来看CONSTANT_Methodref_info表中的第二项,是一个u2的项,其值位04,表示指向常量池第四项索引(看描述列推断第4项类型为CONSTANT_Class_info)

java 查看文件生成时间怎么看_无符号数_12

  接下来看CONSTANT_Methodref_info表中的第三项,此项16进制为0f,十进制为15,表示执行常量池中第15项索引(看描述列推断第15项类型为12 CONSTANT_NameAndType_info)

java 查看文件生成时间怎么看_无符号数_13

至此为止常量池中的第一项解析完毕;

解析常量池第二项(CONSTANT_Fieldref_info)

  有了第一项的解析经验,解析第二项就简单多了,常量池中的第二项,u1的标志位值为09,查表找出顺序码为09的项,也就是CONSTANT_Fieldref_info类型的项

java 查看文件生成时间怎么看_无符号数_14

CONSTANT_Fieldref_info的第二项表示指向常量池中第3项索引(看描述列推断第三项类型为7 CONSTANT_Class_info);CONSTANT_Fieldref_info的第三项表示指向常量池中第15项(16进制位10)索引(看描述列推断第15项类型为12 CONSTANT_NameAndType_info);

关联过程如下图

java 查看文件生成时间怎么看_无符号数_15



解析常量池第三第四项( CONSTANT_Class_info)

  常量池中的第三项u1的标志位值为07,查表找出顺序码为07的项,类型为CONSTANT_Class_info(与上方第二项分析中的括号部分一致),CONSTANT_Class_info第二项是长度为u2的指向常量项的索引;分析发现第四项也是07(与上方第一项括号中分析的一致),具体分析过程如下图

java 查看文件生成时间怎么看_java 查看文件生成时间怎么看_16

经上图分析得出,常量池中第11和第12项类型为1 CONSTANT_utf8_info

解析常量池中的第5项(CONSTANT_utf8_info)

  通过上边已经分析完常量池中的前四项,接下来分析第五项,第五项的标志位为01,查表找出顺序码为01的项,类型为CONSTANT_utf8_info;还是老规矩第一位为标志位,第二位为一个u2长度的项,表示后边跟随的字符的长度,本例中表示后边一位为字符的内容。

java 查看文件生成时间怎么看_无符号数_17

常量池剩余内容解析

  上边说了常量池中前五项内容的解析,涉及四种类型,其他类型解析方法与上述一致,自己参考表3即可解析,由于项比较多就不一一解读,下边给出整个常量池的解析内容,其中绿色代表一行没放下的项,有折行;紫色代表一行可以放下的项。

java 查看文件生成时间怎么看_无符号数_18

解析工具

  使用javap -verbose Simple.class可以帮助解析出来,如下图

java 查看文件生成时间怎么看_常量池_19

每天5分钟,您看着不累!剩余部分解析内容下节分享!