点击上方「蓝字」关注,给 Java 加点料~
写文章,标题真是个头疼的事儿。写的偏技术点,可能被认为太生硬。写的吸引点儿,可能被认为是「广告」,看着每次阅读量都不到 3%,不由得「老泪纵横」...
如果本文对你有帮助,转发到朋友圈和「在看」支持一下啊。
扯远了,回到我们的正题。前面一篇写到Java 虚拟机的几个组成部分。不知道你有没有觉得, JVM 也像我们人或者生物一样,执行的过程一如咱们吃东西。只不过他吃的是 .class
文件,把其中认为有营养
的常量池、字节码指令等消化吸收,同时一边把垃圾
处理掉,在最后不用的时候,再把全部的垃圾unload
。
整个 .class
文件中, 字节码指令是很重要的一个部分,所有方法内的逻辑,都是通过这些指令来完成操作。
今天咱就一起来看看指令。
指令
我们前面说过,指令集(ISA)的实现,一般有两种形式
基于寄存器实现
基于栈的实现
两者各有优劣,但对于 JVM 来说,设计者在初期就已经明确了场景和目标,所以JVM实现的指令集是基于栈实现的,具有指令数量少,格式简单,操作数少,易于理解和实现等等特点。
一般一个典型的指令集系统中,需要实现的操作分为以下几类:
数据传送
运算:包括算术运算、逻辑运算和移位运算等
流程控制:控制转移、条件转移、无条件转移以及复合条件转移
中断、同步、图形处理(硬件)等
用通俗的语言描述的话,JVM 这些指令,按革命分工不同
,大概干的事儿有:
像搬运工一样,来回在
局部变量区
和操作数栈
这两个地方来回挪动数据。比如从局部变量区加载到操作数栈,计算一下,再保存回局部变量区。
这类的命令又根据搬运方向的不同,分为从局部变量表
到 操作数栈
的load
指令:iload_n
、lload_n
、aload_n
等,分别又对应到不同的操作数类型上,第一个字母基本都代表类型,i -> int
, l -> long
, a -> 引用
。后面的n是数字。
以及分为从 操作数栈
到局部变量表
的store
指令:istore_n
、lstore_n
、astore_n
等等,类型同上。
还有一些是从常量池直接加载到栈顶的,像ldc
、bipush
、iconst_i
等。
像手艺人一样,做些打磨加工的工作,
把石头做成雕塑
类似的类型转换
。比如把int 转成long,把double 转成int这些,对应的JVM 指令是i2l
和d2i
2前面是源类型,后面是目标类型。新的生命的孕育,像
对象的创建
、数组的创建
等,以及对类型
的操作。创建一个新的类实例new
, 新建一个数组newarray
比如getstatic
是访问类的static 域 、getfield
获取类的实例域 判断对象是否属于特定类型的instanceof
像红绿灯一样,指导道路的通行方向,来控制程序流程。有条件的转移:像咱们常用的
if (x == 1)
这种,到了字节码的时候,就变成了if_icmpne
还有像try-catch
字节码里常看到的goto
,做无条件的跳转。还有一些复合条件的转移,像tableswitch
来支持switch
语法。而对于 switch 能支持 String ,则是通过编译的时候,把 String 对应的 hashCode取出来,做为int 值来使用,通过lookupswitch
来处理 case 不连续的情形。像你我程序员一样 :-),在 PM 提过来需求之后, 负责把它实现出来,在JVM里这些是
运算
指令的活儿。比如int 加法iadd
, int 减法isub
, 递增iinc
这些。还有些函数的调用,执行的返回等等,对于静态和非静态方法,对应的指令稍有差别。像
invokevirtual
是调用普通实例方法的,invokestatic
是调用类的静态方法的。以及类的初始化方法init
,是通过invokespecial
调用的。方法调用完,一般通过return
结束调用,返回 void, 如果是返回类型数据,则是return,这里的T 和咱们前面说的各种代表数据类型的一样,比如返回int类型的值,对应的指令是ireturn
。异常的情况,通过
athrow
指令,抛出去。异常的处理原理,可以参考上一篇文章:你写下的try-catch-finally,在JVM看来不过是...
用来学习的工具
如果对这一部分感兴趣,日常开发中,有几个小工具可以使用。
像Java 自带的
javap
开箱即用。一个图形界面的工具
jclasslib
下载地址:https://github.com/ingokegel/jclasslib/releases
IDEA 里面可以安装工具 jclasslib 对应的插件。
相比 javap,图形界面工具除了使用方便,不用命令行,可以方便查看自己编写的代码生成的字节码到底是哪些外,同时各个方法内对应的字节码指令,只要点击一下就能跳转到指令的官方说明,也方便理解和学习。
比如上面的 iconst_2 指令,会跳转到 Oracle 的这个说明页面
体验还是不错的。 开始你的字节码之旅吧!
看点别的
你写下的try-catch-finally,在JVM看来不过是...
Java虚拟机的显微镜 Serviceability Agent
更多常见问题,请关注公众号,在菜单「常见问题」中查看,也欢迎加我微信,一起交流。
源码|实战|成长|职场
这里是「Tomcat那些事儿」
请留下你的足迹
我们一起「终身成长」