欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

实例分析Class字节码文件(一)

程序员文章站 2024-03-16 23:28:10
...

一、小试牛刀

要分析的代码如下:

package com.demo6;

    public class TestClass {

        private int m;

        public int inc(){
            return m + 1;
        }
    }

Class字节码文件部分转化为16进制如下:

实例分析Class字节码文件(一)

根据Class文件格式表:

实例分析Class字节码文件(一)

转换几个:

编码(16进制) 说明
ca fe ba be 魔数
00 00 次版本号
00 33 主版本号 : JDK 1.7
00 16 常量池容量 :22-1 = 21
07 tag :CONSTANT_Class_info
00 02 name_index :指向常量池中的第二个常量 [name_index:必须指向的是一个CONSTANT_Utf8_info]
01 tag : CONSTANT_Utf8_info
00 13 length : 表示字符串长度是多少个字节(13)
63 6f 6d 2f 64 65 6d 6f 36 2f 54 65 73 bytes : com/demo6/TestClass


我们转换了两个常量,剩余19个使用JDK自带工具进行转化:

实例分析Class字节码文件(一)

从上面的清单中,我们能看到常量池具有21个常量,从1开始计数。

第一个常量类型为CONSTANT_Class_info,并且指向第二个常量;
第二个常量类型为CONSTANT_Utf8_info,具体指com/demo6/TestClass;

与我们分析的一致。

二、访问标志

在常量池结束后,紧接着的两个字节代表访问标志(access_flags),这个标志用于识别一些类获接口层次的访问信息,包括:

① 这个Class是类还是接口
② 是否定义为public类型
③ 是否定义为abstract类型
④ 是否被声明为final等

access_flags一共有16位可以使用,当前只使用了8个,没有使用到的位一律为0.

具体标识如下:

实例分析Class字节码文件(一)

以上面的代码为例:

实例分析Class字节码文件(一)

是否为public类型 0x0001
用了JDK1.2之后的编译器进行编译 0x0020
其他 ×


0x0001 | 0x0020 = 0x0021

三、类索引、父类索引和接口索引集合

紧接着访问标志后的就是类索引、父类索引和接口索引集合

类型 名称 说明
u2 类索引 类全限定名
u2 父类索引 父类全限定名
多个u2 接口索引集合 实现的所有接口的全限定名


类索引和父类索引引用两个u2类型的索引值表示,他们各自指向一个类型为CONSTANT_Class_info的类描述符常量,通过CONSTANT_Class_info找到CONSTANT_Utf8_info所表示的字符串。

对于接口索引集合,入口的第一项为u2类型的接口计数器(interfaces_count),表示实现接口的个数,如果为0,后面接口的索引表不再占用字节。

以上面的代码为例子:

实例分析Class字节码文件(一)

类型 名称
u2 类索引 0x0001
u2 父类索引 0x0003
多个u2 接口索引集合 0x0000


① 类索引指向第一个常量;

② 父类索引指向第三个常量;

③ 接口索引集合为0,不占用任何字节;