小师妹学JVM之:java的字节码byte code简介
简介
Byte Code也叫做字节码,是连接java源代码和JVM的桥梁,源代码编译成为字节码,而字节码又被加载进JVM中运行。字节码怎么生成,怎么查看字节码,隐藏在Byte Code背后的秘密是什么呢?快跟小师妹一起来看看吧。
Byte Code的作用
小师妹:F师兄,为什么Java需要字节码呢?直接编译成为机器码不是更快吗?
小师妹,Java的设计初衷是一次编写,到处运行。为了兼容各个平台的运行环境,java特别为各种平台设计了JVM。
我们可以把JVM看做是一种抽象,对外提供了统一的接口。这样我们只需要编写符合JVM规范的代码,即可在JVM中运行。
回想下之前我们提到过的java的执行过程:
- 编写java代码文件比如Example.java
- 使用java编译器javac将源文件编译成为Example.class文件
- JVM加载生成的字节码文件,将其转换成为机器可以识别的native machine code执行
小师妹:F师兄,我有一个大胆的想法,JVM的作用是将字节码解释或者编译成为机器码。然后在相应的运行环境中执行。那么有没有可能,不需要JVM,不需要机器码,而是直接在对应的平台上执行字节码呢?
爱因斯坦说过没有想像力的灵魂,就像没有望远镜的天文台。小师妹你这个想法很好,这种实现有个专业的说法叫做:Java processor。
Java processor就是用硬件来实现的JVM。因此字节码可以直接在Java processor中运行。
其中比较出名的是Jazelle DBX,这是一个主要支持J2ME环境的硬件架构。为了提升java在手机端的执行速度。
但是这样做其实也是有缺点的,后面我们会讲到,java字节码中的指令非常非常多。所以如果用硬件来实现的话,就会非常非常复杂。
一般来说Java processor不会实现全部的字节码中的功能,只会提供部分的实现。
查看Byte Code字节码
小师妹:F师兄,那使用javac编译过后的class文件跟字节码有什么关系呢?
class文件中大部分都是byte code,其他的部分是一些meta data元数据信息。这些组合在一起就是class文件了。
小师妹:F师兄,你说class文件是byte code,为什么我在IDE中打开的时候,直接显示的是反编译出来的源文件呢?
小师妹,这是IDE的一个便利功能。因为大多数情况下,没有人想去看class文件的Byte code的,大家都是想去看看这个class文件的源文件是什么样的。
我们举个最简单的例子:
这个类中,我们定义了一个很简单的testByteCode方法,里面定义了两个变量,然后返回他们两个的和。
现在有两种方法来查看这个类的Byte Code:
第一种方法是用javap命令:
javap -c ByteCodeUsage.class
生成的结果如上所示。
第二种方法就是在IDEA中,选中class文件,然后在view中选中show Bytecode:
我们看下输出结果:
两个的结果在显示上面可能有细微的差异,但是并不影响我们后面对其的解析。
java Byte Code是怎么工作的
小师妹:F师兄,能讲解一下这些byte code到底是怎么工作的吗?
首先我们要介绍一下JVM的实现是基于栈的结构的。为什么要基于栈的结构呢?那是因为栈是最适合用来实现function互相调用的。
我们再回顾一下上面的testByteCode的字节码。里面有很多iconst,istore的东西,这些东西被称作Opcode,也就是一些基于栈的操作指令。
上面讲了java bytecode的操作指令其实有很多个。下面我们列出这些指令的部分介绍:
实在是太多了,这里就不把所有的列出来了。
我们看到的指令名字其实是一个助记词,真实的Opcode是一个占用两个字节的数字。
下面我们来详细解释一下testByteCode方法:
public int testByteCode();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: ireturn
第一步,iconst_1将int 1加载到stack中。
第二步,istore_1将入栈的int 1出栈,并存储到变量1中。
第三步,iconst_2将int 2入栈。
第四步,istore_2将入栈的int 2出栈,并存储到变量2中。
第五步,iload_1将变量1中的值入栈。
第六步,iload_2将变量2中的值入栈。
第七步,iadd将栈中的两个变量出栈,并相加。然后将结果入栈。
第八步,ireturn将栈中的结果出栈。
这几步实际上完美的还原了我们在testByteCode方法中定义的功能。
当然我们只介绍了最贱的byte code命令,通过这些简单的命令可以组合成为更加复杂的java命令。
总结
本文介绍了java byte code的作用和具体的指令,并分析了一个简单的例子来做说明。希望大家能够掌握。
本文的例子https://github.com/ddean2009/learn-java-base-9-to-20
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/jvm-byte-code/
本文来源:flydean的博客
欢迎关注我的公众号:程序那些事,更多精彩等着您!
小师妹学JVM之:java的字节码byte code简介的更多相关文章
- 小师妹学JVM之:JVM的架构和执行过程
目录 简介 JVM是一种标准 java程序的执行顺序 JVM的架构 类加载系统 运行时数据区域 执行引擎 总结 简介 JVM也叫Java Virtual Machine,它是java程序运行的基础,负 ...
- 小师妹学JVM之:JIT中的PrintAssembly
目录 简介 使用PrintAssembly 输出过滤 总结 简介 想不想了解JVM最最底层的运行机制?想不想从本质上理解java代码的执行过程?想不想对你的代码进行进一步的优化和性能提升? 如果你的回 ...
- 小师妹学JVM之:深入理解JIT和编译优化-你看不懂系列
目录 简介 JIT编译器 Tiered Compilation分层编译 OSR(On-Stack Replacement) Deoptimization 常见的编译优化举例 Inlining内联 Br ...
- 小师妹学JVM之:JDK14中JVM的性能优化
目录 简介 String压缩 分层编译(Tiered Compilation) Code Cache分层 新的JIT编译器Graal 前置编译 压缩对象指针 Zero-Based 压缩指针 Escap ...
- 小师妹学JVM之:JIT中的LogCompilation
目录 简介 LogCompilation简介 LogCompilation的使用 解析LogCompilation文件 总结 简介 我们知道在JVM中为了加快编译速度,引入了JIT即时编译的功能.那么 ...
- 小师妹学JVM之:JIT中的PrintCompilation
目录 简介 PrintCompilation 分析PrintCompilation的结果 总结 简介 上篇文章我们讲到了JIT中的LogCompilation,将编译的日志都收集起来,存到日志文件里面 ...
- 小师妹学JVM之:JVM中的Safepoints
目录 简介 GC的垃圾回收器 分代回收器中的问题 safepoints safepoint一般用在什么地方 总结 简介 java程序员都听说过GC,大家也都知道GC的目的是扫描堆空间,然后将那些标记为 ...
- 小师妹学JVM之:GC的垃圾回收算法
目录 简介 对象的生命周期 垃圾回收算法 Mark and sweep Concurrent mark sweep (CMS) Serial garbage collection Parallel g ...
- 小师妹学JVM之:逃逸分析和TLAB
目录 简介 逃逸分析和栈上分配 TLAB简介 TLAB详解 设置TLAB空间的大小 TLAB中大对象的分配 TLAB空间中的浪费 总结 简介 逃逸分析我们在JDK14中JVM的性能优化一文中已经讲过了 ...
随机推荐
- oracle11g数据库导入、导出操作
一.在linux系统中导入数据库. 1.linux中先输入 su - oracle下切换到oracle用户.然后以sysdba打开sqlplus:sqlplus / as sysdba 然后创建表空间 ...
- OkHttp,一次无奈的使用
一次使用OKHTTP的心痛历程 最近由于一些不得已的原因,接触到了OKHttp,说起来也挺Dan疼的,之前同事将生产附件上传地址配置成了测试地址,还好数量不多,没有造成太大的影响,况且的是这位同事又离 ...
- Java实现 LeetCode 912 排序数组(用数组去代替排序O(N))
912. 排序数组 给你一个整数数组 nums,将该数组升序排列. 示例 1: 输入:nums = [5,2,3,1] 输出:[1,2,3,5] 示例 2: 输入:nums = [5,1,1,2,0, ...
- Java实现 LeetCode 611 有效三角形的个数(双指针)
611. 有效三角形的个数 给定一个包含非负整数的数组,你的任务是统计其中可以组成三角形三条边的三元组个数. 示例 1: 输入: [2,2,3,4] 输出: 3 解释: 有效的组合是: 2,3,4 ( ...
- Java实现 LeetCode 68 文本左右对齐
68. 文本左右对齐 给定一个单词数组和一个长度 maxWidth,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本. 你应该使用"贪心算法"来放置 ...
- ArrayDeque使用&实现原理分析
ArrayDeque使用&实现原理分析 学习Okhttp实现源码时,发现其任务分发时用到了ArrayDeque.因此了解一下ArrayDeque的使用方式和实现原理. 一.Deque dequ ...
- tensorflow2.0学习笔记第一章第三节
1.3鸢尾花数据读入 # 从sklearn包datasets读入数据 from sklearn import datasets from pandas import DataFrame import ...
- linux 删除文件后 df 查看磁盘空间并没有释放
1.错误现象 Linux 磁盘空间总是报警,查到到大文件,删除之后,df看到磁盘空间并没有释放. 用du -sh ./* | sort -nr (查看当前目录下文件的大小)通过查找了下发现文件被mys ...
- [AGC034F]RNG and XOR
题目 点这里看题目. 分析 第一步可以将\(A\)数组转化成概率\(P(j)\):每一步操作异或\(j\)的概率. 接着发现,\(x\)从\(0\)变成\(i\)的期望等于\(x\)从\( ...
- cheerio html方法中文被编码问题
var $ = cheerio.load("<h1><p>你好</p><em>Hello,World!</em></h1&g ...