引言
我们知道,java语言之所以能够跨平台运行,一方面是因为jvm帮助我们屏蔽了操作系统之间的差异性,而另一方面则是class文件的独特性。
程序员编写的文件是.java文件,而javac命令能够帮我们将.java文件编译成.class文件,那class文件的结构是怎样的?
class类文件结构
一个class文件总共包含以下15个部分
| 字段名称 | 描述 | 长度 | 备注 |
|---|---|---|---|
| magic | 唯一标识 | 4 | class文件固定为0xcafebabe |
| version | class版本号 | 4 | 包括minor_version和major_version |
| constant_pool_count | 常量池数量 | 2 | |
| constant_pool[1~constant_pool_count] | 常量池内容 | 无 | constant_pool[0]专用于空指向 |
| access_flags | 访问标志 | 2 | |
| this_class | 当前类名 | 2 | 当前类的全限定名 |
| super_class | 父类名 | 2 | 父类的全限定名 |
| interfaces_count | 接口数量 | 2 | |
| interfaces[interfaces_count] | 接口内容 | 无 | |
| fields_count | 属性数量 | 2 | |
| fields[fields_count] | 属性内容 | 无 | |
| methods_count | 方法数量 | 2 | |
| methods[methods_count] | 方法内容 | 无 | |
| attributes_count | 附加属性数量 | 2 | |
| attributes[attributes_count] | 附加属性内容 | 无 |
常量池
在常量池中,java总共包含14中不同类型的常量池,如下表
| 常量名称 | 描述 | 字段tag | 字段2 | 字段3 | 长度(字节) |
|---|---|---|---|---|---|
| CONSTANT_Utf8_info | uf-8编码的字符串 | 1 | u2 length | ulength bytes[length] | length+3 |
| CONSTANT_Integer_info | 整型字面量 | 3 | u4 bytes | 5 | |
| CONSTANT_Float_info | 浮点型字面量 | 4 | u4 bytes | 5 | |
| CONSTANT_Long_info | 长整型字面量 | 5 | u4 high_bytes | u4 low_bytes | 9 |
| CONSTANT_Double_info | 双精度型字面量 | 6 | u4 high_bytes | u4 low_bytes | 9 |
| CONSTANT_Class_info | 表示类或接口 | 7 | u2 name_index | 3 | |
| CONSTANT_String_info | String类型的常量对象 | 8 | u2 string_index | 3 | |
| CONSTANT_Fieldref_info | 字段信息表 | 9 | u2 class_index | u2 name_and_type_index | 5 |
| CONSTANT_Methodref_info | 方法 | 10 | u2 class_index | u2 name_and_type_index | 5 |
| CONSTANT_InterfaceMethodref_info | 接口方法 | 11 | u2 class_index | u2 name_and_type_index | 5 |
| CONSTANT_NameAndType_info | 名称和类型表 | 12 | u2 name_index | u2 descriptor_index | 5 |
| CONSTANT MethodHandle_info | 方法句柄表 | 15 | u1 reference_kind | u2 reference_index | 4 |
| CONSTANT_MethodType_info | 方法类型表 | 16 | u2 descriptor_index | 3 | |
| CONSTANT_InvokeDynamic_info | 动态方法调用点 | 18 | u2 bootstrap_method_attr_index | u2 name_and_type_index | 5 |
访问标志符
实际存储的值通过位运算的形式进行计算最终的访问标志,比如0x0021 = 0x0020 + 0x0001
| 字段名称 | 值 | 描述 |
|---|---|---|
| ACC_PUBLIC | 0x0001 | 是否为public类型 |
| ACC_FINAL | 0x0010 | 是否为final |
| ACC_SUPER | 0x0020 | 该标志必须为真,JDK1.0.2之后编译出来的内容必须为真,指明invokespectial指令使用新语义 |
| ACC_INTERFACE | 0x0200 | 是否接口 |
| ACC_ABSTRACT | 0x0400 | 接口或抽象类 |
| ACC_SYNTHETIC | 0x1000 | 编译器自动生成,非用户代码产生 |
| ACC_ANNOTATION | 0x2000 | 是否为注解 |
| ACC_ENUM | 0x4000 | 是否为枚举 |
属性、方法
| 字段名称 | 描述 | 大小 |
|---|---|---|
| access_flags | 访问符 | 2字节 |
| name_index | 名称指向 | 2 |
| descriptor_index u2 | 描述指向 | 2 |
| attributes_count | 属性长度 | 4 |
| attributes | 属性名索引 | 2 |
版权声明:本文为weixin_43660088原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。