字节码指令
目录
2.1 入门
2.2 javap 工具
2.3 图解方法执行流程
1)原始 java 代码
2)编译后的字节码文件
3)常量池载入运行时常量池
4)方法字节码载入方法区
5)main 线程开始运行,分配栈帧内存
6)执行引擎开始执行字节码
bipush 10
istore_1
ldc #3
istore_2
iload_2
iadd
istore_3
getstatic #4
iload_3
invokevirtual #5
return
2.1 入门
接着上一节,研究一下两组字节码指令,一个是
//构造方法的字节码指令
public cn.itcast.jvm.t5.HelloWorld();
2a b7 00 01 b1
- 2a => aload_0 加载 slot 0 的局部变量,即 this,做为下面的 invokespecial 构造方法调用的参数
- b7 => invokespecial 预备调用构造方法,哪个方法呢?
- 00 01 引用常量池中 #1 项,即【 Method java/lang/Object."":()V 】
- b1 表示返回
另一个是 public static void main(java.lang.String[]); 主方法的字节码指令
b2 00 02 12 03 b6 00 04 b1
- b2 => getstatic 用来加载静态变量,哪个静态变量呢?
- 00 02 引用常量池中 #2 项,即【Field java/lang/System.out:Ljava/io/PrintStream;】
- 12 => ldc 加载参数,哪个参数呢?
- 03 引用常量池中 #3 项,即 【String hello world】
- b6 => invokevirtual 预备调用成员方法,哪个方法呢?
- 00 04 引用常量池中 #4 项,即【Method java/io/PrintStream.println:(Ljava/lang/String;)V】
- b1 表示返回
请参考
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5
2.2 javap 工具
自己分析类文件结构太麻烦了,Oracle 提供了 javap 工具来反编译 class 文件
[root@localhost ~]# javap -v HelloWorld.class
Classfile /root/HelloWorld.class
Last modified Jul 7, 2019; size 597 bytes
MD5 checksum 361dca1c3f4ae38644a9cd5060ac6dbc
Compiled from "HelloWorld.java"
public class cn.itcast.jvm.t5.HelloWorld
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #6.#21 // java/lang/Object."<init>":()V
#2 = Fieldref #22.#23 //
java/lang/System.out:Ljava/io/PrintStream;
#3 = String #24 // hello world
#4 = Methodref #25.#26 // java/io/PrintStream.println:
(Ljava/lang/String;)V
#5 = Class #27 // cn/itcast/jvm/t5/HelloWorld
#6 = Class #28 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcn/itcast/jvm/t5/HelloWorld;
#14 = Utf8 main
#15 = Utf8 ([Ljava/lang/String;)V
#16 = Utf8 args
#17 = Utf8 [Ljava/lang/String;
#18 = Utf8 MethodParameters
#19 = Utf8 SourceFile
#20 = Utf8 HelloWorld.java
#21 = NameAndType #7:#8 // "<init>":()V
#22 = Class #29 // java/lang/System
#23 = NameAndType #30:#31 // out:Ljava/io/PrintStream;
#24 = Utf8 hello world
#25 = Class #32 // java/io/PrintStream
#26 = NameAndType #33:#34 // println:(Ljava/lang/String;)V
#27 = Utf8 cn/itcast/jvm/t5/HelloWorld
#28 = Utf8 java/lang/Object
#29 = Utf8 java/lang/System
#30 = Utf8 out
#31 = Utf8 Ljava/io/PrintStream;
#32 = Utf8 java/io/PrintStream
#33 = Utf8 println
#34 = Utf8 (Ljava/lang/String;)V
{
public cn.itcast.jvm.t5.HelloWorld();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."
<init>":()V
4: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcn/itcast/jvm/t5/HelloWorld;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field
java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String hello world
5: invokevirtual #4 // Method
java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 6: 0
line 7: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 args [Ljava/lang/String;
MethodParameters:
Name Flags
args
}
2.3 图解方法执行流程
1)原始 java 代码
package cn.itcast.jvm.t3.bytecode;
/**
* 演示 字节码指令 和 操作数栈、常量池的关系
*/
public class Demo3_1 {public static void main(String[] args) {int a = 10;int b = Short.MAX_VALUE + 1;int c = a + b;System.out.println(c);}
}
2)编译后的字节码文件
[root@localhost ~]# javap -v Demo3_1.class
Classfile /root/Demo3_1.class
Last modified Jul 7, 2019; size 665 bytes
MD5 checksum a2c29a22421e218d4924d31e6990cfc5
Compiled from "Demo3_1.java"
public class cn.itcast.jvm.t3.bytecode.Demo3_1
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #7.#26 // java/lang/Object."<init>":()V
#2 = Class #27 // java/lang/Short
#3 = Integer 32768
#4 = Fieldref #28.#29 //
java/lang/System.out:Ljava/io/PrintStream;
#5 = Methodref #30.#31 // java/io/PrintStream.println:(I)V
#6 = Class #32 // cn/itcast/jvm/t3/bytecode/Demo3_1
#7 = Class #33 // java/lang/Object
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 LocalVariableTable
#13 = Utf8 this
#14 = Utf8 Lcn/itcast/jvm/t3/bytecode/Demo3_1;
#15 = Utf8 main
#16 = Utf8 ([Ljava/lang/String;)V
#17 = Utf8 args
#18 = Utf8 [Ljava/lang/String;
#19 = Utf8 a
#20 = Utf8 I
#21 = Utf8 b
#22 = Utf8 c
#23 = Utf8 MethodParameters
#24 = Utf8 SourceFile
#25 = Utf8 Demo3_1.java
#26 = NameAndType #8:#9 // "<init>":()V
#27 = Utf8 java/lang/Short
#28 = Class #34 // java/lang/System
#29 = NameAndType #35:#36 // out:Ljava/io/PrintStream;
#30 = Class #37 // java/io/PrintStream
#31 = NameAndType #38:#39 // println:(I)V
#32 = Utf8 cn/itcast/jvm/t3/bytecode/Demo3_1
#33 = Utf8 java/lang/Object
#34 = Utf8 java/lang/System
#35 = Utf8 out
#36 = Utf8 Ljava/io/PrintStream;
#37 = Utf8 java/io/PrintStream
#38 = Utf8 println
#39 = Utf8 (I)V
{
public cn.itcast.jvm.t3.bytecode.Demo3_1();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."
<init>":()V
4: return
LineNumberTable:
line 6: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcn/itcast/jvm/t3/bytecode/Demo3_1;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: bipush 10
2: istore_1
3: ldc #3 // int 32768
5: istore_2
6: iload_1
7: iload_2
8: iadd
9: istore_3
10: getstatic #4 // Field
java/lang/System.out:Ljava/io/PrintStream;
13: iload_3
14: invokevirtual #5 // Method
java/io/PrintStream.println:(I)V
17: return
LineNumberTable:
line 8: 0
line 9: 3
line 10: 6
line 11: 10
line 12: 17
LocalVariableTable:
Start Length Slot Name Signature
0 18 0 args [Ljava/lang/String;
3 15 1 a I
6 12 2 b I
10 8 3 c I
MethodParameters:
Name Flags
args
}
3)常量池载入运行时常量池

