关于class:解析Class文件示例

43次阅读

共计 1770 个字符,预计需要花费 5 分钟才能阅读完成。

筹备

class 文件是 Java 虚拟机惟一能够辨认的文件,依据 Class 文件咱们能够实现一个程序的运行,本节文章是自己解析一个根本 Class 文件的全过程,记录在此,心愿能提供给正在后退路上的同学作为辅助作用,上面是咱们要解析 Class 文件必要条件。

代码

以下是一个简略的 Java 类,一个公有变量,一个公开办法。

public class TestClass {

    private int a;

    public int increment() {return a + 1;}

}

将这个类编译为 Class 文件

筹备文本编辑器

自己应用 Sublime Text 关上咱们编译后的 Class 文件,次要目标是对照《Java 虚拟机标准》中的 Class 文件的数据结构, 上面是 Sublime Text 下载的网址。

Sublime Text

应用 Sumlime 关上 Clas 文件

《Java 虚拟机标准》

咱们须要依照 Java 虚拟机标准中的数据结构,进行 Class 文件的十六进制码进行解析,所以这里须要依照官网,进行解析,以下是 PDF 在线链接,本节应用 Java8 版本。
Java 虚拟机标准 1.8

关上《Java 虚拟机标准》

解析

咱们须要晓得一个 Class 文件由哪些数据结构组成,并排列进去,一项数据占几个字节,这些咱们都要晓得。
咱们首先须要记录,这个 Class 文件的大体构造,Class 文件的数据结构及程序都是须要严格依照《Java 虚拟机标准》生成的,找到《Java 虚拟机标准》中的 “The Class File Format (Class 文件格式)” 中的 Class 构造项。

须要解释的是,这个 ClassFile 数据结构中的 U2、u4 别离代表两个字节、四个字节,其对应的左边的英文项,代表着其数据的常量项,Class 文件是肯定依照这个构造进行构件的,《Java 虚拟机标准》中也阐明了每一项的形容,自己联合官网整顿如下:

这个是自己整顿的 Class 文件的数据结构,有且只有这 16 项,具体的每一项,本文稍后都有解释。其实 Class 文件并不简单,只是 Class 中的援用比拟多,例如 constant_pool_info 中,这是一个常量池,池中记录着类、办法、字面量等描述符,是互相援用的形式。

javap 查看 class 文件具体构造

应用 javap 查看文件构造,次要是为了供咱们于 Class 二进制形式进行比对时的一个参照物,以阐明咱们解读 class 文件时得出的论断是正确的。其余咱们须要确定咱们常量池中的程序以及所对应的常量池名。

javap -v TestClass.class

输入后果

依据 javap 所输入的数据结构,咱们失去了大抵的数据结构,剩下的咱们须要自行解析,并比对 class 中的十六进制数进行填写。这里采纳 yaml 文本格式进行填充,yaml 格局能很直观的展现出一个对象的数据结构,并且采纳这种形式也能够很间接的将解析的值带入。针对咱们要解析的 class 文件,其中____是咱们要填充的数据,并且也进行了简略的正文阐明字段的含意及所占用的字节。构造如下:

class:
  #魔数 u4
  magic-number: ____
  #小版本号 u2
  minor-version: ____
  #大版本号 u2
  major-version: ____
  #常量池
  constant-pool:
    #常量池总数 u2
    count: ____
    #常量池(数组)constants: ____
  #拜访标记 u2
  access_flags: ____
  #以后类 u2
  this_class: ____
  #父类 u2
  super_class: ____
  #接口
  interface:
    # u2
    count: ____
    interfaces:
  #字段
  field:
    # u2
    count: ____
    fields: ____
  #办法
  method:
    # u2
    count: ____
    methods: ____
  #属性
  attributes:
    #u2
    count: ____
    attributes: ____

有了大抵的构造,咱们就能够开始解析之路啦!!

魔数

魔数项提供标识类文件格式的魔术数; 它的值为 0xCAFEBABE,这个值是固定的,每个文件都有属于本人的魔数,但在 class 文件中,CAFEBABE 就是 class 文件的魔数,它占用 4 个字节。

随后将 CAFEBABE 填入咱们的 yaml 文件中:

小版本号

小版本号占用 2 个字节,因而,将 class 文件中的 0000 转换为十进制为 0,所以小版本号为 0;

大版本号

。。。

正文完
 0