目录
一、开篇感言
二、正文
1.Java技术体系
1.1 Java技术体系介绍
1.2 JDK和JRE范围
1.3 Java主要产品线
1.4 Java发展史
1.5 Java虚拟机家族
一、开篇感言
对于Java开发程序员来说,对于JVM大都不会陌生。近来对JVM产生了浓厚的兴趣,拜读了周志明老师的《深入理解Java虚拟机》,学到了很多认知之外的知识。遂产生了梳理该书的主要知识点以及用通俗方式让大家更快更好的掌握认识到该书。
如果你对JVM还处于一知半解或者从未接触的情况,希望本栏目对你的个人提升能够有所帮助。如果你对JVM已经炉火纯青或者有所建树,希望对本栏目给予更多的指导和指正,以期帮助更多的人。
最后,以本书该章节的第一句话结束感言:世界上并没有完美的程序,但我们并不因此而沮丧,因为写程序本来就是一个不断追求完美的过程。
二、正文
1.Java技术体系
1.1 Java技术体系介绍
1.1 Java技术体系介绍
从广义上讲,Kotlin、Clojure、JRuby、Groovy等运行于Java虚拟机上的编程语言及其相关的程序都属于Java技术体系中的一员。
从传统意义上来看,JCP官方(Java Community Process,通称“Java社区”)所定义的Java技术体系包括了以下几个组成部分:Java程序设计语言、Java虚拟机、Class文件、Java类库、第三方Java类库。
1.2 JDK和JRE范围
Java类库API中的Java SE API子集和Java虚拟机这两部分统称为JRE(Java Runtime Environment),JRE是支持Java程序运行的标准环境。
Java程序设计语言、Java虚拟机、Java类库这三部分统称为JDK(Java Development Kit),JDK是用于支持Java程序开发的最小环境。
下图展示了Java技术体系所包括的内容,以及JDK和JRE所涵盖的范围。
1.3 Java主要产品线
| 名称 | 介绍 |
|---|---|
| Java Card | 支持Java小程序(Applets)运行在小内存设备(如智能卡)上的平台。 |
| Java ME(Micro Edition) | 支持Java程序运行在移动终端(手机、PDA)上的平台,对Java API有所精简,并加入了移动终端的针对性支持。 JDK 6以前被称为J2ME。 |
| Java SE(Standard Edition) | 支持面向桌面级应用(如Windows下的应用程序)的Java平台,提供了完整的Java核心API。 JDK 6以前被称为J2SE。 |
| Java EE(Enterprise Edition) | 支持使用多层架构的企业应用(如ERP、MIS、CRM应用)的Java平台,除了提供Java SE API外,还对其做了大量有针对性的扩充(以javax.*作为包名)。 JDK 6以前被称为J2EE,在JDK 10以后被Oracle放弃,捐献给Eclipse基金会管理,此后被称为Jakarta EE。 |
1.4 Java发展史
1991年4月,由James Gosling博士领导的绿色计划(Green Project)开始启动,此计划最初的目标是开发一种能够在各种消费性电子产品(如机顶盒、冰箱、收音机等)上运行的程序架构。这个计划的产品就是Java语言的前身:Oak。
1995年5月23日,Oak语言改名为Java,并且在SunWorld大会上正式发布Java 1.0版本。
1996年1月23日,JDK 1.0发布,提供了一个纯解释执行的Java虚拟机实现(Sun Classic VM)。代表技术包括:Java虚拟机、Applet、AWT等。
1996年5月底,Sun于美国旧金山举行了首届JavaOne大会。
1997年2月19日,JDK 1.1发布,代表技术包括:JAR文件格式、JDBC、JavaBeans、RMI等。语法增强:内部类(Inner Class)、反射(Reflection)。
1999年4月8日,JDK 1.1一共发布了1.1.0至1.1.8这9个版本。从1.1.4以后,每个JDK版本都有一个属于自己的名字(工程代号),分别为:JDK 1.1.4-Sparkler(宝石)、JDK 1.1.5-Pumpkin(南瓜)、JDK 1.1.6-Abigail(阿比盖尔,女子名)、JDK 1.1.7-Brutus(布鲁图,古罗马政治家和将军)和JDK 1.1.8-Chelsea(切尔西,城市名)。
1998年12月4日,JDK 1.2-Playground(竞技场)发布,代表性技术:EJB、Java Plug-in、Java IDL、Swing等。Java技术体系拆分为三个方向:J2SE、J2EE和J2ME。Java虚拟机内置了JIT(Just In Time)即时编译器。在语言和API层面上,Java添加了strictfp关键字,Java类库添加了Collections集合类等。
1999年3月和7月,JDK 1.2.1和JDK 1.2.2两个小升级版本发布。
1999年4月27日,发布HotSpot虚拟机(JDK 1.3及之后所有JDK版本的默认Java虚拟机)。
2000年5月8日,JDK 1.3-Kestrel(美洲红隼)发布,Java类库:数学运算和新的Timer API。JNDI服务从扩展服务提升为平台级服务,使用CORBA IIOP来实现RMI的通信协议,提供了大量新的Java 2D API,并且新添加了JavaSound类库。
2001年5月17日,JDK 1.3.1-Ladybird(瓢虫)发布,此后JDK的主版本以动物命名,修正版本以昆虫作为工程代号。
2002年2月13日,JDK 1.4-Merlin(灰背隼)发布,是Java真正走向成熟的一个版本。新的技术特性:正则表达式、异常链、NIO、日志类、XML解析器和XSLT转换器等等。
2002年9月16日,JDK 1.4.1-Grasshopper(蚱蜢)发布。
2003年6月26日,JDK 1.4.2-Mantis(螳螂) 发布 。
2004年9月30日,JDK 5-Tiger(老虎)发布,语法特性:自动装箱、泛型、动态注解、枚举、可变长参数、遍历循环(foreach循环)等。虚拟机和API层:改进了Java的内存模型(Java Memory Model,JMM)、提供了java.util.concurrent并发包等。此后JDK的版本号从“JDK 1.x”修改成了“JDK x”。
2006年11月13日的JavaOne大会上,Java正式开源,JDK各个部分陆续在GPL v2协议下公开了源码,并建立了OpenJDK组织对这些源码进行独立管理。OpenJDK几乎拥有了当时SunJDK 7的全部代码。
2006年12月11日,JDK 6-Mustang(野马)发布,语法特性:提供初步的动态语言支持(通过内置Mozilla JavascriptRhino引擎实现)、提供编译期注解处理器和微型HTTP服务器API。Java虚拟 机内部:锁与同步、垃圾收集、类加载等。此外,八年历史的J2EE、J2SE、J2ME的产品线命名修改为Java EE 6、Java SE 6、JavaME 6。
2018年10月18日,Java SE 6 Update 211(JDK 6最后版本)发布(由于代码复杂性、Java开源、开发JavaFX、世界经济危机及Oracle对Sun的收购案等原因,JDK 6的升级补丁共计发布211次)。
2009年2月19日,JDK 7-Dolphin(海豚)发布第一个里程碑版本(规划十个里程碑。最后一个里程碑版本原计划定于2010年9月9日结束,但由于各种原因,JDK 7最终无法按计划完成)。
2011年7月28日,JDK 7-Dolphin(海豚)发布,改动特性:提供新的G1收集器(G1在发布时依然处于Experimental状态,直至2012年4月的Update 4中才正式商用)、加强对非Java语言的调用支持(JSR-292,这项特性在到JDK 11还有改动)、可并行的类加载架构、Fork/Join框架、switch语句块支持字符串等。从JDK 7 Update 4起,开始支持Mac OS X操作系统,并在JDK 7 Update 6中完全兼容Mac OS X;JDK 7 Update 6对ARM指令集架构提供了支持(此前仅支持x86、x86-64和SPARC指令集架构)。
2014年3月18日,JDK 8-Spider(蜘蛛)发布,语法特性:Lambda表达式、内置Nashorn Javascript引擎的支持、新的时间日期API、彻底移除HotSpot的永久代、函数式接口、JavaFX等。
2017年9月21日,JDK 9发布,语法特性:Jigsaw、整顿HotSpot日志系统、JShell、默认垃圾回收期切换为G1、竞争锁性能优化。此后JDK将会在每年的3月和9月各发布一个大版本避免交付风险。此后每六个JDK大版本中才会被划出一个长期支持(Long Term Support,LTS)版,LTS版能够获得为期三年的支持和更新,普通版只有短短六个月的生命周期。JDK 8和JDK 11会是LTS版,再下一个就到2021年发布的JDK 17了。
2018年3月20日,JDK 10发布,内部重构:统一源仓库、统一垃圾收集器接口、统一即时编译器接口(JVMCI在JDK 9已经有了,这里是引入新的Graal即时编译器)等。
2018年3月,Oracle将Java EE所有权赠送给Eclipse基金会,不准再使用“Java”这个商标,此后改名为Jakarta EE。详见以下文章。Java EE重命名为Jakarta EE:Java EE Guardians与Oracle的分歧-InfoQ看新闻很累?看技术新闻更累?试试下载InfoQ手机客户端,每天上下班路上听新闻,有趣还有料!由于对Oracle不热心回应Java社区反馈感到失望,JavaEEGuardians于今年早些时候提交了一封公开信,表达了他们对Oracle限制使用EE4J的“Java”和“javax”包名的担忧。Oracle依据其商标使用准则,继续保持自己的立场。著名的JavaEE布道师RezaRahman,同时担任Cahttps://www.infoq.cn/article/2018/02/from-javaee-to-jakartaee
2018年9月25日,JDK 11发布(LTS版本),语法特性:ZGC垃圾收集器出现、Stream、String、Lambda语法等功能增强。
Oracle从JDK 11起把以前的商业特性全部开源给OpenJDK,这样OpenJDK 11和OracleJDK 11的代码和功能本质上是完全相同的。Oracle宣布以后将会同时发行两个JDK:一个是以GPLv2+CE协议下由Oracle发行的OpenJDK(本书后面章节称其为Oracle OpenJDK),另一个是在新的OTN协议下发行的传统的OracleJDK,这两个JDK共享绝大部分源码,在功能上是几乎一样的,核心差异是前者可以免费在开发、测试或生产环境中使用,但是只有半年时间的更新支持;后者个人依然可以免费使用,但若在生产环境中商用就必须付费,可以有三年时间的更新支持。
2019年2月,RedHat同时从Oracle手上接过OpenJDK 8和OpenJDK 11的管理权利和维护职责,RedHat代替Oracle成为JDK历史版本的维护者。
2019年3月20日,JDK 12发布,语法特性:Switch语句、Java微测试套件(JMH)、垃圾收集器算法Shenandoah等。RedHat领导开发的Shenandoah垃圾收集器与Oracle在JDK 11中发布的ZGC几乎完全一致,Oracle违背尽可能保证OracleJDK和OpenJDK的兼容一致,在OracleJDK 12里把Shenandoah的代码通过条件编译强行剔除掉,使其成为历史上唯一进入了OpenJDK发布清单,但在OracleJDK中无法使用的功能。
2019年9月17日,JDK 13发布,语法特性:ZGC垃圾收集器增强、Switch语句等。
2020年3月17日,JDK 14发布,语法特性: instanceof的模式匹配预览版本、Records预览版本、jpackage打包工具孵化、G1的NUMA内存分配优化、移除CMS垃圾收集器、弃用Parallel Scavenge和Serial Old垃圾收集算法的组合、ZGC移植到Windows和mac OS。
2020年9月15日,JDK 15发布,语法特性:instanceof的模式匹配预览版本、EdDSA 数字签名算法、隐藏类、Records预览版本、重新实现 Legacy DatagramSocket API、ZGC。
2021年3月16日,JDK 16发布,语法特性:instanceof发布、Records发布、jpackage打包工具发布等。
2021年9月14日,JDK 17发布(LTS版本),伪随机数生成器 (PRNG) 增强、删除实验性 AOT 和 JIT 编译器、switch功能增强等。
1.5 Java虚拟机家族
1.5.1 虚拟机始祖:Sun Classic/Exact VM
1996年1月23日,Sun发布的JDK 1.0所带的虚拟机就是Classic VM。这款虚拟机只能使用纯解释器方式来执行Java代码,如果要使用即时编译器必须进行外挂,但是外挂即时编译器的话,即时编译器就会完全接管虚拟机的执行系统,解释器便不能再工作了。在JDK 1.2及之前,用户用Classic虚拟机执行java-version命令,将会看到类似下面这行的输出:
java version "1.2.2" Classic VM(build JDK-1.2.2-001,green threads,sunwjit)
“sunwjit”(Sun Workshop JIT)就是Sun提供的外挂编译器,其他类似的外挂编译器还有Symantec JIT和shuJIT等。由于解释器和编译器不能配合工作,意味着使用编译执行时不得不对每一个方法、每一行代码都进行编译。
Sun的虚拟机团队在JDK 1.2时,曾在Solaris平台上发布过一款名为Exact VM的虚拟机,它的编译执行系统已经具备热点探测、两级即时编译器、编译器与解释器混合工作模式等。Exact VM因它使用准确式内存管理(Exact Memory Management,也可以叫Non-Conservative/Accurate Memory Management)而得名。
准确式内存管理是指虚拟机可以知道内存中某个位置的数据具体是什么类型。譬如内存中有一个32bit的整数123456,虚拟机将有能力分辨出它到底是一个指向了123456的内存地址的引用类型还是一个数值为123456的整数,准确分辨出哪些内存是引用类型,这也是在垃圾收集时准确判断堆上的数据是否还可能被使用的前提。由于使用了准确式内存管理,Exact VM可以抛弃掉以前Classic VM基于句柄(Handle)的对象查找方式(原因是垃圾收集后对象将可能会被移动位置,如果地址为123456的对象移动到654321,在没有明确信息表明内存中哪些数据是引用类型的前提下,那虚拟机肯定是不敢把内存中所有为123456的值改成654321的,所以要使用句柄来保持引用值的稳定),这样每次定位对象都少了一次间接查找的开销,显著提升执行性能。
虽然Exact VM的技术相对Classic VM来说先进了许多,但是它只存在了很短暂的时间就被外部引进的HotSpot VM所取代。而Classic VM的生命周期则相对要长不少,它在JDK 1.2之前是JDK中唯一的虚拟机,在JDK 1.2时,它与HotSpot VM并存,但默认是使用Classic VM(用户可用java-hotspot参数切换至HotSpot VM),而在JDK 1.3时,HotSpot VM成为默认虚拟机,它仍作为虚拟机的“备用选择”发布(使用java-classic参数切换),直到JDK 1.4的时候,Classic VM才完全退出商用虚拟机的历史舞台,与Exact VM一起进入了Sun Labs Research VM之中。
1.5.2 武林盟主:HotSpot VM
HotSpot虚拟机是Sun/OracleJDK和OpenJDK中的默认Java虚拟机,也是目前使用范围最广的Java虚拟机。HotSpot虚拟机来源于Strongtalk虚拟机,由“Longview Technologies”公司设计,这款虚拟机中相当多的技术来源于一款为支持Self语言实现“达到C语言50%以上的执行效率”的目标而设计的Self虚拟机,Sun公司在1997年收购了Longview Technologies公司,从而获得了HotSpot虚拟机。
其实HotSpot与Exact虚拟机基本上是同时期的独立产品,HotSpot出现得还稍早一些,一开始HotSpot就是基于准确式内存管理的,而Exact VM之中也有与HotSpot几乎一样的热点探测技术,为了Exact VM和HotSpot VM哪个该成为Sun主要支持的虚拟机,在Sun公司内部还争吵过一场,HotSpot击败Exact并不能算技术上的胜利。
HotSpot虚拟机的热点代码探测能力可以通过执行计数器找出最具有编译价值的代码,然后通知即时编译器以方法为单位进行编译。如果一个方法被频繁调用,或方法中有效循环次数很多,将会分别触发标准即时编译和栈上替换编译(On-Stack Replacement,OSR)行为。通过编译器与解释器恰当地协同工作,可以在最优化的程序响应时间与最佳执行性能中取得平衡,而且无须等待本地代码输出才能执行程序,即时编译的时间压力也相对减小,这样有助于引入更复杂的代码优化技术,输出质量更高的本地代码。
2006年,Sun陆续将SunJDK的各个部分在GPLv2协议下开放了源码,HotSpot从此成为Sun/OracleJDK和OpenJDK两个实现极度接近的JDK项目的共同虚拟机。Oracle收购Sun以后把BEA JRockit(Oracle已收购BEA公司的JRockit)中的优秀特性融合到HotSpot之中。HotSpot在这个过程里移除掉永久代,吸收了JRockit的Java Mission Control监控工具等功能。
1.5.3 小家碧玉:Mobile/Embedded VM
1.5.4 天下第二:BEA JRockit/IBM J9 VM
1.5.5 软硬合璧:BEA Liquid VM/Azul VM
1.5.6 挑战者:Apache Harmony/Google Android Dalvik VM
1.5.7 没有成功,但并非失败:Microsoft JVM及其他
1.5.8 百家争鸣