4)方法字节码载入方法区

5)main 线程开始运行,分配栈帧内存
(stack=2,locals=4)

6)执行引擎开始执行字节码
bipush 10
将一个 byte 压入操作数栈(其长度会补齐 4 个字节),类似的指令还有
sipush 将一个 short 压入操作数栈(其长度会补齐 4 个字节)
ldc 将一个 int 压入操作数栈
ldc2_w 将一个 long 压入操作数栈(分两次压入,因为 long 是 8 个字节)
这里小的数字都是和字节码指令存在一起,超过 short 范围的数字存入了常量池

istore_1
将操作数栈顶数据弹出,存入局部变量表的 slot 1

ldc #3
从常量池加载 #3 数据到操作数栈
注意 Short.MAX_VALUE 是 32767,所以 32768 = Short.MAX_VALUE + 1 实际是在编译期间计算
好的

istore_2

iload_1

iload_2

iadd


istore_3

getstatic #4


iload_3

invokevirtual #5
找到常量池 #5 项
定位到方法区 java/io/PrintStream.println:(I)V 方法
生成新的栈帧(分配 locals、stack等)
传递参数,执行新栈帧中的字节码

执行完毕,弹出栈帧
清除 main 操作数栈内容

return
完成 main 方法调用,弹出 main 栈帧
程序结束
相关文章:
字节码指令
目录 2.1 入门 2.2 javap 工具 2.3 图解方法执行流程 1)原始 java 代码 2)编译后的字节码文件 3)常量池载入运行时常量池 4)方法字节码载入方法区 5)main 线程开始运行,分配栈帧内存 6)…...
TLS/SSL证书彻底扫盲
证书格式 pem Privacy Enhanced Mail文本格式,以 -----BEGIN CERTIFICATE----- 开头,以-----END CERTIFICATE-----结尾 der 二进制格式,只保存证书,不保存私钥java和window服务器常见 pfx/p12 Predecessor of PKCS#12二进制格式&…...
WGCNA | 值得你深入学习的生信分析方法!~(网状分析-第五步-高级可视化)
1写在前面 前面我们用WGCNA分析完成了一系列的分析,聚类分割模块。🥰 随后进一步筛选,找到与我们感兴趣的表型或者临床特征相关的模块,而且进行了模块内部分析。😘 再然后是对感兴趣模块进行功能注释,了解模…...
try catch finally执行顺序
try catch finally,try里有return,finally还执行么?答案: 执行,并且返回return时,finally的执行早于try。try-catch-finally的执行顺序无return当try中的t()没有抛出异常public static void main(String[] …...
2023年数学建模美赛D题(Prioritizing the UN Sustainability Goals)分析与编程
2023年数学建模美赛D题分析建模与编程 重要说明: 本文介绍2023年美赛题目,并进行简单分析;本文首先对 D题进行深入分析,其它题目分析详见专题讨论;本文及专题分析将在 2月17日每3小时更新一次,完全免费&am…...
35岁测试工程师被辞退,给你们一个忠告
一:前言:人生的十字路口静坐反思 入软件测试这一行至今已经10年多,承蒙领导们的照顾与重用,同事的支持与信任,我的职业发展算是相对较好,从入行到各类测试技术岗位,再到测试总监,再转…...
华为OD机试题 - 租车骑绿岛(JavaScript)
最近更新的博客 2023新华为OD机试题 - 斗地主(JavaScript)2023新华为OD机试题 - 箱子之形摆放(JavaScript)2023新华为OD机试题 - 考古学家(JavaScript)2023新华为OD机试题 - 相同数字的积木游戏 1(JavaScript)2023新华为OD机试题 - 最多等和不相交连续子序列(JavaScri…...
Linux下Python脚本的编写解析fio(minimal格式)(三)
在服务器测试(storage)过程中,会看到很多人写跑fio的脚本用minimal格式来解析,因为这种格式返回的结果对与脚本(shell,python)解析log非常方便.下面介绍一下这种方式下,用Python来解析log 1 一般客户会要求结果中出现一下参数的值: bandwidth…...
【实战场景二】如何设计一个分布式锁?
如何优雅的设计一个分布式锁?如何设计一个分布式锁?1、什么是分布式锁2、那么分布式锁,具备什么条件呢?3、设计分布式锁有哪些方式?3.1 利用redis实现分布式锁原理3.2 基于数据库做分布式锁3.3 基于zookeeper实现分布式…...
Java中ThreadLocal类详解
ThreadLocal从名字上我们看出,它叫做本地线程变量,每个线程都有各自的的变量,而不再是我们之前的两个线程共用同一个变量;以这个类创建的变量,在多个线程都用到这个变量时,可以为每一个线程创建一个变量副本…...
从一致性角度考虑推荐冷启动长尾推荐问题(一)
前言:目前中长尾推荐的方法有很多,主流的方法有几类比如:1)在没有项目ID嵌入的情况下提高推荐模型的鲁棒性,2)利用有限的交互数据提高学习效率,如使用元学习方法;3)利用物品侧面信息,便于物品ID嵌入的初始化࿰…...
电脑(Windows)常用快捷键
简述:实用的键盘快捷键是一个程序员的必备技能,下面给大家整理了一下常用的键盘快捷键; ⭐CtrlP 打开“打印机”对话框; ⭐CtrlW 关闭当前网页; ⭐CtrlF 查找(网页内查找); ⭐…...
Java类加载器
1 类加载器 1.1 类加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的连接,类的初始化这三个步骤来对类进行初始化。如果不出现意外情况,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为…...
信号完整性设计规则之单根信号失真最小化
本文内容从《信号完整性与电源完整性分析》整理而来,加入了自己的理解,如有错误,欢迎批评指正。 1. 通常采用所能容许的最长上升边。 上升边越短,带宽越大,信号完整性问题越严重。 2. 使用可控阻抗走线。 可控阻抗…...
Python3 数据结构
列表 Python中列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和元组不能。 以下是 Python 中列表的方法: 方法 描述 list.append(x) 把一个元素添加到列表的结尾…...
Compose-Navigation带参传递
带参传递 目前 compose 还不支持传入对象作为参数! 简单双参数 根目录下新建文件夹 entity,新建单例类 ContentType 作为数据类存储位置 新增数据类 DemoContent,这表示我们需要传入的两个参数,后面带问号判空 object ContentT…...
【函数栈帧的创建和销毁】 -- 神仙级别底层原理,你学会了吗?
文章目录1.函数的调用方式 2.函数在栈区上的动作 1.函数的调用方式 相信你对调用函数一点都不陌生,但是在调用函数的过程中,却存在着很多你无法见到的东西,这是底层信息,想要理解透彻,就得深入底层去观察。 本文以…...
Promise的使用及原理
此文章主要讲解核心思想和基本用法,想要了解更多细节全面的使用方式,请阅读官方API 这篇文章假定你具备最基本的异步编程知识,例如知道什么是回调,知道什么是链式调用,同时具备最基本的单词量,例如page、us…...
怎么拥有一个帅气的 CMD 命令窗口 ❓ - Windows
自从拥有这样一个炫酷的命令窗口,我都舍不得关掉它了 关于我为什么我要闲的去 “打扮” 一个命令窗口,这要从星期五下午的一场 摸鱼 🐠 开始,当时我要创建一个 vue ts vite 的项目练练手,为新项目开始做准备&#x…...
时隔多年再学习Vuex,什么?原来如此简单!
时隔多年再学习Vuex,什么?原来如此简单! start 写 Vue 写了好多年了,少不了和 Vuex 打交道。虽然使用它的次数非常频繁,但是潜意识里总觉得这东西很难,导致遇到与之相关的问题就容易慌张。时至今日,升级版…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
