看看 JVM 是怎样消化字节码指令的 ~~

点击上方「蓝字」关注,给 Java 加点料~



写文章,标题真是个头疼的事儿。写的偏技术点,可能被认为太生硬。写的吸引点儿,可能被认为是「广告」,看着每次阅读量都不到 3%,不由得「老泪纵横」...

如果本文对你有帮助,转发到朋友圈和「在看」支持一下啊。

扯远了,回到我们的正题。前面一篇写到Java 虚拟机的几个组成部分。不知道你有没有觉得, JVM 也像我们人或者生物一样,执行的过程一如咱们吃东西。只不过他吃的是 .class 文件,把其中认为有营养的常量池、字节码指令等消化吸收,同时一边把垃圾处理掉,在最后不用的时候,再把全部的垃圾unload

整个 .class 文件中, 字节码指令是很重要的一个部分,所有方法内的逻辑,都是通过这些指令来完成操作。

今天咱就一起来看看指令。

指令

我们前面说过,指令集(ISA)的实现,一般有两种形式

  • 基于寄存器实现

  • 基于栈的实现

两者各有优劣,但对于 JVM 来说,设计者在初期就已经明确了场景和目标,所以JVM实现的指令集是基于栈实现的,具有指令数量少,格式简单,操作数少,易于理解和实现等等特点。

一般一个典型的指令集系统中,需要实现的操作分为以下几类:

  • 数据传送

  • 运算:包括算术运算、逻辑运算和移位运算等

  • 流程控制:控制转移、条件转移、无条件转移以及复合条件转移

  • 中断、同步、图形处理(硬件)等

用通俗的语言描述的话,JVM 这些指令,按革命分工不同,大概干的事儿有:

  1. 像搬运工一样,来回在局部变量区操作数栈这两个地方来回挪动数据。比如从局部变量区加载到操作数栈,计算一下,再保存回局部变量区。

这类的命令又根据搬运方向的不同,分为从局部变量表操作数栈load指令:iload_nlload_naload_n等,分别又对应到不同的操作数类型上,第一个字母基本都代表类型,i -> int, l -> long, a -> 引用。后面的n是数字。

以及分为从 操作数栈局部变量表store指令:istore_nlstore_nastore_n等等,类型同上。

还有一些是从常量池直接加载到栈顶的,像ldcbipushiconst_i等。

  1. 像手艺人一样,做些打磨加工的工作,把石头做成雕塑类似的类型转换。比如把int 转成long,把double 转成int这些,对应的JVM 指令是i2ld2i 2前面是源类型,后面是目标类型。

  2. 新的生命的孕育,像对象的创建数组的创建等,以及对类型的操作。创建一个新的类实例 new, 新建一个数组 newarray比如getstatic 是访问类的static 域 、getfield 获取类的实例域 判断对象是否属于特定类型的instanceof

  3. 像红绿灯一样,指导道路的通行方向,来控制程序流程。有条件的转移:像咱们常用的 if (x == 1) 这种,到了字节码的时候,就变成了if_icmpne还有像try-catch字节码里常看到的 goto,做无条件的跳转。还有一些复合条件的转移,像tableswitch 来支持 switch 语法。而对于 switch 能支持 String ,则是通过编译的时候,把 String 对应的 hashCode取出来,做为int 值来使用,通过 lookupswitch 来处理 case 不连续的情形。

  4. 像你我程序员一样 :-),在 PM 提过来需求之后, 负责把它实现出来,在JVM里这些是运算指令的活儿。比如int 加法iadd, int 减法isub, 递增iinc这些。

  5. 还有些函数的调用,执行的返回等等,对于静态和非静态方法,对应的指令稍有差别。像 invokevirtual是调用普通实例方法的,invokestatic 是调用类的静态方法的。以及类的初始化方法init,是通过 invokespecial调用的。方法调用完,一般通过 return结束调用,返回 void, 如果是返回类型数据,则是return,这里的T 和咱们前面说的各种代表数据类型的一样,比如返回int类型的值,对应的指令是 ireturn

  6. 异常的情况,通过 athrow指令,抛出去。异常的处理原理,可以参考上一篇文章:你写下的try-catch-finally,在JVM看来不过是...

用来学习的工具

如果对这一部分感兴趣,日常开发中,有几个小工具可以使用。

  1. 像Java 自带的javap 开箱即用。

  2. 一个图形界面的工具jclasslib

下载地址:https://github.com/ingokegel/jclasslib/releases

  1. IDEA 里面可以安装工具 jclasslib 对应的插件。

相比 javap,图形界面工具除了使用方便,不用命令行,可以方便查看自己编写的代码生成的字节码到底是哪些外,同时各个方法内对应的字节码指令,只要点击一下就能跳转到指令的官方说明,也方便理解和学习。

比如上面的 iconst_2 指令,会跳转到 Oracle 的这个说明页面

体验还是不错的。 开始你的字节码之旅吧!

看点别的

怎样计算一个Java对象大小?这儿有几种方法~

你写下的try-catch-finally,在JVM看来不过是...

理解了1+2的过程,就理解了Java虚拟机

问题诊断神器BTrace

Java七武器系列霸王枪 -- 线程状态分析 jstack

Tomcat的异步Servlet实现原理

监控诊断工具 Arthas 源码原理分析

Java虚拟机的显微镜 Serviceability Agent

怎样回答技术面试题?

怎样了解你的线程在干嘛?

更多常见问题,请关注公众号,在菜单「常见问题」中查看,也欢迎加我微信,一起交流。 

源码|实战|成长|职场

这里是「Tomcat那些事儿」

请留下你的足迹

我们一起「终身成长」

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值