「Java 路线」| Class 文件结构

点赞关注,不再迷路,你的支持对我意义重大!

🔥 Hi,我是丑丑。本文 「Java 路线」| 导读 —— 他山之石,可以攻玉 已收录,这里有 Android 进阶成长路线笔记 & 博客,欢迎跟着彭丑丑一起成长。(联系方式在 GitHub)

前言

  • Class 文件Java技术体系的重要组成部分,在学习整个虚拟机的执行引擎之前,应该清楚Class 文件的结构;
  • 这篇文章将带你理解Class 文件的基本结构,希望能帮上忙。

延伸文章

目录


1. 什么是 Class 文件?

  • 定义:或称字节码,可以看作Java 虚拟机的可执行文件

  • 作用:对应于一个类 / 抽象类 / 接口的定义信息

  • 意义Java 虚拟机 & Class 文件共同构成了Java无关性的基础

  • 来源

      1. Java 源码经过Java 编译器编译后得到,以磁盘文件形式存在
      1. 由字节码生成技术(如javassist / CGLib / ASM)生成,以内存中二进制流形式存在
# 咬文嚼字 #

虽然字节码不一定是以 “磁盘文件” 的形式存在,但是通常在很多文献 & 资料中会笼统地将字节码表述为Class 文件,这里不必钻牛角尖。

更多信息请务必阅读:《Java | 为什么 Java 实现了平台无关性》


2. Class 文件的大致结构

  • Class 文件是一种强协议的紧凑型结构(遵循《Java 虚拟机规范》)
  • Class 文件有三种数据结构:无符号数、TVL、表,具体如下:
  • Class 文件本质上也是一个表,大致结构如下图:
  • 魔数:固定值0xCAFEBABE,用于鉴别为合法的Class 文件
  • 版本号:表示Class 文件的目标版本号,高版本的虚拟机可以向前兼容旧版本Class 文件
  • 访问标志:一个u2无符号数,用于表示本类 / 接口的访问信息。其中每个标志位的值与java.lang.reflect.Modifier中的常量一一对应:
  • 本类索引 & 父类索引 & 接口索引集:是一个索引值,(共经过 2 次索引后)指向常量池中一个utf-8编码的 全限定名,例如:java/lang/Object;

  • 字段表集合:用于描述类或接口中声明的变量(包括类变量与成员变量)

  • 方法表集合:用于描述类或接口中声明的方法(包括类方法与成员方法)

  • 属性表集合:用于描述 Class 文件、字段表、方法表中携带的属性


下面,我将概括表中各个重点数据项的具体含义!

3. 常量池(const pool)

  • 常量池中的每一项常量都是一个表
  • 存放两种类常量:字面量(Literal)符号引用(Symbolic References)

符号引用(Symbolic References)是一个字符串类型的字面量(存储在常量池),它的作用是唯一地标示一个实体,最重要的特点如下:

  • 平台无关性
    这一点与Java的特性是一脉相承的。符号引用与具体虚拟机实现内存布局无关,需要在运行期将符号引用转换为直接引用(Direct Reference),这个直接引用才是符号引用在虚拟机中的真实存在。

  • 唯一性
    无歧义地标示一个目标,以方法为例,如果是本类中声明的方法,不需要添加类名(如:Method func:()V);如果是其他类中声明的方法, 需要添加类名前缀(如:Method com/Base.func:()V)。

常量池表结构有一个共同的特点,就是表结构的首元素是u1的标志位,代表当前的常量类型,截止到Java 13总共有 20 种常量:

常量类型 —— 引用自《深入理解Java虚拟机》

4. 本类索引 & 父类索引 & 接口索引集

  • 本类索引肯定存在,只有一个
  • Java是类单继承,所以父类索引只有一个(特例:Object的父类索引为 0)
  • Java是接口多继承,所以接口索引有零或多个

这三个索引值均指向常量池中CONSTANT_Class_info常量,而CONSTANT_Class_info常量本质上也是一个索引值,指向CONSTANT_Utf8_info常量。经过 2次 索引,这三个索引最终指向对应 类 / 接口的全限定名

2 次索引后指向全限定名 —— 引用自《深入理解Java虚拟机》

5. 字段表(field_info)

字段表用于描述类字段与实例字段,但只包括在本类中声明的字段,既不包括父类中声明的字段,也不包括方法内部声明的局部变量。要注意的是,编译器生成的字段是包括的,例如编译器会为非静态内部类添加外部类的引用字段。字段表的基本结构如下:

字段表的基本结构
  • access_flags:字段的访问标志位
  • name_index:常量池索引,最终指向字段的简单名称,见第 8 节
  • descriptor_index:常量池索引,最终指向字段的描述符,见第 8 节
  • attributes_count & attributes:字段属性,为字段的附加信息,见第 8 节

6. 方法表(method_info)

方法表和字段表的设计是很相似的。方法表用于描述类方法与实例方法,但只包括在本类中声明的方法或者重写的方法,不包括父类或父接口中声明的方法。需要注意的是,编译器生成的方法是包括的,例如类构造器<clinit>()与实例构造器<init>()。方法表的基本结构如下:

方法表的基本结构

可以看到,方法表和字段表的基本结构是完全一致的,此处不再赘述。需要特别指出的是,方法里面的代码在方法的Code属性,方法的受检异常声明在Exception属性


7. 属性表(attribute_info)

  • 属性相当于字段表或方法表的附加信息
  • 每一项属性都是一个表,基本结构如下图所示:
属性表的基本结构
  • attribute_name_index:常量池索引,最终指向一个属性名。Class 文件使用属性名来区分每一种属性,截止到Java 12,总共有 29 种预定义属性。
  • attribute_length:不同属性的属性信息是不同的,因此需要一个长度表表示属性信息占用的长度
  • info:属性信息
# 你觉得呢?#

市面上你能找到的介绍虚拟机的书籍,普遍都会按顺序罗列出每种属性的信息。笔者并不是说这种方式不好,因为作为书籍的阐述方式需要考虑到读者可接受度 & 参考性的问题。但是如果以博客的阐述方式也采用同样地方式,岂非成为知识搬运工?因此,我将从不同的问题域出发,在每个问题域中介绍每种属性。

Code 属性
Exceptions 属性

LocalVariableTable 属性

LocalVariableTypeTable 属性
Signature 属性

泛型中所谓的类型擦除,其实只是擦除Code 属性中的泛型信息,在类常量池属性中其实还保留着泛型信息,这也是在运行时可以反射获取泛型信息的根本依据。在这篇文章里,我们详细讨论:《Java | 关于泛型能问的都在这里了(含Kotlin)》,请关注!


RuntimeVisibleAnnotations 属性
RuntimeInvisibleAnnotations 属性
RuntimeVisibleParameterAnnotations 属性
RuntimeInvisibleParameterAnnotations 属性

注解在编译后擦除,如果注解的保留级别为CLASS & RUNTIME,在 Class 文件中还会生成对应的注解属性。在这篇文章里,我们详细讨论:《Java | 这是一篇全面的注解使用攻略(含 Kotlin)》,请关注!


InnerClasses 属性

8. 信息描述规则

Editting...


参考资料

  • 《深入理解Java虚拟机(第3版本)》(第6章)—— 周志明 著
  • 《深入理解Android:Java虚拟机 ART》(第2章) —— 邓凡平 著
  • 《深入理解 JVM 字节码》(第2、3、4章)—— 张亚 著

创作不易,你的「三连」是丑丑最大的动力,我们下次见!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249