JVM与Java体系结构
本文整理自尚硅谷宋红康老师在B站的视频,侵权即删。
本文的思维导图如下:
1 Java及JVM简介
Java是一门跨平台的计算机编程语言,通过使用Java虚拟机,实现在不同硬件和操作系统下的“write once, run anywhere(一次编译,到处运行)”。
同时,随着JVM的发展,它已经成为一个跨语言的平台:
- 随着Java7的正式发布,通过JsR-292规范,基本实现在Java虚拟机平台上运行非Java语言编写的程序。
- Java虚拟机根本不关心运行在其内部的程序到底是使用何种编程语言编写的,它只关心“字节码”文件,也就是说, Java虚拟机拥有语言无关性,并不会单纯地与Java语言“终身绑定”,只要其他编程语言的编译结果满足并包含Java虚拟机的内部指令集、符号表以及其他的辅助信息,它就是一个有效的字节码文件,就能够被虚拟机所识别并装载运行。
以上提到的“字节码”文件:
- 我们平时说的Java字节码,指的是用Java语言编译成的字节码。准确的说,任何能在JVM平台上执行的字节码格式都是一样的,所以应该统称为JVM字节码。
- 不同的编译器,可以编译出相同的字节码文件,字节码文件也可以在不同的JWM上运行。
- Java虚拟机与Java语言没有必然的联系,它只与Class文件格式所关联——一种特定的二进制文件格式,其中包含Java虚拟机指令集(或者称为字节码、 Bytecodes)和符号表,以及一些其他的辅助信息。
2 Java发展的重大事件
Java语言已经走过了20多年,以下是发展过程中的一些重大事件,仅作了解:
- 1990年,在Sun计算机公司中,由 Patrick Naughton、 Mikesheridan及James Gosling领导的小组Green Team,开发出的新的程序语言,命名为Oak,后期命名为
Java
。 - 1995年,Sun正式发布Java和 HotJava产品,Java首次公开亮相。
- 1996年1月23日,Sun Microsystems发布了JDK1.0。
- 1998年,JDK1.2版本发布。同时,Sun发布了JSP/servlet、EJB规范,以及将Java分成了J2EE、J2SE和J2ME,表明Java开始向企业、桌面应用和移动设备应用三大领域挺进。
- 2000年,JDK1.3发布,
Java HotSpot Virtual Machine(JVM)
正式发布,成为Java的默认虚拟机。 - 2002年,JDK1.4发布,古老的Classic虚拟机退出历史舞台。
- 2003年,Java平台的scala式发布,同年,Groovy也加入Java阵营。
- 2004年,JDK1.5发布,同时JDK1.5改名为JavaSE5.0。
- 2006年,JDK6发布。同年,Java开源并建立了
OpenJDK
,Hotspot虚拟机也成为OpenJDK中的默认虚拟机。 - 2007年,Java平台迎来新伙伴
Clojure
。 - 2008年,Oracle收购了BEA,得到了
JRockit虚拟机
。 - 2010年, Oracle收购Sun,获得Java商标和最具价值的 HotSpot虚拟机。此时, Oracle拥有市场占用率最高的两款虚拟机 HotSpot和JRockit,并计划在未来对它们进行整合:HotRockit
- 2011年,JDK7发布。在JDK1.7中,正式启用了新的
垃圾回收器G1
。 - 2017年,JDK9发布。将G1设置为默认GC,替代CMS。同年,IBM的J9开源,形成了现在的 Open J9社区。
- 2018年, Android的Java侵权案判决, Google赔偿 Oracle计88亿美元同年, Oracle宣告 javaEE成为历史名词,JDBC、JMS、Servlet赠予Eclipse基金会。
- 同年,JDK11发布,LTS版本的JDK,发布革命性的
ZGC垃圾回收器
,调整JDK授权许可。 - 2019年,JDK12发布,加入Redhat领导开发的
Shenandoah GC
。
3 虚拟机与Java虚拟机
3.1 虚拟机
所谓虚拟机( Virtual Machine)
,就是一台虚拟的计算机,它是一款软件,用于执行一系列虚拟计算机指令。大体上,虚拟机可以分为系统虚拟机
和程序虚拟机
。
- 常用的Visual Box,VMware等属于系统虚拟机,它们完全是对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台。
- 程序虚拟机的典型代表是Java虚拟机,它专门为执行单个计算机程序而设计,在Java虚拟机中执行的指令被称为
Java字节码指令
。
无论是系统虚拟机还是程序虚拟机,在虚拟机中运行的软件都被限制于虚拟机提供的资源中。
3.2 Java虚拟机
Java虚拟机
是一台执行Java字节码的虚拟计算机,拥有独立的运行机制,其运行的Java字节码可能由Java语言编译而成,也可能由其他语言编译而成。
JVM平台的各种语言可以共享Java虚拟机带来的跨平台性、优秀的垃圾回收器,以及可靠的即时编译器。
JVM的特点:
- 一次编译,到处运行
- 自动内存管理,包括:
- 内存的自动分配
- 垃圾的自动回收
前面提到,JVM属于程序虚拟机,所以JVM运行于操作系统之上,与硬件没有直接交互:
4 JVM的整体结构
HotSpot虚拟机是目前市面上高性能虚拟机的代表之一,主要包括类加载子系统、运行时数据区和执行引擎等,执行引擎采用解释器与即时编译器并行存的架构,运行速度可与C/C++一较高下。整体结构如下:
5 Java代码的执行流程
Java代码的执行流程如下:
- 源码文件经过编译(前端编译)生成字节码文件
- 字节码文件加载到JVM并执行,有可能解释执行,也可能编译执行(后端编译)
6 JVM的架构模型
Java编译器输入的指令基木上是基于栈的指令集架构
,另外一种常见的指令集架构是基于寄存器的指令集架构
。
两种架构之间的区别:
基于栈式架构的特点:
- 设计和实现更简单,适用于资源受限的系统;
- 避开了寄存器的分配难题:使用零地址指令方式分配;
- 指令流中的指令大部分是
零地址指令
,其执行过程依赖于操作栈,指令集更小
,编译器容易实现,但完成一项操作需要更多的指令
; - 不需要硬件支持,可移植性更好,更好实现跨平台。
基于寄存器架构的特点:
- 典型的应用是x86的二进制指令集:比如传统的PC以及Android的Davlik虚拟机;
- 指令集架构完全依赖硬件,可移植性差;
- 性能优秀,执行更高效;花费更少的指令去完成一项操作;
- 在大部分情况下,基于寄存器架构的指令集往往以一地址指令、二地址指令和三地址指令为主,而基于栈式架构的指令集以零地址指令为主。
以下例子简单说明两种指令集架构的区别:
执行2+3
的操作,指令分别如下:
基于栈的指令集架构的计算流程(以Java虚拟机为例):
iconst_2 //常量2入栈
istore_1
iconst_3 //常量3入栈
istore_2
iload_1
iload_2
iadd //常量2、3出栈,执行相加
istore_0 //结果5入栈
基于寄存器的指令集架构的计算流程:
mov eax,2 //将eax寄存器的值设为2
add eax,3 //使eax寄存器的值加3
总结:
由于跨平台
的设计,而不同平台的CPU架构不同,所以Java的指令不能设计为基于寄存器的,而是根据栈来设计的。此种设计的优点是跨平台,指令集小,编译器实现容易;缺点是性能下降,实现同样的功能需要更多的指令。
7 JVM的生命周期
JVM的生命周期主要分为启动、执行和退出三个阶段:
- 启动
- Java虚拟机的启动是通过
引导类加载器(bootstrap classloader)
创建一个初始类(initial Class)
来完成的,这个类是由虚拟机的具体实现指定的。
- Java虚拟机的启动是通过
- 执行
- 一个运行中的Java虚拟机有一个清晰的任务:执行Java程序;
- 程序开始执行时它才运行,程序结束时它就停止;
- 执行一个Java程序的时候,真正在执行的是一个叫做
Java虚拟机的进程
。
- 退出,有如下几种情况:
- 程序正常执行结束
- 程序在执行过程中遇到异常或错误,由此非正常终止
- 由于操作系统出现错误,导致Java虚拟机进程终止
- 某线程调用 Runtime类或 System类的exit方法,或 Runtime类的ha1t方法,并且Java安全管理器也允许这次exit或halt操作
- JNI( Java Native interface)规范描述了:用JNI Invocation API来加载或卸载Java虚拟机时,Java虚拟机的退岀情况
8 JVM发展历程
下面介绍JVM发展历程中的几款具体的虚拟机,仅作了解:
8.1 Sun Classic VM
- 早在1996年Java1.0版本的时候,Sun公司发布了一款名为
Sun classic VM
的Java虚拟机,同时也是世界上第一款商用Java虚拟机
,JDK1.4时被完全淘汰。 - Sun Classic VM内部只提供解释器。
- 如果使用JIT编译器,需要进行外挂;而且一旦使用了JIT编译器,JIT就会接管虚拟机的执行系统,解释器就不再工作,即解释器和编译器不能配合工作。现在hotspot内置了此虚拟机。
8.2 SUN公司的HotSpot VM
- HotSpot历史
- 最初由一家名为“ Longview Technologies"的小公司设计
- 1997年,此公司被sun收购;2009年,sun公司被甲骨文收购
- JDK1.3时, Hotspot VM成为默认虚拟机
- 目前Hotspot占有绝对的市场地位
- 不管是现在仍在广泛使用的JDK6,还是使用比例较多的JDK8中,默认的虚拟机都是Hotspot
- Sun/oracle JDK和Open JDK的默认虚拟机
- 从服务器、桌面到移动端、嵌入式都有应用
- 名称中的Hotspot指的是它的热点代码探测技术
- 通过计数器找到最具编译价值代码,触发即时编译或栈上替换
- 通过编译器与解释器协同工作,在最优化的程序响应时间与最佳执行性能中取得平衡
8.3 BEA公司的JRockit
- 专注于服务器端应用
- 它不太关注程序的启动速度,因此JRockit内部不包含解析器实现,全部代码都通过即时编译器编译后执行
- 大量的行业基准测试显示, JRockit JVM是
世界上最快的JVM
- 使用 JRockit产品,客户已经体验到了显著的性能提高(一些超过了70%)和硬件成木的减少(达50%)
- 优势:全面的Java运行时解决方案组合
- JRockit面向延迟敏感型应用的解决方案 jRockit Rea1Time提供毫秒或微秒级的JVM响应时间,适合财务、军事指挥、电信网络的需要
- MissionControl服务套件,它是一组以极低的开销来监控、管理和分析生产环境中的应用程序的工具
- 2008年,BEA被Oracle收购
- Oracle整合了两大优秀虚拟机的工作,大致在JDK8中完成,整合方式是在Hotspot的基础上,移植JRockit的优秀特性
8.4 IBM公司的J9
- 全称:IBM Technology for Java Virtual Machine,简称IT4J,内部代号:J9
- 市场定位与 HotSpot接近,服务器端、桌面应用、嵌入式等多用途VM
- 目前,有影响力的三大商用服务器之一,也号称是世界上最快的Java虚拟机,但主要用于IBM公司自家的各种Java产品
- 2017年左右,IBM发布了开源J9,命名为 openJ9,交给Eclipse基金会管理,也称为Ecilpse OpenJ9
Virtual Machine,简称IT4J,内部代号:J9
- 市场定位与 HotSpot接近,服务器端、桌面应用、嵌入式等多用途VM
- 目前,有影响力的三大商用服务器之一,也号称是世界上最快的Java虚拟机,但主要用于IBM公司自家的各种Java产品
- 2017年左右,IBM发布了开源J9,命名为 openJ9,交给Eclipse基金会管理,也称为Ecilpse OpenJ9