每天进步一点点!
在第二篇方法调用中,我们主要学习的是确定目标方法,这篇我们就来看看方法内容的具体执行。
目前基于虚拟机的语言中,既有编译执行的(以c,c++为代表),也有解释执行的(比如Python,JavaScript等)。
下面让我们针对java虚拟机简单分析一下这两种执行的区别。
编译执行:编译器将源文件编译成目标机器码文件,运行时不需要重新翻译,下次再运行该文件的时候也无需再次编译。
典型的比如说C语言,由于笔者没有C语言的环境,就不在这里举例子了(我肯定不能说我把学过的C语言知识都还给老师啦,机智!)。
由于编译型语言直接转换成了机器码文件,不再需要编译,这也是为什么说C语言的执行效率比java语言执行效率高的一个原因。
解释执行:不需要编译,每次执行的时候,程序逐行解释成机器语言。
我们以Python语言为例,编写好的.py文件可直接通过python命令运行。
而对于java属于哪一种语言,笔者谈一下个人的见解,java属于混合型的一种语言。
javac.exe可以简单看成是Java编译器,将.java文件编译成Class字节码文件(中间代码)。
java.exe可以简单看成是Java解释器。在java虚拟机中,解释器是JVM的一部分,用来解释执行Java编译器编译后的程序。解释器又将Class字节码文件翻译成机器代码进行解释运行。虽然说多了一步运算影响了效率,但是也正是因为中间代码,达到了跨平台性。
所以很难确切的说java应该属于哪一种类型,朋友们如果感兴趣推荐搜索一下大神RednaxelaFX的文章,由于文章内不让发链接,朋友们要链接的可以私信我。
接下来再介绍一下指令集:
1. 基于寄存器的指令集架构:这是大部分操作系统都采用的方式。
寄存器是CPU的组成部分,可用来暂存指令、数据和地址。
优点是执行速度非常非常快(没有出栈入栈,指令比栈操作少);缺点是受硬件约束。
如果基于寄存器执行1+1的话,可能是:
1. mov eax,1;
2. add eax,1;
2. 基于栈的指令集架构(ISA):java采用的就是这种方式,指令操作都是在操作数栈上进行。
优点:可移植性好,不依赖与操作系统;代码紧凑,编译器实现更加简单;缺点则是执行速度较慢一些。
让我们还是用加法来举例。如下图所示,定义两个方法,执行加法运算。
打开字节码文件查看方法的执行指令,为什么定义了两个方法呢,主要是想看一下,当多定义了一个变量c的时候,字节码指令显示确实是多了一些操作的。
下面让我们简单分析一下add1()方法基于操作数栈的执行过程:
1. ILOAD 1:将局部变量表中第一个slot的整数值复制到数据栈顶。
2. ILOAD 2:将局部变量表中第二个slot的整数值复制到数据栈顶。
3. IADD:将操作数栈中前两个栈顶元素出栈,做整形加法,将结果放到栈顶。
4. ISTORE 3:将栈顶元素出栈并存放到局部变量表中第3个slot中。
下面步骤省略……
不过对于在虚拟机中实际的指令执行过程和文件中的顺序可能不太一样,虚拟机是会对其进行优化的。
喜欢文章或想一起学习的朋友可以关注我,给我点赞,我将会持续更新,有什么疑问或文中有不当之处请给我留言,真诚地希望能与大家一起交流探讨,学习进步!