《深入理解Java虚拟机:JVM高级特性与最佳实践》(第三版)-周志明
《深入理解Java虚拟机:JVM高级特性与最佳实践》(第三版)-周志明
《深入理解 Java 虚拟机:JVM 高级特性与最佳实践》(第三版)-周志明
第一部分 走进 Java
第 1 章 走进 Java
世界上并没有完美的程序,但我们并不因此而沮丧,因为写程序本来就是一个不断追求完美的过程。
1.1 概述
Java 不仅仅是一门编程语言,它还是一个由一系列计算机软件和规范组成的技术体系,这个技术体系提供了完整的用于软件开发和跨平台部署的支持环境。
应用:嵌入式系统、移动终端、企业服务器、大型机
特点:
- 结构严谨,面向对象
- 一次编写,到处运行
- 相对安全的内存管理和访问机制,避免了绝大部分内存泄漏和指针越界问题
- 热点代码检测和运行时编译及优化
- 完善的应用程序接口和无数三方类库
1.2 Java 技术体系
广义上,运行于 Java 虚拟机上的编程语言及其相关的程序都属于 Java 技术体系中的一员;传统意义上,官方定义的 Java 技术体系包括了:Java 程序设计语言、各种硬件平台上的 Java 虚拟机实现、Class 文件格式、Java 类库 API、来自商业机构和开源社区的第三方 Java 类库。
可以把 Java 程序设计语言、Java 虚拟机、Java 类库这三部分统称为 JDK,JDK 是用于支持 Java 程序开发的最小环境;可以把 Java 类库 API 中的 Java SE API 子集和 Java 虚拟机这两部分统称为 JRE,JRE 是支持 Java 程序运行的标准环境。
1.3 Java 发展史
1996 年,JDK 1.0 发布
1998 年,JDK 1.2 拆分为三个方向,SE、EE、ME
1999 年,HotSpot 虚拟机诞生
2009 年,JDK 7 发布,Oracle 收购 Sun 公司提供新的 G1 收集器加强对非 Java 语言的调用支持可并行的类加载架构二进制字面量 √ 数字字面量可以出现下划线 √switch 语句可以用字符串泛型简化(即泛型推断)异常的多个 catch 合并 try-with-resources 语句 √
2014,JDK 8 发布
- Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
- 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有 Java 类或对象(实例)的方法或构造器。与 lambda 联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
- 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
- 新工具 − 新的编译工具,如:Nashorn 引擎 jjs、 类依赖分析器 jdeps。
- Stream API − 新添加的 Stream API(java.util.stream) 把真正的函数式编程风格引入到 Java 中。
- Date Time API − 加强对日期与时间的处理。
- Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
- Nashorn, JavaScript 引擎 − Java 8 提供了一个新的 Nashorn javascript 引擎,它允许我们在 JVM 上运行特定的 javascript 应用。
2017 年,JDK 9Jigsaw 作为 Java 模块化规范,此外,JDK 9 还增强了若干工具(JS Shell、JLink、JHSDB 等),整顿了 HotSpot 各个模块各自为战的日志系统,支持 HTTP 2 客户单 API 等 91 个 JEP。每六个 JDK 大版本才会被划出一个长期支持——LTS,目前是 JDK 8 和 JDK 11
2018 年,JDK 10 内部重构,诸如统一源仓库、统一垃圾收集器接口、统一即时编译器接口
2018 年,JDK 11ZGC 垃圾收集器,Lambda 语法改进
2019 年,JDK 12Switch 表达式、Java 微测试套件
1.4 Java 虚拟机家族
1.4.1 虚拟机始祖:Sun Classic/Exact VM
世界上第一款商用 Java 虚拟机,纯解释器方式执行 Java 代码,解释器和编译器不能配合工作。使用编译执行,编译器就得对每一个方法、每一行代码进行编译,执行效率低。
Exact VM 的虚拟机,它的编译执行系统已经具备现代高性能虚拟机雏形,如热点探测、两级即时编译器、编译器与解释器混合工作模式等,但是很快就被 HotSpot 替代。
1.4.2 武林盟主:HotSpot VM
默认的 Java 虚拟机,目前使用范围最广。2014 年的 JDK 8 时期,HotSpot 一处永久代,吸收了 JRockit 的 Java Mission Control 监控工具等功能。
1.4.3 小家碧玉:Mobile/Embedded VM
Java ME,面向移动和嵌入式市场的 Java 虚拟机产品,但是使用很少
1.4.4 天下第二:BEA JRockit/IBM J9 VM
曾经与 HotSpot 并称“三大商业虚拟机”的另外,两位 BEA System 公司的 JRockit 与 IBM 公司的 IBM J9。
JRockit 被发展为一款专门为服务器硬件和服务端应用场景高度优化的虚拟机,专注于服务端应用,可以不太关注于程序启动速度,因此 JRockit 内部不包含解释器实现,全部代码都靠即时编译器编译后执行。除此之外,JRockit 的垃圾收集器和 Java Mission Control 故障处理套件等部分的实现,在当时众多的 Java 虚拟机中也处于领先水平。JRockit 随着 BEA 被 Oracle 收购,已不再继续发展,停留在 R28 版本,JDK 6 版 JRockit 的代号。
IBM J9 虚拟机的市场定位与 HotSpot 比较接近,在设计上全面考虑服务端、桌面应用,再到嵌入式的多用途虚拟机,IBM J9 虚拟机的职责分离与模块化做得比 HotSpot 更优秀,由 J9 虚拟机中抽象封装出来的核心组件库(包括垃圾收集器、即时编译器、诊断监控子系统等)就单独构成了 IBM OMR 项目,可以在其他语言平台如 Ruby、Python 中快速组装成相应的功能。
1.4.5 软硬合璧:BEA Liquid VM/Azul VM
一般所说的“高性能 Java 虚拟机”一般是指 HotSpot、JRockit、J9 这类通用虚拟机。还有一类与特定硬件平台绑定、软硬件配合工作的专有虚拟机,往往能够实现更高的执行性能,或提供某些特殊的功能特性。这类专有虚拟机的代表是 BEA Liquid VM 和 Azul VM。
Liquid VM 不需要操作系统的支持,或者说它自己本身实现了一个专用操作系统的必要功能,如线程调度、文件系统、网络支持等。由虚拟机越过通用操作系统直接控制硬件可以获得很多好处,如在线程调度时,不需要再进行内核态/用户态的切换,这样可以最大限度地发挥硬件的能力,提升 Java 程序的执行性能。随着 JRockit 虚拟机终止开发,Liquid VM 项目也已经停止了。
Azul VM 是 Azul Systems 公司在 HotSpot 基础上进行大量改进,运行于 Azul Systems 公司的专有硬件 Vega 系统上的 Java 虚拟机,每个 Azul VM 实例都可以管理至少数十个 CPU 和数百 GB 的内存的硬件资源,并提供在巨大内存范围内停顿时间可控的垃圾收集器(即业内赫赫有名的 PGC 和 C4 收集器),为专有硬件优化的线程调度等优秀特性。但是成本太高,放弃了。
Zing 虚拟机是一个从 HotSpot 某旧版代码分支基础上独立出来重新开发的高性能 Java 虚拟机,可以运行在通用的 Linux/x86-64 平台上。Azul 公司为它编写了新的垃圾收集器,也修改了 HotSpot 内的许多实现细节,在要求低延迟、快速预热等场景中,Zing VM 都要比 HotSpot 表现得更好。Zing 的 PGC、C4 收集器可以轻易支持 TB 级别的 Java 堆内存,而且保证暂停时间仍然可以维持在不超过 10 毫秒的范围里,HotSpot 要一直到 JDK 11 和 JDK 12 的 ZGC 及 Shenandoah 收集器才达到了相同的目标,而且目前效果仍然远不如 C4。Zing 的 ReadyNow!功能可以利用之前运行时收集到的性能监控数据,引导虚拟机在启动后快速达到稳定的高性能水平,减少启动后从解释执行到即时编译的等待时间。Zing 自带的 ZVision/ZVRobot 功能可以方便用户监控 Java 虚拟机的运行状态,从找出代码热点到对象分配监控、锁竞争监控等。Zing 能让普通用户无须了解垃圾收集等底层调优,就可以使得 Java 应用享有低延迟、快速预热、易于监控的功能,这是 Zing 的核心价值和卖点,很多 Java 应用都可以通过长期努力在应用、框架层面优化来提升性能,但使用 Zing 的话就可以把精力更多集中在业务方面。
1.4.6 挑战者:Apache Harmony/Google Android Dalvik VM
这两者只是“虚拟机”而不是“Java 虚拟机”。
Apache Harmony 是一个 Apache 软件基金会旗下以 Apache License 协议开源的实际兼容于 JDK 5 和 JDK 6 的 Java 程序运行平台,它含有自己的虚拟机和 Java 类库 API,用户可以在上面运行 Eclipse、Tomcat、Maven 等常用的 Java 程序。但是,它并没有通过 TCK 认证,的许多代码(主要是 Java 类库部分的代码)被吸纳进 IBM 的 JDK 7 实现以及 Google Android SDK 之中,尤其是对 Android 的发展起了很大推动作用。