JVM设计原理与实现——虚拟机概述

        最近小编正在读《揭秘java虚拟机 JVM设计原理与实现》,顺便总结一下成一个系列记录一下读书的历程吧(挺厚的一本书,怕读不完)!


一、来源


        其实这个问题应该从编程语言的始祖说起,我们都知道,在计算机出现的初期,程序员们都是用纯机器语言+打孔纸带进行编程操作的,不同型号的机器还有不同纸带上面打点的规律都是不一样的,然后这样人们为了解决机器语言繁琐的问题,就发明了汇编语言,从汇编的角度再来看编程的话,就比较容易多了,但是还是不怎么符合人们的思维习惯,所以,人们又在汇编的基础上发明了一系列的高级语言,C,C++ 等等语言,都在这个时候并发出来,但是这个时候会有一个问题,在不同的机器上,不同的操作系统上,我们写的程序,调用的API都是不同的,也就是说跨操作系统或者硬件的编程是需要很大的学习成本的,这个时候我们的java编程语言的作者——“詹姆斯·高斯林”,也就是詹爷,就想我们能不能开发一种不需要根据运行环境不同而进行不同编码的语言呢,做到“write onece , run anywhere”,于是这个JVM的核心思想就诞生了。

      简单说:

       发展史:机器生汇编,汇编生B,B生C,C生万物

       詹爷理念: 1、“write onece , run anywhere”

                          2、简单的,才是最美的:开发者只需要关注功能实现,不需要关注底层细节


二、JVM原理简述


           其实说道JVM的原理,还要从一般语言的书写,编译,再到运行说起。一般的语言,比如C/C++等语言,在程序编写好后,经过编译,就可以成为机器码这样的可以直接被硬件操作的程序了,但是我们都知道,不同底层的硬件对于机器码的解析也是不同的,所以当我们的程序想要在另外一个机器上运行的时候需要进行API重新调用,或者是重新进行编译。

          java为了实现不用重新编译这个复杂的过程,所以在实现编译的时候进行了一个省略,就是在编译的时候不直接翻译成机器码,而是要翻译成一个中间语言,为字节码,这个时候我们的主角就登场了,我们在不同的系统,上都安装上JVM ,然后他负责去解析字节码,然后把字节码写成机器码,这样就可以被宿主机器去运行了。

         但是要是这么说下去,java在jvm解析的时候又多了一层,岂不是要运行的更慢了吗?

         其实在java和jvm的初期(初版)就是这样的,因为运行缓慢而成为java的一大诟病,然后当时人们很少用java来进行开发。但是java的开发者们却不是这么想的,因为这是跨时代的一个想法,一个创意,所以java的开发者们用尽他们的技术和经验,经过重重优化,才把java语言,还有JVM优化到和C/C++持平,甚至有的时候可以通过人为对于JVM进行调控,从而让他适应运行环境而比C/C++更加的高效。但是具体是什么样的技术呢?

         

        关键技术:直译机器码

        要解释这个技术还得从第一代jvm说起,那是一个月黑风高的夜晚,詹爷灵机一动,想到了用字节码来当做中间码进行编译,但是这个时候有个问题,我们要如何编写JVM,实现字节码到机器码的转换呢?于是很自然的想到了强大的C语言作为支柱,通过把字节码变为C ,在对C语言进行编译,这样就可以了。然后。。。。这样虽然是实现了,但是由于字节码到C的转化就会生成一个比较多的C代码,然后C到机器码之间又需要通过汇编来转化,所以到了机器码的时候不仅仅是过程缓慢,运行也是很慢的。

        这个时候,再怎么优化也是不行的了。于是詹爷就拿出了真本事,让字节码直接翻译成机器码,因为翻译成中间的任何一种语言都太费事了。

        我们都知道CPU在执行代码的时候,是通过CS(段地址寄存器)和IP(偏移地址寄存器)两个寄存器,我们通过CS:IP这样的地址形式就可以找到目标程序的位置,我们的程序执行和各种调用也是这样产生的。因为C语言和汇编都可以直接去修改CS和IP的指向,把这种修改规则叫做语法糖。通过这个语法糖,我们可以把我们的程序执行指向一个特定的已经写好的机器语言的存储空间上去,这就是直译机器码的核心。具体就是我们可以把中间语言直接指向一个机器代码,通过C语言的语法糖直接指向这些机器码的地方进行程序的执行。这里书上举出的C语言的例子看的不是很懂,先把代码留空吧,等懂了就补上:“C!”


       这种方式堪称神器,在编程时代的初期,很多大牛用这种方式实现了很多匪夷所思的功能,才有了我们现在这个多彩斑斓的程序世界。詹爷正是用了这个神器,才是的java语言的运行速度变得更快,使他的性能得的很大的提高,在某种程度上可以赶上C/C++了。为什么能赶上C和C++呢,因为我们可以在程序运行期间对JVM进行一些优化和调整,然而C和C++的程序在编译之后就是固定的机器码了,所以不能实时的进行优化,所以在优化上使用JVM的java是无可比拟的。

        这里还要说一点,由于JVM中的java的指令集是用8位二进制进行描述的,总共的指令数量不超过255种,所以我们学习也好,程序进行编译也好都不是什么难事。但是就是这么简单的指令集,却有着很强的适应性,这里我们在后续的读书中会遇到。


        简单说:java——字节码(中间语言)——jvm解析——机器码

        JVM层有C语言参与,并且可以动态的执行解析的机器码。

         存在的问题:字节码到机器码     与      C语言到机器码     之间有着机器码数量级的区别。解决办法:对于热点代码进行指令优化。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 26
    评论
实现一个JVM虚拟机,需要深入了解JVM的内部实现原理和Java语言规范。一般来说,JVM虚拟机由以下几个模块组成: 1. 类加载器:负责从文件系统、网络或其他来源加载Java类文件,并将其转换为JVM能够理解的格式。 2. 运行时数据区:Java程序运行时需要的内存空间,包括Java堆、方法区、虚拟机栈、本地方法栈、程序计数器等。 3. 执行引擎:负责执行Java字节码,将它们转换为机器码并执行。 4. 垃圾收集器:负责回收未使用的对象,释放内存空间。 5. 本地方法接口:允许Java代码调用本地方法(C/C++代码)。 下面是一个简单的Java虚拟机实现的示例: ```java public class JVM { private ClassLoader classLoader; private RuntimeDataArea runtimeDataArea; private ExecutionEngine executionEngine; private GarbageCollector garbageCollector; private NativeMethodInterface nativeMethodInterface; public JVM() { classLoader = new ClassLoader(); runtimeDataArea = new RuntimeDataArea(); executionEngine = new ExecutionEngine(); garbageCollector = new GarbageCollector(); nativeMethodInterface = new NativeMethodInterface(); } public void run(String className) { // 加载类 Class clazz = classLoader.loadClass(className); // 初始化类 clazz.initialize(runtimeDataArea); // 执行方法 Method mainMethod = clazz.getMethod("main", String[].class); executionEngine.execute(mainMethod); } } ``` 这个简单的JVM实现只包含了类加载器、运行时数据区和执行引擎三个部分。在实现时,还需要考虑Java语言规范中的各种细节,如异常处理、线程安全等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值