Java class 文件结构

本贴最后更新于 2590 天前,其中的信息可能已经天翻地覆

一、class 文件数据项的类型
u1
u2
u4
u8
...

二、class 文件的数据项

类型 名称 数量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count - 1
u2 access_flags 1
u2 this_class 1
u2 super_class 1
u2 interfaces_count 1
u2 interfaces interfaces_count
u2 fields_count 1
field_info fields fields_count
u2 methods_count 1
method_info methods methods_count
u2 attribute_count 1
attribute_info attributes attributes_count

三、各数据项
1、魔数(magic)
4 个字节,固定为 0XCAFEBABE。

2、次版本号(minor_version)
2 个字节。

3、主版本号(major_version)
2 个字节。

4、常量池大小(constant_pool_count)
2 个字节。

5、常量池(constant_pool)
constant_pool_count-1 个 cp_info。
索引为 0 的常量池项空白,引用索引为 0 的常量池项则表示不引用任何常量池项。
常量池数据项类型:

常量池中数据项类型 类型标志 类型描述
CONSTANT_Utf8 1 UTF-8 编码的 Unicode 字符串
CONSTANT_Integer 3 int 类型字面值
CONSTANT_Float 4 float 类型字面值
CONSTANT_Long 5 long 类型字面值
CONSTANT_Double 6 double 类型字面值
CONSTANT_Class 7 对一个类或接口的符号引用
CONSTANT_String 8 String 类型字面值
CONSTANT_Fieldref 9 对一个字段的符号引用
CONSTANT_Methodref 10 对一个类中声明的方法的符号引用
CONSTANT_InterfaceMethodref 11 对一个接口中声明的方法的符号引用
CONSTANT_NameAndType 12 对一个字段或方法的部分符号引用

class 文件的特殊字符串:
i. 类的全限定名:java/lang/Object
ii. 描述符:

基本数据类型和 void 类型 类型的对应字符
byte B
char C
double D
float F
int I
long J
short S
boolean Z
void V

