JVM基础系列第2讲:Java 虚拟机的历史
说起 Java 虚拟机,许多人就会将其与 HotSpot 虚拟机等同看待。但实际上 Java 虚拟机除了 HotSpot 之外,还有 Sun Classic VM、Exact VM、BEA JRocketit、IBM J9 等等。今天我们就来简单回顾下 Java 虚拟机的发展历史。
虚拟机始祖:Sun Classic
在 1996 年 1 月 23 日,Sun 发布 JDK 1.0,其中自带的虚拟机就是 Classic VM。但这款虚拟机有个特点,即只能使用纯解释器的方式来执行 Java 代码,如果要使用 JIT 编译器那就必须使用外挂。
tips: 执行代码可以分为编译执行和解释执行。解释执行指的是边解释边运行代码。编译执行指的是先编译,后执行。
但如果外挂了 JIT 编译器,那么 JIT 编译器就完全替代了虚拟机的执行系统,解释器便不再工作了。简单地说,在 Sun Classic 虚拟机中,解释器与编译器无法共同存在。
而且即使使用了外挂 JIT 编译器,Sun Classic 虚拟机的执行速度也快不起来。因为解释器无法和编译器配合工作,虚拟机无法判断哪个方法是使用频率高,所以它只能对每个方法都进行编译。这就导致了虚拟机只能采取相对简单的优化技术,无法进行耗时稍微较高的优化技术。因为如果对所有代码都采用耗时高的优化技术,那么编译时间会慢得无法接受。
虽然 Sun Classic 虚拟机有这样那样的问题,但其生命力还是非常旺盛的。在 JDK 1.3 之前,其一直是 JDK 的默认虚拟机。而在 JDK 1.3 时,HotSpot 成为默认虚拟机,其作为备用虚拟机存在。到了 JDK 1.4 时,其正式退出历史舞台。可以说 Sun Classic 还是存在了将近四年的时间,但另外一个虚拟机可就没有那么好的运气了。
无疾而终:Sun Exact VM
在 Sun Classic 发布后,Sun 的虚拟机团队在 JDK 1.2 时 发布了一款名为 Exact VM 的虚拟机,尝试解决 Classic VM 遇到的所有问题。它的执行系统解决了 Classic VM 存在的解释器和编译器无法同时工作的问题,还具备了一些现代高性能处理器的特性,如:两级即时编译等。
除此之外,Exact VM 还改进了虚拟机的对象查找方式。在 Classic VM 中,如果要查找一个对象,那么需要通过句柄(类似指针)来查找。如果需要查找一个对象,那么需要通过其构建成的句柄树一层层寻找。但在 Exact VM 中使用了准确式内存管理(Exact Memory Management),即虚拟机可以知道内存中某个位置的数据具体是什么类型,这样就减少了查找的的开销,提升执行性能。
但可惜的是,虽然 ExactVM 发布了,但一直到它退出时,其都没有真正被大规模使用过。在 JDK 1.2 其发布时,Exact VM 推出,但Sun Classic VM 依然作为默认的 Java 虚拟机。在 JDK 1.3 发布时,推出虚拟机 HotSpot VM 作为默认虚拟机,而 Sun Classic VM 作为备用虚拟机。
武林盟主:Sun HotSpot VM
HotSpot VM 可以说是使用最为广泛的 Java 虚拟机,几乎所有的 Java 虚拟机都知道它。但实际上,这个虚拟机并不是由 Sun 公司原生开发的,而是由一个叫 Longview Technologies 公司开发的。而 Sun 公司注意到了这款虚拟机在 JIT 编译上的许多优秀成果,于 1997 年收购了 Longview Technologies 公司,从而获得了 HotSpot VM。
要说 HotSpot 不仅仅有前面说到两款虚拟机的优点(如:准确式内存管理),也有许多自己的新技术,例如:热点探测技术。热点探测技术指的是通过执行计数器找出最具优化价值的代码,然后通知 JIT 编译器以方法为单位进行深度优化编译。但其实 Exact VM 中也有类似的技术,Sun 公司内部还因此大吵了一架,但最终还是选择了 HotSpot 作为默认的虚拟机,其中的缘由不得而知。
总的来说,从 2000 年 JDK 1.3 发布,HotSpot VM 作为默认的虚拟机开始登上历史舞台。到现在 2018 年,18 年时间过去了,其依然是我们最常用的虚拟机,可见 Sun HotSpot VM 的生命力之顽强。
百家争鸣:BEA JRockit / IBM J9 VM
前面说的都是 Sun 公司推出的虚拟机,但除了 Sun 公司之外,其他组织、公司也研发过不少的虚拟机实现,其中最著名的要算 BEA 公司的 BEA JRockit 和 IBM 公司的 J9 VM 了。
BEA 公司的 JRockit 是一款专注于服务器硬件和服务端应用场景的虚拟机,其针对服务端场景做了大量的优化,因此其不太关注程序启动速度。JRockit 虚拟机内部不包含解释器实现,全部代码都靠即时编译器编译后执行。此外,其提供的 MissionControl 服务套件也十分强大。
IBM 公司的 J9 VM 则是一款比较通用的虚拟机,其定位应用于从服务端到桌面应用再到嵌入式的多用途虚拟机。IBM 公司开发 J9 VM 的目的是将其作为 IBM 公司各种 Java 产品的执行平台。
武林外传:那些无名虚拟机
从 Sun Classic、Sun Exact VM、Sun HotSpot VM,再到 BEA JRockit、IBM J9 VM,这几个虚拟机可以说是虚拟机的正史了,是每个 Java 程序员应该了解的。但在这之外,其实还有各种各样的虚拟机存在。
例如性能最强悍的并不是上面所说的虚拟机,而是名为 Azul VM 和 BEA Liquid VM 的专用商业及虚拟机。这些虚拟机只运行在特定硬件平台,因此要求比较高。但其性能也是非常强悍的。其可以管理至少数十个 CPU 和数百 GB 的内存资源,还提供在巨大内存范围内实现可控 GC 时间的垃圾收集器等等。
此外还有许许多多其他的虚拟机存在,例如:Apache Harmony、Google Android Dalvik VM、Mircosoft JVM 等等。
最后的赢家:Oracle
看了这么些历史,似乎都是在说 Sun公司发布的虚拟机,与 Oracle 似乎没有什么关系。但在 2010 年,Oracle 公司收购了 Sun 公司,这样 Oracle 就拥有了 HotSpot VM。再加上其在 2008 年收购 BEA 公司获得的 JRocket VM,Oracle 公司就拥有了地球上最优秀的两款虚拟机。
对于虚拟机未来的规划,Oracle 宣布会将 JRockit 的优秀特性整合到 HotSpot VM 中,例如移植 JRockit 的垃圾回收器和 MissionControl 服务。
附录:Java 虚拟机历史
JDK 版本升级不仅仅体现在语言和功能特性上,还包括了其编译和执行的 Java 虚拟机的升级。
- 1996 年,JDK 1.0 发布时,提供了纯解释执行的 Java 虚拟机实现:Sun Classic VM。
- 1997 年,JDK 1.1 发布时,虚拟机没有做变更,依然使用 Sun Classic VM 作为默认的虚拟机。
- 1998 年,JDK 1.2 发布时,提供了运行在 Solaris 平台的 Exact VM 虚拟机,但此时还是用 Sun Classic VM 作为默认的 Java 虚拟机。
- 2000 年,JDK1.3 发布,默认的 Java 虚拟机由 Sun Classic VM 改为 Sun HotSopt VM,而 Sun Classic VM 则作为备用虚拟机。
- 2002 年,JDK 1.4 发布,Sun Classic VM 退出商用虚拟机舞台,直接使用 Sun HotSpot VM 作为默认虚拟机一直到现在。
参考资料
如果只是看,其实无法真正学会知识的。为了帮助大家更好地学习,我建了一个虚拟机群,专门讨论学习 Java 虚拟机方面的内容,每周针对我所发文章进行讨论答疑。如果你有兴趣,关注「Java技术精选」公众号,通过右下角菜单「入群交流」加我好友,小助手会拉你入群。
JVM基础系列文章目录
- JVM基础系列开篇:为什么要学虚拟机?
- JVM基础系列第1讲:Java 语言的前世今生
- JVM基础系列第2讲:Java 虚拟机的历史
- JVM基础系列第3讲:到底什么是虚拟机?
- JVM基础系列第4讲:从源代码到机器码,发生了什么?
- JVM基础系列第5讲:字节码文件结构
- JVM基础系列第6讲:Java虚拟机内存结构
- JVM基础系列第7讲:JVM类加载机制
- JVM基础系列第8讲:JVM 垃圾回收机制
- JVM基础系列第9讲:JVM垃圾回收器
- JVM基础系列第10讲:垃圾回收的几种类型
- JVM基础系列第11讲:JVM参数之堆栈空间配置
- JVM基础系列第12讲:JVM参数之查看JVM参数
- JVM基础系列第13讲:JVM参数之追踪类信息
- JVM基础系列第14讲:JVM参数之GC日志配置
- JVM基础系列第15讲:JDK性能监控命令
JVM基础系列第2讲:Java 虚拟机的历史的更多相关文章
- JVM基础系列第6讲:Java 虚拟机内存结构
看到这里,我相信大家对于一个 Java 源文件是如何变成字节码文件,以及字节码文件的含义已经非常清楚了.那么接下来就是让 Java 虚拟机运行字节码文件,从而得出我们最终想要的结果了.在这个过程中,J ...
- JVM基础系列第3讲:到底什么是虚拟机?
我们都知道在 Windows 系统上一个软件包装包是 exe 后缀的,而这个软件包在苹果的 Mac OSX 系统上是无法安装的.类似地,Mac OSX 系统上软件安装包则是 dmg 后缀,同样无法在 ...
- JVM基础系列第1讲:Java 语言的前世今生
Java 语言是一门存在了 20 多年的语言,其年纪比我自己还大.虽然存在了这么长时间,但 Java 至今都是最大的工业级语言,许多大型互联网公司均采用 Java 来实现其业务系统.大到国际电商巨头阿 ...
- JVM基础系列第15讲:JDK性能监控命令
查看虚拟机进程:jps 命令 jps 命令可以列出所有的 Java 进程.如果 jps 不加任何参数,可以列出 Java 程序的进程 ID 以及 Main 函数短名称,如下所示. $ jps 6540 ...
- JVM基础系列第14讲:JVM参数之GC日志配置
说到 Java 虚拟机,不得不提的就是 Java 虚拟机的 GC(Garbage Collection)日志.而对于 GC 日志,我们不仅要学会看懂,而且要学会如何设置对应的 GC 日志参数.今天就让 ...
- JVM基础系列第13讲:JVM参数之追踪类信息
我们都知道 JVM 在启动的时候会去加载类信息,那么我们怎么得知他加载了哪些类,又卸载了哪些类呢?我们这一节就来介绍四个 JVM 参数,使用它们我们就可以清晰地知道 JVM 的类加载信息. 为了方便演 ...
- JVM基础系列第11讲:JVM参数之堆栈空间配置
JVM 中最重要的一部分就是堆空间了,基本上大多数的线上 JVM 问题都是因为堆空间造成的 OutOfMemoryError.因此掌握 JVM 关于堆空间的参数配置对于排查线上问题非常重要. tips ...
- JVM基础系列第10讲:垃圾回收的几种类型
我们经常会听到许多垃圾回收的术语,例如:Minor GC.Major GC.Young GC.Old GC.Full GC.Stop-The-World 等.但这些 GC 术语到底指的是什么,它们之间 ...
- JVM基础系列第9讲:JVM垃圾回收器
前面文章中,我们介绍了 Java 虚拟机的内存结构,Java 虚拟机的垃圾回收机制,那么这篇文章我们说说具体执行垃圾回收的垃圾回收器. 总的来说,Java 虚拟机的垃圾回收器可以分为四大类别:串行回收 ...
随机推荐
- ASP.NET MVC 执行流程介绍
Routing 组件 Controller Controller中可用的ActionResult MVC-View(使用的抽象工厂模式的视图引擎) 视图模型
- excel导出使用get请求参数过长问题
遇到的问题: excel导出功能时,使用的是window.location.href=url也就是get请求.当传入参数过长的时候就报了414,地址过长的错误. 解决思路: 将get请求换为post请 ...
- C++ 初读vector
vector 向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container).跟任意其它类型容器一样,它能够存放各种类型的对象. Character 高效 C++标准要 ...
- JSTree如何实现第二级菜单异步从数据库读取。
参考文档: https://www.cnblogs.com/luozhihao/p/4679050.html http://jsfiddle.net/vakata/2kwkh2uL/5/ 核心的关键点 ...
- mysql_Navicat数据库破解
Navicat Premium 12.1.16.0安装与激活 Navicat Premium 12是一套数据库开发管理工具,支持连接 MySQL.Oracle等多种数据库,可以快速轻松地创建.管理和维 ...
- 动态规划-LIS
https://vjudge.net/contest/297216?tdsourcetag=s_pctim_aiomsg#problem/E #include<bits/stdc++.h> ...
- Win10上安装Python3.7-64bit
参考https://docs.opencv.org/4.1.0/d5/de5/tutorial_py_setup_in_windows.html 方法一:到官网上https://www.python. ...
- Linux 系统中的内部与外部命令
linux中的命令大致可分为两类,内部命令和外部命令: 内部命令(builtin command):也称shell内嵌命令 外部命令(external command):存放在一个文件中,使用时需要去 ...
- swust oj 1051
输出利用先序遍历创建的二叉树中的指定结点的孩子结点 1000(ms) 10000(kb) 2432 / 5430 利用先序递归遍历算法创建二叉树并输出该二叉树中指定结点的儿子结点.约定二叉树结点数据为 ...
- 格式化数据保留两位小数,输入格式为 :xxx,xx,,,,x,,(x为浮点数)
/** * 格式化字符串 */ static String dataFormat(String data){ String formatedData = ""; // 浮点数正则表 ...