实例分析Class字节码文件(一)
一、小试牛刀
要分析的代码如下:
package com.demo6;
public class TestClass {
private int m;
public int inc(){
return m + 1;
}
}
Class字节码文件部分转化为16进制如下:
根据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自带工具进行转化:
从上面的清单中,我们能看到常量池具有21个常量,从1开始计数。
第一个常量类型为CONSTANT_Class_info
,并且指向第二个常量;
第二个常量类型为CONSTANT_Utf8_info
,具体指com/demo6/TestClass
;
与我们分析的一致。
二、访问标志
在常量池结束后,紧接着的两个字节代表访问标志(access_flags),这个标志用于识别一些类获接口层次的访问信息,包括:
① 这个Class是类还是接口
② 是否定义为public类型
③ 是否定义为abstract类型
④ 是否被声明为final等
access_flags一共有16位可以使用,当前只使用了8个,没有使用到的位一律为0.
具体标识如下:
以上面的代码为例:
是否为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,后面接口的索引表不再占用字节。
以上面的代码为例子:
类型 | 名称 | 值 |
---|---|---|
u2 | 类索引 | 0x0001 |
u2 | 父类索引 | 0x0003 |
多个u2 | 接口索引集合 | 0x0000 |
① 类索引指向第一个常量;
② 父类索引指向第三个常量;
③ 接口索引集合为0,不占用任何字节;
上一篇: windows10系统mysql5.17.28绿色安装教程
下一篇: Nacos 集群搭建