Java class 文件结构

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

一、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 回帖

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • Ant-Design

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

    17 引用 • 23 回帖
  • 数据库

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

    342 引用 • 708 回帖
  • GitBook

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

    3 引用 • 8 回帖 • 4 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3453 回帖 • 203 关注
  • SVN

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

    29 引用 • 98 回帖 • 680 关注
  • Openfire

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

    6 引用 • 7 回帖 • 94 关注
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    21 引用 • 31 回帖 • 1 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    5 引用 • 7 回帖
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    32 引用 • 131 回帖 • 1 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 64 关注
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 73 关注
  • FreeMarker

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

    23 引用 • 20 回帖 • 462 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 4 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    286 引用 • 248 回帖 • 61 关注
  • 反馈

    Communication channel for makers and users.

    123 引用 • 911 回帖 • 245 关注
  • Chrome

    Chrome 又称 Google 浏览器,是一个由谷歌公司开发的网页浏览器。该浏览器是基于其他开源软件所编写,包括 WebKit,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。

    62 引用 • 289 回帖 • 1 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 49 关注
  • Log4j

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

    20 引用 • 18 回帖 • 30 关注
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 764 关注
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 355 关注
  • GraphQL

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

    4 引用 • 3 回帖 • 9 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 638 关注
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    15 引用 • 7 回帖 • 1 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    247 引用 • 1348 回帖
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖 • 1 关注
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    36 引用 • 35 回帖 • 1 关注
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    17 引用 • 236 回帖 • 328 关注