前言
用一段示例代码来解析Class文件。
一、源码
package com.yhcookie.cxt.mytest;
public class Test01_ByteCode {
public Test01_ByteCode(){};
}
二、对应的Class文件(16进制)
- CA FE BA BE 00 00 00 34 00 10 0A 00 03 00 0D 07 00 0E 07 00 0F 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 56 01 00 04 43 6F 64 65 01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 01 00 12 4C 6F 63 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00 04 74 68 69 73 01 00 29 4C 63 6F 6D 2F 79 68 63 6F 6F 6B 69 65 2F 63 78 74 2F 6D 79 74 65 73 74 2F 54 65 73 74 30 31 5F 42 79 74 65 43 6F 64 65 3B 01 00 0A 53 6F 75 72 63 65 46 69 6C 65 01 00 14 54 65 73 74 30 31 5F 42 79 74 65 43 6F 64 65 2E 6A 61 76 61 0C 00 04 00 05 01 00 27 63 6F 6D 2F 79 68 63 6F 6F 6B 69 65 2F 63 78 74 2F 6D 79 74 65 73 74 2F 54 65 73 74 30 31 5F 42 79 74 65 43 6F 64 65 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 00 21 00 02 00 03 00 00 00 00 00 01 00 01 00 04 00 05 00 01 00 06 00 00 00 2F 00 01 00 01 00 00 00 05 2A B7 00 01 B1 00 00 00 02 00 07 00 00 00 06 00 01 00 00 00 04 00 08 00 00 00 0C 00 01 00 00 00 05 00 09 00 0A 00 00 00 01 00 0B 00 00 00 02 00 0C
三、解读该class文件
图为 IDEA的jclasslib解析class文件图。
- CA FE BA BE :magic,标识该class文件为java
- 00 00:minor_version 副版本号 十进制值为0
- 00 34:major_version 主版本号 十进制值为52,表示jdk 1.8
- 00 10:常量池计数器 十进制值为16,表示当前常量池有16-1 个常量
- 0A :表示常量池 第一个常量的类型(文后附常量池所有类型)十进制值为10,表示tag为10的类型,即CONSTANT_Methodref_info,后4个字节为CONSTANT_Methodref_info的两个索引
- 00 03 :表示常量池的索引位置,十进制为3,表示常量池中的3号常量,即
- 00 0D :表示常量池的索引位置,十进制为13,表示常量池中的13号常量,即
至此,第一个常量池中第一个位置的CONSTANT_Methodref_info分析完了,接下来的16进制数表示,第二个位置的,我们继续分析: - 07 :常量池中下一个类型的tag,十进制值为7,即CONSTANT_Class_info
- 00 0E:两个字节的索引,表示指向类的全限定名项的索引,十进制值为14,常量池14号位置存放的如下图所示
1个字节表示常量池2号位置的类的全限定名称的字符串长度n,n个字节表示全限定名称字符串; - 往后依次分析…
附
常量池所有类型(1.8为例)
-
CONSTANT_Utf8_info : 最常用的
tag : 1 – 占用一个字节空间
length : UTF-8 字符串占用的字节数
bytes:长度为length的字符串 -
CONSTANT_Integer_info :
tag : 3 – 占用一个字节空间(下同,不加赘述)
bytes:4个字节,Big-Endian (高位在前)存储的int值 -
CONSTANT_Float_info :
tag : 4
bytes:4个字节,Big-Endian 存储的float值 -
CONSTANT_Long_info :
tag : 5
bytes:8个字节,Big-Endian 存储的long值 -
CONSTANT_Double_info :
tag : 6
bytes:8个字节,Big-Endian 存储的double值 -
CONSTANT_Class_info :
tag : 7
index:2个字节 指向类的全限定名项的索引 -
CONSTANT_String_info :
tag : 8
index:2个字节 指向字符串字面量的索引 -
CONSTANT_Fieldref_info :
tag : 9
index:2个字节 指向声明字段的类或者接口描述符CONSTANT_Class_info的索引项
index: 2个字节 指向字段描述符CONSTANT_NameAndType的索引项 -
CONSTANT_Methodref_info :
tag : 10
index:2个字节 指向声明方法的类或者接口描述符CONSTANT_Class_info的索引项
index: 2个字节 指向字段描述符CONSTANT_NameAndType_info的索引项 -
CONSTANT_InterfaceMethodref_info :
tag : 11
index:2个字节 指向声明方法的类或者接口描述符CONSTANT_Class_info的索引项
index: 2个字节 指向字段描述符CONSTANT_NameAndType_info的索引项 -
CONSTANT_NameAndType_info :
tag : 12
index:2个字节 指向该字段或方法名称常量项的索引
index: 2个字节 指向该子弹或方法描述符常量项的索引 -
CONSTANT_MethodHandle_info :
tag : 15
reference_kind:1个字节 1-9之间的一个值,决定了方法句柄的类型。方法句柄类型的值表示方法句柄的字节码行为
reference_index: 2个字节 对常量池的有效索引 -
CONSTANT_MethodType_info :
tag : 16
descriptor_index:2个字节 指向Utf8_info结构 表示的方法描述符 -
CONSTANT_InvokeDynamic_info :
tag : 18
bootstrap_methed_attr_index:2个字节 当前Class文件中淫荡方法标的bootstrap_methods[]数组的有效索引
name_and_type_index: 2个字节 指向NameAndType_info表示的方法名和方法描述符
随JDK迭代不断增加…