JVM之前世今生实现讲解
前世今生
虚拟机始祖
虚拟机始祖——Classic/Exact VM
JDK1.0
虚拟机Virtual Machine简称为VM
Classic虚拟机
解释器:代码执行的时候首先得解释为本地机器码(也就是计算机能够认识的机器语言)然后再运行代码,边解释边运行,即使在运行相同的代码也要在进行解释。
即时编译器:将代码直接编译成本地机器码之后再执行,这里面涉及到热点探测功能,只有热点代码(反复执行的代码)才会编译为本地机器码,否则还是会解释执行。热点代码探测这个功能是HotSpot VM中才有的。
这个虚拟机只能使用解释器来执行代码,这种效率特别低下。如果要使用即时编译器只能通过外挂的形式使用,但是用了外挂后虚拟机的执行引擎就会完全由即时编译器接管,解释器将不在工作。
定位对象内存空间时,需要先通过句柄的引用来找到句柄,接着在通过句柄中的对象数据地址来找到真正的堆中的数据,句柄还会保存对象类型数据指向方法区中。
优点:当GC时,对象内存空间发生变化时不需要更新对象的引用,直接将句柄中的引用地址更改即可
缺点:GC频繁,查找需要间接通过句柄来找,速度相当于多了一倍
但是这个虚拟机的即时编译器不能和编译器配合,所以需要对所有的代码都进行编译为本地机器码,而不是之后的只针对热点代码编译为本地机器码这种形式,所以“Java语言很慢”在用户心里树立。
在JDK1.2中与HotSpot VM并存,默认使用该虚拟机;
JDK1.3中默认使用HotSpot VM虚拟机;
JDK1.4退出商用虚拟机舞台。
JDK1.2
Exact VM
新增如下功能:
1.热点探测,两级即时编译器,编译器与解释器混合工作模式
2.准确式内存管理:
准确式内存管理是指虚拟机知道内存中某个位置的数据具体是什么类型。比如是一个指向内存地址的引用还是一个直接能用的值。
举例:
内存中有一个32位的整数123456,它到底是一个reference类型指向123456的内存地址还是一个数值为123456的整数,虚拟机将有能力分辨出来,这样才能在垃圾回收的时候准确判断堆上的数据是否还可能被使用。
特点:摒弃了之前基于句柄的对象查找方式(垃圾收集后对象可能会移动位置也就是地址,虚拟机不知道内存中哪些是引用的这个对象,所以不敢直接将内存中所有这个地址的值都进行替换,所以需要有个句柄来保证引用值的稳定性。即使用句柄来管理对象内存地址的变动,定位对象时先去句柄查下实际的地址再去查找对象本身的属性;也就是通过引用的引用来找这个对象的属性)
优点:体现在垃圾回收的时候,由于能够知道哪些内存是引用类型,所以也能够知道堆上的数据是否还可能被引用。每次定位对象都少了一次查找句柄的开销。
只存在了很短的时间就被HotSpot Vm取代。
HotSpot VM(第一)
特点
1.继承前面两款虚拟机的优点(准确式内存管理)
2.热点代码探测技术:
可以通过执行计数器找出具有编译价值的代码,每个方法都有一个计数器,方法每执行一次计数器都会加一,当计数器达到阈值后,会进行第一次优化成本地代码,之后清空计数器为0,然后再进行计数,如果又达到了阈值则在进行下一步优化,直到方法完全被优化成本地代码。
比如一个方法频繁调用,方法中循环次数很多,然后通知前面提到的即时编译器以方法为单位进行编译成本地机器码。
3.解释器和编译器可配合工作:
程序启动的时候用解释器进行解释运行,当检测到热点代码在进行编译为本地机器码(因为编译比较耗时,所以不能程序启动一上来就进行编译)。
对比Classic VM来说无需等待本地代码全部编译完在进行执行程序。
对比Exact VM来说两者其实都有热点代码检测能力,所以当时Sun公司内部出现过争吵,其实HotSpot打败Exact并不算技术上的胜利~。
天下第二:BEA JRockit/ IBM J9 VM
这两个虚拟机与天下第一的HotSpot VM并称三大商业JAVA虚拟机
BEA JRockit VM
研究方向
专注于服务端应用,因此对于程序启动耗时并不关注,所以去除掉了解释器,完全有编译器全部编译为本地机器码后再进行运行程序。
后续
JRockit因为是BEA System公司的虚拟机,之后被Oracle收购后,已不再继续发展。
IBM J9 VM
研究方向
IBM主力JAVA虚拟机。与HotSpot研究方向接近,考虑服务端,桌面,嵌入式的多用虚拟机
优点
对比HotSpot虚拟机来说,职责分离解耦与模块化更优秀,所以J9抽象出来的核心组件库(垃圾收集器,即时编译器等)单独作为一个项目进行开发。
后续
直至今日依旧活跃,可以作为学习虚拟机技术阅读源码一个好的典范。
专有虚拟机
刚刚说的都是在通用硬件平台上的商用虚拟机,但是还有一类虚拟机与特定的硬件平台,软硬件配合工作的专有虚拟机,代表有以下两个虚拟机:
VEA Liquid VM
简介
BEA公司开发,不需要操作系统支持,自己本身实现了一个专有操作系统的必要功能(线程调度,文件系统,网络等)。好处是跳过了操作系统的一些不必要操作,提升JAVA程序性能
后续
推动硬件能力在开源社区上显得吃力,后续放弃,投入到了Zing中。
Zing
优点
1.新的垃圾收集器:PGC,C4 。轻易支持TB级别的堆内存,暂停时间不超过10毫秒。
对比HotSpot在JDK11和JDK12的ZGC收集器和Sheandoah收集器才能达到,而且远不如C4.
2.ReadyNOW!
该功能利用之前运行时收集到的性能监控数据,引导虚拟机在启动后快速达到高性能水平,减少启动后从解释之心到即时编译的等待时间。
3.ZVusuib/ZVRobot
方便用户监控虚拟机运行状态,找出代码热点,对象分配监控,锁竞争监控等。