深入理解JVM - 阅读笔记之思维导图 - 第 6 章 类文件结构
文章目录
- 章节概览
- 笔记
- 1. Class 类文件`结构格式`一览
- 2. 常量池具体`结构`
- 3. 字段表修饰符 access_flags 采用了 `9/16` 个标志位
- 4. 字段表 `描述符索引`
- 5. 方法表修饰符 access_flags 采用了 `12/16` 个标志位
- 6. 属性表集合 => Code 属性 => 所需的 `存储空间`
- 7. 属性表集合 => Code 属性 => `字节码指令长度`
- 8. 属性表集合 => Code 属性 => `字节码指令`
- 9. 属性表集合 => Code 属性 => `异常处理表`
- 10. 字节码指令简介 => 字节码与数据类型:大多数 `指令` 都包含了其操作对应的数据类型信息
- 11. 字节码指令简介 => 同步指令:JVM 支持方法级的同步和方法内部一段指令序列的同步,都是使用 `管程` 来支持的
章节概览
完整版的内容请点击这里
完整版的内容请点击这里
完整版的内容请点击这里
本章节主要分为 2 个部分:① Class 类文件结构,② 字节码指令简介
第 6 章节思维导图(更新于2019年4月14日)
笔记
1. Class 类文件结构格式
一览

2. 常量池具体结构
3. 字段表修饰符 access_flags 采用了 9/16
个标志位
标志值 | 标志名称 | 备注 |
---|---|---|
0x0001 | ACC_PUBLIC | 字段是否是 public 的,以下空白备注的类似 |
0x0002 | ACC_PRIVATE | |
0x0004 | ACC_PROTECTED | |
0x0008 | ACC_STATIC | |
0x0010 | ACC_FINAL | |
0x0040 | ACC_VOLATILE | |
0x0080 | ACC_TRANSIENT | |
0x1000 | ACC_SYNTHETIC | 字段是否是由编译器自动产生 |
0x4000 | ACC_ENUM |
4. 字段表 描述符索引
以下是一些详细的例子,用于解释方法和字段描述符是怎么表示的。
描述符标识字符含义:
标识字符 | 含义 | 标识字符 | 含义 |
---|---|---|---|
B | byte | J | long |
C | char | S | short |
D | double | Z | boolean |
F | float | V | void |
I | int | L | 对象类型,如Ljava/lang/Object |
如:
- java.lang.String[][]
=>[[Ljava/lang/String - void inc()
=>()V - java.lang.String toString()
=>()Ljava/lang/String; - int indexOf(char[] source, int sourceOfset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex)
=>([CII[CIII)I
5. 方法表修饰符 access_flags 采用了 12/16
个标志位
标志值 | 标志名称 | 备注 |
---|---|---|
0x0001 | ACC_PUBLIC | |
0x0002 | ACC_PRIVATE | |
0x0004 | ACC_PROTECTED | |
0x0008 | ACC_STATIC | |
0x0010 | ACC_FINAL | |
0x0020 | ACC_SYNCHRONIZED | |
0x0040 | ACC_BRIDGE | 方法是否是由编译器产生的桥接方法 |
0x0080 | ACC_VARARGS | |
0x0100 | ACC_NATIVE | |
0x0400 | ACC_ABSTRACT | |
0x0800 | ACC_STRICTFP | |
0x1000 | ACC_SYNTHETIC | 方法是否是由编译器自动产生的 |
6. 属性表集合 => Code 属性 => 所需的 存储空间
max_locals 的单位是 Slot,这是 VM 为局部变量分配内存所使用的最小的单位。对于 byte, char, float, int, short, boolean, returnAddress 等长度不超过 32 位的数据类型,每个局部变量占用 1 个 Slot;而 double, long 这两种 64 位的数据类型占用 2 个 Slot。
方法参数(包括实例方法中的隐藏参数 “this”)、显式异常处理器的参数(Exception Handle Parameter,就是 try-catch 语句中 catch 块定义的异常)、方法体中定义的局部变量都需要使用 局部变量表 来存放。
另外,局部变量表之和 不等于 max_locals,因为当代码运行到了超出某个变量的作用域时,该变量的空间可以提供给其他的局部变量使用,Javac 编译器会根据变量的作用域来分配 Slot 给各个变量使用,然后计算出 max_locals 的大小。
7. 属性表集合 => Code 属性 => 字节码指令长度
code_length 是一个 u4 类型的长度值,理论上最大值可以达到 2^32 - 1,但是虚拟机对于长度超过 65535 条字节码指令会拒绝编译。但是在编译一个复杂的 JSP 文件时,有可能会因为方法生成的字节码过长而导致编译失败。
8. 属性表集合 => Code 属性 => 字节码指令
u1 数据类型的取值是 0x00 ~ 0xFF,对应 256 条指令。
在方法中,默认会有一个参数(Args_size) “this”,在编译的时候吧对 this 关键字的访问转变为对一个普通方法参数的访问,然后在虚拟机调用实例方法时自动传入此参数。但是静态方法则默认为 0。
9. 属性表集合 => Code 属性 => 异常处理表
结构:
类型 | 名称 | 数量 | 备注 |
---|---|---|---|
u2 | start_pc | 1 | |
u2 | end_pc | 1 | |
u2 | handler_pc | 1 | |
u2 | catch_type | 1 | 指向 CONSTANT_Class_info 型常量的索引 |
含义:
如果当字节码在第 start_pc
行到底 end_pc
行之间(不含)出现类类型为 catch_type
或者其子类的异常,则跳转到第 handler_pc
行继续处理,当 catch_type
等于 0 时,代表所有异常都要跳转到 handler_pc
行来处理。
10. 字节码指令简介 => 字节码与数据类型:大多数 指令
都包含了其操作对应的数据类型信息
如 iload
表示从局部变量表中加载 int
型的数据到操作数栈中,而 fload
加载的则是 float
类型的数据