java开发C语言编译器: JVM的基本原理
来源:互联网 发布:手机淘宝上如何开网店 编辑:程序博客网 时间:2024/05/19 00:54
更详细的讲解和代码调试演示过程,请参看视频
用java开发C语言编译器
如果你对机器学习感兴趣,请参看一下链接:
机器学习:神经网络导论
上一节,我们把C语言编译成了可以被java虚拟机加载执行的java汇编语言。这节,我们就jvm的基本机制进行深入了解,如果不理解java虚拟机的体系结构,那么我们不可能把C语言转换成能顺利在虚拟机上执行的字节码。
把握java虚拟机,必须把握一点,那就是java虚拟机的运行是以栈为基础的。理解了这点,对jvm的理解就掌握了一大半。java程序运行时,当某个函数被调用是,jvm会创建一个执行环境,这个环境叫stack frame, 这个环境有三个需要理解的要点,第一是,stack frame 含有一个执行堆栈,任何指令的执行,都会围绕这个堆栈来进行。第二是局部变量数组,函数的输入参数和局部变量就存储在这个数组中。第三个是指令指针PC,它指向下一条要执行的指令。
举个例子,假设java 代码中有一个函数:
int f(int a, int b) { return a+b;}
上面代码编译后,jvm会产生的stack frame 如下:
stack:
local_array: a, b
PC-> 把变量a 从local_array 取出,然后压入堆栈
把变量b 从local_array 取出,然后压入堆栈
把堆栈顶部两个元素弹出后相加,把结果压入堆栈
把堆栈顶部的元素弹出后返回。
假设函数的调用方式为 f(1,2) 那么stack frame 形式如下:
stack:
local_array: 1, 2
PC-> 把变量a 从local_array 取出,然后压入堆栈
把变量b 从local_array 取出,然后压入堆栈
把堆栈顶部两个元素弹出后相加,把结果压入堆栈
把堆栈顶部的元素弹出后返回。
执行第一条语句后,stack frame 如下:
stack: 1
local_array: 2
把变量a 从local_array 取出,然后压入堆栈
PC-> 把变量b 从local_array 取出,然后压入堆栈
把堆栈顶部两个元素弹出后相加,把结果压入堆栈
把堆栈顶部的元素弹出后返回。
继续执行当前PC指针指向的语句后,情况如下:
stack: 2, 1
local_array:
把变量a 从local_array 取出,然后压入堆栈
把变量b 从local_array 取出,然后压入堆栈
PC-> 把堆栈顶部两个元素弹出后相加,把结果压入堆栈
把堆栈顶部的元素弹出后返回。
继续执行后情况如下:
stack: 3
local_array:
把变量a 从local_array 取出,然后压入堆栈
把变量b 从local_array 取出,然后压入堆栈
把堆栈顶部两个元素弹出后相加,把结果压入堆栈
PC-> 把堆栈顶部的元素弹出后返回。
依次类推。
你可以看到,java指令运行时,必须确保指令需要的参数全部放在栈上,指令执行后如果有结果,结果也同样会存在在堆栈上。
有了上面的基本理论,我们可以看看上一节程序生成的java汇编代码:
.class public CSourceToJava.super java/lang/Object.method public static main([Ljava/lang/String;)V getstatic java/lang/System/out Ljava/io/PrintStream; ldc "Hello java virtual machine!" invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V return.end method.end class
指令getstatic 的作用就是把out对象压入前面所说的堆栈中。ldc 的作用是把字符串压入到前面所说的堆栈中,这两句执行后,堆栈情况如下:
stack:
“Hello java virtual machine!”
out
invokevirtual 指令执行时,它会从堆栈顶部取出两个元素,接着从第二个元素,也就是out对象中,找到要调用的方法,也就是println, 然后把堆栈第一个元素作为参数,调用println方法,执行完毕后,如果有返回值,则把返回值给压入堆栈。
理解了指令的执行原理后,其他语句完全可以跟下面的代码对应起来:
public class CSourceToJava { public static void main(String[] args) { System.out.println("Hello java virtual machine!"); }}
由此语句.class public CSourceToJava对应的就是java代码中类的声明部分:
public class CSourceToJava, 指令.method public static main 对应的就是静态函数main 的声明:public static void main。
语句Ljava/io/PrintStream; 表示对象的类型,例如对象out 的类型是java.io.PrintStream。前面的L表示该对象是一个类,如果前面还有一个左中括号,那表示该对象是一个数组,例如[Ljava/lang/String; 表示的是String[].
更详实讲解请参看视频。
更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:
- java开发C语言编译器: JVM的基本原理
- java开发C语言编译器:jvm的return指令以及局部变量的操作
- java开发C语言编译器:JVM 的基本操作指令介绍及其程序运行原理
- java开发C语言编译器:把C实现的快速排序算法编译成jvm字节码
- java开发编译器:自底向上语法解析的基本原理
- java开发C语言编译器:把C语言的数组操作转换成java字节码
- java开发C编译器:jvm函数调用时的参数传递
- java开发C语言编译器:把printf编译成java字节码的算法详解
- java开发编译器:把C语言的循环指令编译成java字节码
- C语言的编译器
- java开发编译器:C语言逻辑控制语句if else if 的语法解析
- java开发C语言编译器: return 语句的解释和执行
- 使用Lex和Yacc开发C语言的编译器
- 使用Lex和Yacc开发C语言的编译器
- 使用Lex和Yacc开发C语言的编译器
- 编译器开发:C语言循环控制语句的解析
- java开发C语言编译器:为C语言提供API调用
- C语言编译器的错误信息
- linux服务器 shell脚本 编写定时器
- java实现我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
- Approaching (Almost) Any Machine Learning Problem
- C++:字符串分割
- 解决微信界面返回问题
- java开发C语言编译器: JVM的基本原理
- 初识Celery
- java实现在Excel2003中,用A表示第一列,B表示第二列...Z表示第26列,AA表示第27列,AB表示第28列...依次列推。请写出一个函数, 输入用字母表示的列号编码,输出它是第几列
- 平安7年精益敏捷转型之路
- [李景山php] 深入理解PHP内核[读书笔记]--第三章:变量及数据类型--变量的结构和类型--PHP的哈希实现
- \n \r\n \t的区别
- java实现输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
- int main(int argc, char* argv[])理解
- Java中处理二进制移位