JVM 字节码的结构
编译的.class文件,可以用javap进行反编译
javap Test.class
javap -c Test.class
javap -verbose Test.class
1、创建MyTest1.java
public class MyTest1 {
private int a = 1; public MyTest1() {
} public int getA() {
return this.a;
} public void setA(int a) {
this.a = a;
}
}
使用D:\workspace\study\ jvm_demo\build\classes\java\main\com\example\jvm\bytecode>javap -verbose MyTest1.class
Classfile /D:/workspace/study/ jvm_demo/build/classes/java/main/com/example/jvm/bytecode/MyTest1.class
Last modified 2019-6-23; size 495 bytes
MD5 checksum 54c0850cfabb7f115919c93e556e3630
Compiled from "MyTest1.java"
public class com.example.jvm.bytecode.MyTest1
SourceFile: "MyTest1.java"
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #4.#20 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#21 // com/example/jvm/bytecode/MyTest1.a:I
#3 = Class #22 // com/example/jvm/bytecode/MyTest1
#4 = Class #23 // java/lang/Object
#5 = Utf8 a
#6 = Utf8 I
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/example/jvm/bytecode/MyTest1;
#14 = Utf8 getA
#15 = Utf8 ()I
#16 = Utf8 setA
#17 = Utf8 (I)V
#18 = Utf8 SourceFile
#19 = Utf8 MyTest1.java
#20 = NameAndType #7:#8 // "<init>":()V
#21 = NameAndType #5:#6 // a:I
#22 = Utf8 com/example/jvm/bytecode/MyTest1
#23 = Utf8 java/lang/Object
{
public com.example.jvm.bytecode.MyTest1();
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_1
6: putfield #2 // Field a:I
9: return
LineNumberTable:
line 6: 0
line 8: 4
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this Lcom/example/jvm/bytecode/MyTest1; public int getA();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field a:I
4: ireturn
LineNumberTable:
line 12: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/jvm/bytecode/MyTest1; public void setA(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: putfield #2 // Field a:I
5: return
LineNumberTable:
line 16: 0
line 17: 5
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/example/jvm/bytecode/MyTest1;
0 6 1 a I
}
2、使用WinHex打开MyTest1.class文件
1、使用javap -verbose命令分析一个字节码文件时,将会分析该字节码文件的魔数、版本号、常量池、类的构造方法、类中的方法信息、类变量与成员变量等信息。
2、魔数: 所有的.class字节码文件的前4个字节都是魔数,魔数值为固定值: 0xCAFEBABE.
3、魔数之后的四个字节为版本信息,前两个字节表示minor version(次版本号),后两个字节表示major version(主版本号)。这里的版本号为 00 00 00 33,换算成十进制,表示次版本为0,主版本为51. (51代表JDK7). 所有该文件的版本号为: 1.7.0
4、常量池(constant pool): 紧接着主版本号之后的就是常量池入口。一个Java类中定义的很多信息都是由常量池来维护和描述的,可以将常量池看作是Class文件的资源仓库,比如说Java类中定义的方法与变量信息,都是存储在常量池中。常量池主要存储两类常量: 字面量与符号引用。字面量如文本字符串,Java中声明为final的 常量值等,而符号引用如类和接口的全局限定名,字段的名称和描述符,方法的名称和描述符等。
5、常量池的总体结构: Java类所对应常量池主要由常量池数量与常量池数组(常量表)这两部分共同构成。常量池数量紧跟在主版本号后面,占据2个字节; 常量池数组则紧跟在常量池数量之后。常量池数组与一般的数组不同的是,常量池数组中不同的元素的类型、结构都是不同的,长度当然也是不同; 但是,每一种元素的第一个数据都是一个u1类型,该字节是标志位,占据1个字节。JVM在解析常量池时,会根据这个u1类型来获取元素的具体类型。值得注意的是,常量池数组中元素的个数 = 常量池数 - 1 (其中0暂时不使用), 目的是满足某些常量池索引值的数据在特定情况下需要表单[不引用任何一个常量池]的含义 ; 根本原因在于,索引为0也是一个常量(保留常量),只不过它不位于常量表中,这个常量就对应null值; 所以常量池的索引从1而非0开始。
6、在JVM规范中,每个变量/字段都有描述信息,描述信息主要的作用是描述字段的数据类型、方法的参数列表(包括数量、类型与顺序)与返回值。根据描述规则,基本数据类型和代表无返回值的void类型都用一个大写字符来表示,对象类型则使用字符L加对象的全限定名称来表示。为了压缩字节码文件的体积,对于基本数据类型,JVM都只使用一个大写字母来表示,如下所示B - byte, C - char, D - double, F - float, I - int, J - long, S - short, Z -boolean, V -void, L -对象类型, 如Ljava/lang/String;
7、对于数组来说,每一个维度使用一个前置的[来表示,如int[]被记录为[I, String[][]被记录为[[Ljava/lang/String
8、用描述符描述方法时,按照先参数列表,后返回值的顺序来描述。参数列表按照参数的严格顺序放在一组()之内,如方法String getRealnamebyIdAndNickname(int id, String name)的描述符为:(I,Ljava/lang/String;) Ljava/lang/String;
3、Class文件结构中常量池中11种数据类型的结构总表
上面的表中描述了11中数据类型的结构,其实在jdk1.7之后又增加了3种
CONSTANT_MethodHandle_info, CONSTANT_MethodType_info 以及CONSTANT_InvokeDynamic_info) 这样总共14种。
4、Java字节码整体结构
Access_Flag访问标志: 访问标志信息包括该Class文件是类还是接口,是否被定义成public,是否是abstract,如果是类,是否被声明成final。通过上面的MyTest1源代码,我们知道该文件是类并且是public。
0x 00 21: 是0x 0020 和 0x0001的并集,表示ACC_PUBLIC与ACC_SUPER
Fields字段表集合: 字段表用于描述类和接口中声明的变量。这里的字段包含了类级别变量(静态变量)以及实例变量(成员变量),但是不包含方法内声明的局部变量
字段表结构:
field_info
5、Java字节码整体结构
在Class文件的定义
6、Class字节码中有两种数据类型
1)字节数据直接量: 这是基本的数据类型。共细分为u1,u2,u4,u8四种,分别代表连续的1个字节,2个字节,4个字节,8个字节组成的整体数据。
2)表(数组): 表是由多个基本数据或其它表,按照既定顺序组成的大的数据集合。表是有结构的,它的结构体现在: 组成表的成分所在的位置和顺序都是已经严格定义好的。
JVM 字节码的结构的更多相关文章
- JVM 字节码执行实例分析
前言 最近在看<Java 虚拟机规范>和<深入理解JVM虚拟机>,对于字节码的执行有了进一步的了解.字节码就像是汇编语言,是 JVM 的指令集.下面我们先对 JVM 执行引擎做 ...
- Java finally语句到底是在return之前还是之后执行(JVM字节码分析及内部体系结构)?
之前看了一篇关于"Java finally语句到底是在return之前还是之后执行?"这样的博客,看到兴致处,突然博客里的一个测试用例让我产生了疑惑. 测试用例如下: public ...
- JVM 字节码(三)异常在字节码中的处理(catch 和 throws)
JVM 字节码(三)异常在字节码中的处理(catch 和 throws) 在 ClassFile 中到底是如何处理异常的呢? 一.代码块异常 catch catch 中的异常代码块在异常是如何处理的呢 ...
- JVM 字节码(二)方法表详解
JVM 字节码(二)方法表和属性表 上一节中对 ClassFile 的整体进行了五个详细的说明, 本节围绕 ClassFile 最重要的一个内容 - 方法表的 Code 属性展开 ,更多 JVM Me ...
- JVM 字节码(一)字节码规范
JVM 字节码(一)字节码规范 JVM 学习资源 Java ClassFile 字节码规范(Oracle) Java 虚拟机规范(Java SE 7 中文版) (周志明等译) Java 反编译工具 - ...
- JVM总结(五):JVM字节码执行引擎
JVM字节码执行引擎 运行时栈帧结构 局部变量表 操作数栈 动态连接 方法返回地址 附加信息 方法调用 解析 分派 –“重载”和“重写”的实现 静态分派 动态分派 单分派和多分派 JVM动态分派的实现 ...
- class字节码的结构
class字节码的结构 使用javap -verbose 命令分析一个.class字节码文件时(以下简称字节码文件),将会分析该字节码文件的魔数,版本号,常量池,类信息,类的构造方法,类中的方法信息, ...
- 一夜搞懂 | JVM 字节码执行引擎
前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 一.为什么要学习字节码执行引擎? 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一 ...
- 初探JVM字节码
作者: LemonNan 原文地址: https://juejin.im/post/6885658003811827725 代码地址: https://github.com/LemonLmNan/By ...
随机推荐
- MySql时区修改
1.查看当前时间 > select curtime(); #或select now()也可以+-----------+| curtime() |+-----------+| 15:18:10 | ...
- mac安装openjdk8-maven-mysql-git-docker
1. openjdk8安装命令查看地址:https://github.com/AdoptOpenJDK/homebrew-openjdk#other-versions 感觉上面命令地址不靠谱,还是 ...
- 不错的DSP和FPGA作者
https://blog.csdn.net/wordwarwordwar/article/details/90233903
- css详解3
推荐学习链接:css盒模型 1.盒模型的常用属性 1.1.pading <html lang="en"> <head> <meta charset=& ...
- linux 的常用命令(1)
1.关于ls [选项][目录名] -a 列出包括.a开头的隐藏文件的所有文件-A 通-a,但不列出"."和".."-l 列出文件的详细信息-c 根据ct ...
- springboot rabbitmq 死信队列应用场景和完整demo
何为死信队列? 死信队列实际上就是,当我们的业务队列处理失败(比如抛异常并且达到了retry的上限),就会将消息重新投递到另一个Exchange(Dead Letter Exchanges),该Exc ...
- 51nod 2499 不降的数字
小b有一个非负整数 N,她想请你找出 ≤N≤N 的最大整数x,满足x各个位数上的数字是不降的.也就是说,设x的十进制表示为 a1,a2,…,ama1,a2,…,am,则对于任意 1≤i<m1≤i ...
- 《ABCD组》第九次团队作业:Beta冲刺与验收准备
<ABCD组>第九次团队作业:Beta冲刺与验收准备 项目 内容 这个作业属于哪个课程 http://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 http ...
- destoon二次开发-签到时间函数扩展
在api/extend.func.php文件下增加以下代码: //签到时间函数 function timetoday($time = 0, $type = 6) { if(!$time) $time ...
- Linux中修改环境变量
<1>Linux 的变量作用范围可分为两类:环境变量和本地变量 环境变量,或者称为全局变量,存在与所有的shell 中,在你登陆系统的时候就已经有了相应的系统定义的环境变量了.Linux ...