一文讲清楚JVM字节码文件的组成

01-以正确的姿势打开文件

字节码文件中保存了 源代码编译之后的内容,以 二进制的方式 存储,无法直接用记事本打开阅读

通过NotePad++使用十六进制插件查看class文件:

推荐使用 jclasslib 工具查看字节码文件;
Github地址: https://github.com/ingokegel/jclasslib

02-字节码文件的组成

字节码文件总共可以分为以下几个部分:

  • 基础信息 :魔数、字节码文件对应的 Java版本号、访问标识(public final 等)、父类和接口信息
  • 常量池: 保存了 字符串常量、类或接口名、字段名,主要在字节码指令中使用
  • 字段: 当前类或接口声明的 字段信息
  • 方法: 当前类或接口声明的方法信息,核心内容为方法的字节码指令
  • 属性: 类的属性,比如源码的文件名、内部类的列表等

2.1 基本信息

基本信息包含了jclasslib中能看到的两块内容:一般信息 和 接口

01-魔数

02-主副版本号

03-其它基础信息

2.2 常量池

字节码文件中常量池的作用:避免相同的内容重复定义,节省空间

本质是一个数组

2.3 方法

通过分析方法的字节码指令,可以清楚地了解一个方法到底是如何执行的。先来看如下案例:

java 复制代码
int i = 0;
int j = i + 1;

这段代码编译成字节码指令之后是如下内容:

关于三条字节码指令的说明:

  • iconst_常量值:将 该常量放入操作数栈 中;
  • istore_数组下标:将 操作数栈中的值 放到 局部变量表对应的数组下标 中;
  • iload_数组下标:将 局部变量表中对应数组下标的值取出来放到操作数栈 中

01-操作数栈 & 局部变量表

要理解这段字节码指令是如何执行的,我们需要先理解两块内存区域:操作数栈和局部变量表。

  • 操作数栈 是用来存放临时数据的内容,是一个栈式的结构,先进后出;
  • 局部变量表 是存放方法中的局部变量,包含方法的参数、方法中定义的局部变量,在编译期就已经可以确定方法有多少个局部变量

02- i = i++ 的执行流程

i++ 的字节码指令如下:

  • 其中 iinc 1 by 1 指令指的是 将局部变量表1号位置增加1,其实就实现了i++的操作

最终结果仍为 0

03- i = ++i 的执行流程

而 ++i 只是对两个字节码指令的顺序进行了更改:iioad_1 和 iinc 1 by 1

最终结果为 1

04-经典面试题

05-思考

i++:iinc 1 by 1;
k+=1:iinc 2 by 1

i++ 和 k+=1 都是一行 iinc _ by 1 就搞定了,但是 j = j + 1 需要四行指令

相关推荐
李可以量化3 分钟前
Tornado 从了解到精通(一)下:异步与非阻塞 IO 核心原理
java·数据库·tornado
yurenpai(27届找实习中)5 分钟前
从销售订单推送 MES 看懂微服务调用(二):DTO 转换与 OpenFeign 调用
java·微服务·架构·服务调用
Patrick在香港11 分钟前
Python爬虫框架实战:优雅抓取香港政府公开API数据的通用方案
java·开发语言·爬虫·python·ai编程·数据可视化·可用性测试
hey_sml20 分钟前
MySQL常用操作速记:从字符集到游标全解析
java·开发语言·mysql
掉鱼的猫23 分钟前
Solon AOT & Native:三段式编译,从 Java 到原生可执行文件
java·云原生
Java内核笔记27 分钟前
容错能力进入 spring-core:Spring Boot 4 原生重试机制全解析
java·后端
未秃头的程序猿32 分钟前
虚拟线程上线一周后翻车了——pinning问题排查实录
java·后端·架构
wuminyu35 分钟前
JDK21解决虚拟线程IO阻塞原理剖析
java·linux·c语言·jvm·c++
带刺的坐椅41 分钟前
Solon AOT & Native:三段式编译,从 Java 到原生可执行文件
java·aot·solon·native
程序员良辰1 小时前
【TongWeb8】使用 Crontab 定时重启和检测 TongWeb 服务
java·中间件·tomcat