引用类型:“L”+ 类型的全限定名 +“;”
数组类型:若干个“[”+ 数组中元素类型的对应字符串
方法:(参数 1 类型 参数 2 类型 参数 3 类型 ...)返回值类型 //各个参数类型之间没有空格, 参数列表和返回值类型之间也没有空格

iii. 特殊方法的方法名
构造方法:<init>
静态代码块:<clinit>

  • CONSTANT_Utf8
一个 CONSTANT_Utf8_info
tag(1 个字节)
length(2 个字节)
bytes(length 个字节)

CONSTANT_Utf8 类型数据项可表示:程序中的字符串常量, 类型的全限定名, 方法和字段的名称, 方法和字段的描述符, 属性相关字符串。

  • CONSTANT_NameAndType
一个 CONSTANT_NameAndType_info
tag(1 个字节)
name_index(名称)
descriptor_index(描述符)

一个 CONSTANT_NameAndType_info 就表示了一个被调用的方法(如父类的构造函数)或一个被使用的字段。
仅在类中定义的字段或方法没有相应的 CONSTANT_NameAndType_info。

  • CONSTANT_Integer
一个 CONSTANT_Integer_info
tag(1 个字节)
bytes(4 个字节)
  • CONSTANT_Float
一个 CONSTANT_Float_info
tag(1 个字节)
bytes(4 个字节)
  • CONSTANT_Long
一个 CONSTANT_Long_info
tag(1 个字节)
bytes(8 个字节)
  • CONSTANT_Double
一个 CONSTANT_Double_info
tag(1 个字节)
bytes(8 个字节)
  • CONSTANT_String
一个 CONSTANT_String_info
tag(1 个字节)
string_index(2 个字节)
  • CONSTANT_Class
    一个 CONSTANT_Class_info 是对类或者接口的符号引用(包括数组)。
一个 CONSTANT_Class_info
tag(1 个字节)
name_index(类的全限定名,2 个字节)
  • CONSTANT_Fieldref
    该数据项表示对一个字段的符号引用, 可以是对本类中的字段的符号引用, 也可以是对其他类中的字段的符号引用, 可以是对成员变量字段的符号引用, 也可以是对静态变量的符号引用。
    字段必须被使用才会有相应的符号引用,只在类中定义是没有符号引用的。
一个 CONSTANT_Fieldref_info
tag(1 个字节)
class_index(2 个字节)
name_and_type_index(2 个字节)
  • CONSTANT_Methodref
    对一个类中方法的符号引用, 可以是对本类中的方法的符号引用, 也可以是对其他类中的方法的符号引用, 可以是对成员方法的符号引用, 也可以是对静态方法的符号引用,但是不会是对接口中的方法的符号引用。
    方法必须被调用才会有相应的符号引用,只在类中定义是没有符号引用的。
一个 CONSTANT_Methodref_info
tag(1 个字节)
class_index(2 个字节)
name_and_type_index(2 个字节)
  • CONSTANT_InterfaceMethodref
    表示对一个接口方法的符号引用。
一个 CONSTANT_InterfaceMethodref_info
tag(1 个字节)
class_index(2 个字节)
name_and_type_index(2 个字节)

6、当前类(或者接口)的访问修饰符(access_flags)
2 个字节

志名 标志值 标志含义 针对的对像
ACC_PUBLIC 0x0001 public 类型 所有类型
ACC_FINAL 0x0010 final 类型
ACC_SUPER 0x0020 使用新的 invokespecial 语义 类和接口
ACC_INTERFACE 0x0200 接口类型 接口
ACC_ABSTRACT 0x0400 抽象类型 类和接口
ACC_SYNTHETIC 0x1000 该类不由用户代码生成 所有类型
ACC_ANNOTATION 0x2000 注解类型 注解
ACC_ENUM 0x4000 枚举类型 枚举

7、对当前类的描述(this_class)(类的全限定名)
2 个字节(对一个 CONSTANT_Class_info 数据项的索引)。

8、对当前类的超类的描述(super_class)
2 个字节(对一个 CONSTANT_Class_info 数据项的索引)。

9、当前类所实现的接口的数量(interfaces_count)
注意, 只有当前类直接实现的接口才会被统计, 如果当前类继承了另一个类, 而另一个类又实现了一个接口, 那么这个接口不会统计在当前类的 interfaces_count 中。

10、当前类所实现的接口(interfaces)
interfaces_count 个 u2。
每个数据项指向常量池中的一个 CONSTANT_Class_info。

11、当前的类中定义的字段的个数(fields_count)
2 个字节。
注意, 这里包括静态字段, 但不包括从父类继承的字段。 如果当前 class 文件是由一个接口生成的, 那么这里的 fields_count 描述的是接口中定义的字段, 我们知道, 接口中定义的字段默认都是静态的。此外要说明的是, 编译器可能会自动生成字段, 也就是说, class 文件中的字段的数量可能多于源文件中定义的字段的数量。 举例来说, 编译器会为内部类增加一个字段, 这个字段是指向外围类的对象的引用。

12、当前的类中定义的字段(fields)
field_count 个 field_info。
field 结构:

一个 field
access_flags
name_index
descriptor_index
attributes_count
attributes
  • 标志位(access_flags)
    2 个字节。
标志位名称 含义 设定者
ACC_PUBLIC 0x0001 字段被设为 public 类和接口
ACC_PRIVATE 0x0002 字段被设为 private
ACC_PROTECTED 0x0004 字段被设为 protected
ACC_STATIC 0x0008 字段被设为 static 类和接口
ACC_FINAL 0x0010 字段被设为 final 类和接口
ACC_VOLATILE 0x0040 字段被设为 volatile
ACC_TRANSIENT 0x0080 字段被设为 transient
  • 字段名(name_index)
    2 个字节。
    指向常量池中的一个 CONSTANT_Utf8_info 数据项。

  • 描述符(descriptor_index)
    2 个字节。
    指向常量池中的一个 CONSTANT_Utf8_info 数据项。

  • 属性数量(attributes_count)
    2 个字节。

  • 属性(attributes)
    可以出现在 filed_info 中的属性有三种, 分别是 ConstantValueDeprecated, 和 Synthetic

13、当前的类中定义的方法的个数(methods_count)

标志位名称 标志值 设定含义 设定者
ACC_PUBLIC 0x0001 方法设为 public 类和接口
ACC_PRIVATE 0x0002 方法设为 private
ACC_PROTECTED 0x0004 方法设为 protected
ACC_STATIC 0x0008 方法设为 static
ACC_FINAL 0x0010 方法设为 final
ACC_SYNCHRONIZED 0x0020 方法设为 sychronized
ACC_NATIVE 0x0100 方法设为 native
ACC_ABSTRACT 0x0400 方法设为 abstract 类和接口
ACC_STRICT 0x0800 方法设为 strictFP 类和接口的方法

可以出现在 method_info 中的属性分别是 CodeDeprecatedExceptions Synthetic

14、attribute_count

15、attribute
SourceFile // 内部类的,描述其外部类
InnerClasses // 外部类的,描述其内部类
Synchetic // 表示不是由用户代码生成的,是由编译器自动添加的,可以修饰方法和字段,例如,如果一个类不定义构造方法, 那么编译器会自动添加一个无参数的构造方法, 如果定义了静态字段或静态代码块, 还会根据具体情况, 增加静态初始化方法
ConstantValue // 修饰字段
Deprecated // 修饰字段和方法

符号引用

最基本的 UTF-8 编码的 Unicode 字符串
CONSTANT_Utf8

字面量
CONSTATN_Integer
CONSTATN_Long
CONSTATN_Float
CONSTANT_Double
CONSTANT_String

符号引用
CONSTANT_Class // 类或接口的符号引用
CONSTATN_NameAndType // 一个字段或方法的部分符号引用
// 以下三种符号引用由上面两种符号引用组成
CONSTATN_Fieldref // 字段的符号引用
CONSTANT_Methodref // 类中声明的方法的符号引用
CONSTANT_InterfaceMethodref // 接口中声明的方法的符号引用

#1、#2 等表示在常量池中的下标
#0 表示不引用任何常量池的项,比如

直接引用
就是偏移量,根据这些偏移量可以找到相应的类,并在类的内存区域中找到对应的字段或方法。

class 文件其实就存了两样东西:字面量符号引用

参考:
《深入理解 Java 虚拟机》
《Java 虚拟机规范(JavaSE8)》
http://blog.csdn.net/brave2211/article/category/1593711/1

  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖 • 3 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    343 引用 • 723 回帖
  • Bug

    Bug 本意是指臭虫、缺陷、损坏、犯贫、窃听器、小虫等。现在人们把在程序中一些缺陷或问题统称为 bug(漏洞)。

    76 引用 • 1737 回帖 • 1 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 483 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 317 关注
  • danl
    146 关注
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖
  • SVN

    SVN 是 Subversion 的简称,是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统,它的设计目标就是取代 CVS。

    29 引用 • 98 回帖 • 694 关注
  • 自由行
    4 关注
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    209 引用 • 358 回帖
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 4 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 1 关注
  • Gzip

    gzip (GNU zip)是 GNU 自由软件的文件压缩程序。我们在 Linux 中经常会用到后缀为 .gz 的文件,它们就是 Gzip 格式的。现今已经成为互联网上使用非常普遍的一种数据压缩格式,或者说一种文件格式。

    9 引用 • 12 回帖 • 147 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    110 引用 • 54 回帖 • 1 关注
  • 反馈

    Communication channel for makers and users.

    123 引用 • 913 回帖 • 250 关注
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    71 引用 • 535 回帖 • 789 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 60 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 637 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    167 引用 • 1520 回帖
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 363 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    407 引用 • 3578 回帖
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    149 引用 • 257 回帖
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 465 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 29 关注
  • Openfire

    Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。

    6 引用 • 7 回帖 • 101 关注
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 668 关注