【深入理解JVM-1】JVM字节码文件剖析
一、背景
二、二进制字节码文件分析
1. 使用javap -verbose 命令分析字节码文件
Java字节码整体结构如下所示:
1.1 分析字节码文件的魔数、版本号、常量池
- 工具:Hex_Fiend,下载地址
- 以单字节为间隔展示文件如下:
- 魔数:CA FE BA BE,所有的.class字节码文件的前4字节都是魔数,固定值为0xCAFEBABE
- 版本号:00 00 00 31,前面两字节为次版本号0,后面两字节为主版本号49
1.2 常量池
- 常量池( constant pool):紧接着主版本号之后的即常量池。一个Java类中定义的很多信息都是由常量池来维护和描述的,可将常量池看作是class文件的资源仓库,例如Java类中定义的方法与变量信息,均存储在常量池中。常量池中主要存储两类信息:字面量、符号引用。
- 字面量:文本字符串、Java类中声明为final的常量值等
- 符号引用:类和接口的全局限定名、字段的名称和描述符、方法的名称和描述符(与源码的对应关系)
- 常量池总体结构:Java类所对应的常量池主要由常量池数据量(紧跟主版本号后面,占2字节)与常量池数组( 紧跟常量池数量后面)两部分共同构成。常量池数组中不同元素的类型、结构均不同,但是每个元素的第一个数据都是一个u1类型,该字节是个标志位,占1个字节,JVM在解析常量池时,会根据这个u1类型来获取元素的具体类型。
- 常量池数组中元素个数=常量池数-1(0暂不使用),满足某些常量池索引值的数据表达为【不引用任何一个常量池】的含义
- 如图,00 18代表常量池数量为23。
- 如上图,标注为第一个常量池,0A为1字节的tag,值为10,代表CONSTANT_Methodref_info,
- 00 04为2字节的index,值为4,指向声明方法的类描述符,即如下的“#4 = Class #23 // java/lang/Object”
- 00 14为2字节的index,值为20,指向名称及类型描述符,即如下的“#20 = NameAndType #7:#8 // “”😦)V”,指向#7和#8,方法名称为构造方法,类型描述符为()V。十六进制可以直接通过ASCLL转换成具体的字符
STARLYWANG-MB0:classes starlywang$ javap -verbose com.bytecode.MyTest1
Classfile /Users/starlywang/IdeaProjects/comtest/target/classes/com/bytecode/MyTest1.class
Last modified 2020-3-1; size 471 bytes
MD5 checksum c75cdac216156e899c9491c4738e0b60
Compiled from "MyTest1.java"
public class com.bytecode.MyTest1
minor version: 0 //小版本
major version: