JVM字节码文件

文章目录

  • 字节码文件
    • [1. 基础信息](#1. 基础信息)
    • [2. 常量池](#2. 常量池)
    • [3. 方法](#3. 方法)

字节码文件

Java的字节码文件由基础信息、常量池、字段、方法、属性五个部分组成。

1. 基础信息

字节码中的基础信息包含魔术、字节码文件对应的Java版本号,以及访问标识(public final等等),父类和接口。

Magic魔术

  • 文件是无法通过文件拓展名来确定文件类型的,文件拓展名可以随意修改,不影响文件的内容
  • 软件通过文件的**头几个字节(文件头)**来校验文件的类型,如果软件不支持该种文件类型就会报错
  • Java字节码文件中,将文件头称为Magic魔术
  • 在Java字节码文件中的前4个字节为CAFEBABE

主副版本号

  • 主副版本号指的是编译字节码文件的JDK版本号,主版本号用来标识大版本号,JDK1.0-1.1使用了45.0-45.3,JDK1.2之后每升级一个大版本就加1,副版本号是当前主版本号相同时作为区分不同版本的标识,一般只需关心主版本号
  • 版本号的作用主要是判断当前字节码的版本和运行时的JDK是否兼容
  • JDK1.2之后版本号的计算方法就是主版本号-44,主版本号52就是JDK8

2. 常量池

常量池中保存了字符串常量、类或者接口名、字段名主要在字节码指令中使用。

  • 字节码文件中的常量池的作用就是为了避免相同的内容重复定义,节省空间
  • 常量池中的数据都有一个编号,编号从1开始,在字段或者字节码指令中通过编号可以快速的找到对应的数据
  • 字节码指令中通过编号引用到常量池的过程称为符号引用
  • 需要注意的是字段名也可能引用常量池中的字符串常量,比如说下面这段代码,字段名abc和其它3个字段的值abc都是引用了同一个字符串常量,进一步优化空间
java 复制代码
public class ConstantPoolTest2 {
    public static final String a1 = "abc";
    public static final String a2 = "abc";
    public static final String abc = "abc";
    public static void main(String[] args) {
        ConstantPoolTest2 constantPoolTest = new ConstantPoolTest2();
    }
}

3. 方法

当前类或者接口声明的方法信息(字节码指令)

字节码的方法中有这么几个部分:

  • 字节码指令
  • 操作数栈:临时存放数据的地方
  • 局部变量表数组:存放方法中局部变量的位置

有如下两行代码

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

编译后生成如下字节码指令

java 复制代码
iconst_0 // 将常量0放入操作数栈
istore_1 // 将操作数栈取出放入局部变量表数组1号位置
iload_1  // 将局部变量表数组1号位置的数据放入操作数栈中
iconst_1 // 将常量1 放入操作数栈
iadd     // 将操作数栈顶的两个数据相加,结果放入栈中
istore_2 // 将操作数栈顶的数据取出来放到局部变量数组2号位置
return // 方法结束返回

如下代码输出啥?

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

通过查看字节码的方法

java 复制代码
iconst_0 // 将0放入操作数栈
istore_1 // 从操作数栈取出栈顶元素取出放入局部变量表1号位置
iload_1 // 从局部变量表1号位置加载数据到操作数栈
iinc 1 by 1  // 在局部变量表1号位置数+1
istore_1 // 将操作数栈中的值保存到局部变量表中

i最后答案是0,我通过分析字节码指令发现,i++先把0取出来放入临时的操作数栈中接下来对i进行加1,i变成了1,最后再将之前保存的临时值0放入i,最后就变成了0。

一下这几种自增方式,谁的效率最高呢?

java 复制代码
i++
i += 1
i = i+1

直接来看对应的字节码

i++

java 复制代码
iconst_0
istore_1
iinc 1 by 1

i += 1

java 复制代码
iconst_0
istore_1
iinc 1 by 1

i = i + 1

java 复制代码
iconst_0
istore_1
iload_1
iconst_1
iadd
istore_1

理论来说字节码指令越少,效率是越高的


相关推荐
在努力的前端小白2 小时前
Spring Boot 敏感词过滤组件实现:基于DFA算法的高效敏感词检测与替换
java·数据库·spring boot·文本处理·敏感词过滤·dfa算法·组件开发
完全学不完2 小时前
JVM对象创建和内存分配
jvm
一叶飘零_sweeeet5 小时前
从繁琐到优雅:Java Lambda 表达式全解析与实战指南
java·lambda·java8
艾伦~耶格尔5 小时前
【集合框架LinkedList底层添加元素机制】
java·开发语言·学习·面试
一只叫煤球的猫5 小时前
🕰 一个案例带你彻底搞懂延迟双删
java·后端·面试
最初的↘那颗心5 小时前
Flink Stream API 源码走读 - print()
java·大数据·hadoop·flink·实时计算
JH30736 小时前
Maven的三种项目打包方式——pom,jar,war的区别
java·maven·jar
带刺的坐椅7 小时前
轻量级流程编排框架,Solon Flow v3.5.0 发布
java·solon·workflow·flow·solon-flow
David爱编程7 小时前
线程调度策略详解:时间片轮转 vs 优先级机制,面试常考!
java·后端
阿冲Runner8 小时前
创建一个生产可用的线程池
java·后端