[jvm解析系列][十三]字节码指令小节,从字节码看JVM的栈解释器执行过程。

Posted 胖子程序员

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[jvm解析系列][十三]字节码指令小节,从字节码看JVM的栈解释器执行过程。相关的知识,希望对你有一定的参考价值。

众所周知,JVM以前一直采用的是解释执行,但是后来在历代的版本更迭中也加入了编译执行。所以总的来说JVM是包含了解释执行和编译执行。这一部分不属于JVM的范畴了,已经属于编译了,大多数都是进行词法分析之类的,以后有时间会补充。

同时大家都知道现在大体上分为两种指令集架构,第一种就是基于栈的第二种是基于寄存器的,简单点说,基于寄存器的架构速度更快,但是可移植性不强,但是基于栈的指令集架构虽然慢,但是可移植性很强,大家都知道java本身就是依靠可移植性出名的,所以无可争议的使用了栈的指令集架构。(也有例外,dalvik是基于寄存器的)

下面我们详述一下JVM的栈解释器执行过程,在此之前我们先来讲一下字节码的指令含义:



加载和存储:加载和存储指令一般可以把栈帧中的局部变量放到操作数栈中,然后把操作数栈中的变量存回栈帧中。

把局部变量加载到操作数栈中:主要有iload,liload_<n>,lload,(每一个指令前面代表的是它操作的数据类型iload就是int   lload就是long,接下来我们去除前面的前缀统一用x代替减少篇幅。)

从操作数栈中存回局部变量表 xstore_<n>,xstore(注意有的后面跟了_<n>这是省略了诸如xstore_1,xstore_2这样的指令,xstore默认为xstore_0,之后统一用xstore_<n>替代)

加载一个常量到操作数栈:xipush,xdc,xconst_<n>



运算指令:执行加减乘除取余等运算

加:xadd

减:xsub

乘:xmul

除:xdiv

取余:xrem

取反:xneg

位移:xshl。xshr

按位或指令:xor

按位与指令:xand

按位异或指令:xxor

比较指令:xcmpl



指令上我们大概就讲这么多,接下来就是我们查看字节码的时刻了。首先写一个方法如下:

	public static void main(String[] args) 
		// TODO Auto-generated method stub
		int a = 2;
		int b = 1;
		int c = a+b;
		System.out.println(c);
	


然后我们用javap查看一下字节码



可以看到我们的操作从第01两行来看这事int a =2;的操作,先放置常量2到栈顶然后取出来放到常量表中1的位置。23同样。

而45这两个数字就是把局部变量表上12这两个位置的数加载到操作栈中,然后用6行相加存入常量表3的位置。

为了表明0123和7真的实在存储数字到常量表我们对方法做如下修改:

	public static void main(String[] args) 
		// TODO Auto-generated method stub
		int c = 1+2;
		System.out.println(c);
	
字节码如下

很明显的之前的0123行那种存储的行为没有了,同样我们能看到javac给我们的优化,在第0行把1+2直接变成了3。

以上是关于[jvm解析系列][十三]字节码指令小节,从字节码看JVM的栈解释器执行过程。的主要内容,如果未能解决你的问题,请参考以下文章

[jvm解析系列][十三]字节码指令小节,从字节码看JVM的栈解释器执行过程。

JVM进阶之字节码指令解析(中篇)

[jvm解析系列][十一]字节码执行之栈帧,你的字节码是如何运行的?

JVM进阶之字节码指令解析(上篇)

jvm中篇-05-字节码指令集与解析

JVM进阶之字节码文件解析指令