你有一辆车,你每天开着它,车上功能充满了科技感,你很喜欢它,但后来你不满足它本身的样子,而且有时会出现莫名其妙的问题,可是你只会开车,你真的了解它吗?于是你开始探索它,你会发现有时候能成功,有时候会失败,但是你没有放弃,终于有一天,你可以控制它向你预期发展的方向进行,你会豁然开朗。
有人总问,我是Java程序员,我学习JVM能干嘛?工作中用不到,难道就为了和面试官多聊几句吗?我的回答是,学习什么都是为了自己,面试也是其中的一小部分,事物的发展都是有规律的,如果你想在Java这条路多走几年,学习JVM是必经之路,工欲善其事,必先利其器,这就好比学习数据结构和算法一样,框架可以发展多种多样,但底层原理可能一模一样,我们要做的就是学习事物的精髓,就好比本章一样,我不能把所有虚拟机的知识都一一讲到,我能做的就是,我的一字一句可以在Java的路上陪伴着你。
Java是现如今全球使用者最多的软件开发语言,也是排名第一的部署平台,我们能成为其中的一员是荣幸的一件事。Java 是几乎所有类型的网络应用程序的基础,也是开发和提供嵌入式和移动应用程序、游戏、基于 Web 的内容和企业软件的全球标准。Java 在全球各地有超过 900 万的开发人员。从笔记本电脑到数据中心,从游戏控制台到科学超级计算机,从手机到互联网,Java 无处不在!
Java从第一版到现在已经发展了二十多年的时间了,笔者写这章内容的时候Java14已经上市了,而且Java 15的开发工作将于2020年9月开始,目前更新的速度几乎是一年一个版本,可见Java市场正处在一个黄金的发展阶段。
Java最初的样子并不是这样的,在1990初的时候詹姆斯·高斯林(James Gosling)等人开发一个名为Green的项目,此项目是开发一种能够在各种消费性电子产品(如机顶盒、冰箱、收音机等)上运行等程序架构 。这个项目等产品就是Java语言的前身Oak(橡树)。Oak在当时消费产品上并不成功,低沉了几年后,在1994那年Oak开发团队改变目标 ,将他们的技术应用与万维网,果然他们发现Oak更适合这里,随后同年里 Java1.0a版本提供下载,随后在1995年5月23日,Oak语言正式改名为Java,并且在SunWorld大会上发布Java1.0正式版本,至此Java诞生,所谓“塞翁失马,焉知非福?”如果Green在机顶盒上成功了,哪来的现如今的Java。但为什么命名Java呢,这里还有一个小故事,据说当时要注册Oak商品的时候发现已经被一家显卡制造公司注册了,在Java创始团队中其中一名成员联想到自己曾在Java岛上(爪哇岛)曾喝过一种咖啡,于是命名了Java,当然还有另一种说法是当时取名的时候正好在一家“爪哇”咖啡店喝着咖啡,所以叫Java,当然这些我们也不必较真,既然是故事,还是保持着他的神秘吧,总之和咖啡是脱不了关系了。直到现在我们看Java的logo依然是一杯冒着热气的咖啡,而且在所有Java的类文件中前四个字节是“CA FE BA BE”,大家习惯叫他咖啡宝贝。
1996年4月,10个最主要的操作系统供应商申明将在其产品中嵌入Java技术。
1996年9月,约8.3万个网页应用了Java技术来制作。
1997年2月18日,JDK1.1发布。
新特性及更新修改:
1997年4月2日,JavaOne会议召开,参与者超过万人,创造当时全球同类会议规模之纪录。
1997年9月,JavaDeveloperConnection社区成员超过十万。
1998年2月,JDK1.1被下载超过2,000,000次。
1998年12月8,Java的企业平台Java EE正式发布。
1999年6月,Sun公司发布Java的三大版本:标准版(Java SE)、企业版(Java EE)、微型版(Java ME)。
2000年5月8日,JDK1.3发布。
新特性及更新修改:
2000年5月29日,JDK1.4发布。
2001年6月5日,NOKIA宣布,到2003年将出售1亿部支持Java的手机。
2001年9月24日,Java EE 1.3发布。
2002年2月26日,J2SE1.4发布,自此Java的计算能力有了大幅提升。
2004年9月30日,J2SE1.5发布,是Java语言发展史上的又一里程碑事件。为了表示这个版本的重要性,Java SE 1.5正式更名为Java SE 5.0。
新特性及更新修改:
2006年12月,Sun公司发布了JDK1.6(也被称为Java SE 6)。一直以来,Sun公司维持着大约2年发布一次JDK新版本的习惯。
2009年4月20日,Oracle宣布将以每股9.5美元的价格收购Sun,该交易的总价值约为74亿美元。但Oracle通过收购Sun公司获得了两项软件资产:Java和Solaris。2007年11月,Java语言作为服务器端编程语言,已经取得了极大地成功;而Android平台的流行,则让Java语言获得了在客户端程序上大展拳脚的机会。
2011年7月28日,Oracle公司发布了Java SE 7,这次版本升级经过了将近5年时间。Java SE 7也是Oracle发布的第一个Java版本,引入了二进制整数、支持字符串的switch语句、多异常捕捉、自动关闭资源的try语句等新特性。
2014年3月18日,Oracle公司发布了Java SE 8,这次版本升级为Java带来了全新的Lambda表达式。除此之外,Java 8还增加了大量新特性,这些新特性使得Java变得更加强大。
目前Java的版本已经更新了好几个版本,但目前市场主流还是使用的JDK8。
新特性及更新修改:
2017年9月22日,Oracle公司发布了Java SE 9,这次版本升级强化了Java的模块化系统,让庞大的Java语言更轻量化,而且采用了更高效、更智能的G1 垃圾回收器,并在核心类库上进行了大量更新,可以进一步简化编程;但对语法本身更新并不多。
2018年3月20日JDK10发布,这次主要对内部重构,统一一些接口和规范,这些改变对Java以后的更新升级是做了铺垫,但是对于Java使用者来说就显得乏善足陈。同年一场官司让Google赔偿Oracle公司88亿美元,赔偿相当于免单了收购Sun公司。
2018年9月25日JDK11发布,其中ZGC垃圾收集器诞生,对Lambda语法改进,Oracle宣布发行两个版本对JDK,一个是OpenJDK另一个是OracleJDK,两个JDK源码大部分一致,功能几乎一样,区别在于OpenJDK免费开发、测试、生产环境中使用,但只要半年更新支持。OracleJDK依然免费,但如果用在生产环境只提供三年的更新支持。
2019年3月20日JDK12发布,主要包括Switch表达式、Java微测试套件(JMH)等新功能,还有Shenandoa垃圾收集器的诞生,该收集器非Oracle公司开发的,故在OracleJDK中剔除了Shenandoa垃圾收集器,但他还存在于OpennJDK中。
同年9月JDK13发布。
Sun Classic/Exact VM(执行效率很慢)
1996年1月23日,Sun公司发布JDK 1.0。这个JDK中所带的虚拟机就是Classic VM。这款虚拟机只能使用纯解释器方式来执行Java代码,如果要使用JIT编译器,就必须进行外挂。但是假如外挂了JIT编译器,JIT编译器就完全接管了虚拟机的执行系统,解释器便不再工作了。它是“世界上第一款商用Java虚拟机”的头衔。
由于解释器和编译器不能配合工作,这就意味着如果要使用编译器执行,编译器就不得不对每一个方法、每一行代码都进行编译,而无论它们执行的频率是否具有编译的价值。因此这个阶段的虚拟机即使用了JIT编译器输出本地代码,执行效率很慢。
Exact VM的虚拟机(使用准确是内存管理,存在时间很短,很快被HotSpot替代)
即虚拟机可以知道内存中某个位置的数据具体是什么类型。这样才能在GC(垃圾收集)的时候准确判断堆上的数据是否还可能被使用。由于使用了准确式内存管理,Exact VM可以抛弃以前Classic VM基于handler的对象查找方式。这样每次定位对象都少了一次间接查找的开销,提升执行性能。
HotSpot VM(目前使用范围最广的Java虚拟机,HotSpot指的就是热点代码探测技术)
JDK 1.2时,与classic VM并存,但默认使用的是Classic VM,在JDK 1.3时,HotSpot VM成为默认虚拟机,但Classic VM仍作为虚拟机的“备用选择”发布(使用java-classic参数切换),直到JDK 1.4的时候,Classic VM才完全退出商用虚拟机的历史舞台。
最初并非由Sun公司开发,而是由一家名为“Longview Technologies”的小公司设计的。既继承了Sun之前两款商用虚拟机的优点(如前面提到的准确式内存管理)
HotSpot VM的热点代码探测能力可以通过执行计数器找出最具有编译价值的代码,然后通知JIT编译器以方法为单位进行编译。如果一个方法被频繁调用,或方法中有效循环次数很多,将会分别触发标准编译和OSR(栈上替换)编译动作。通过编译器与解释器恰当地协同工作,可以在最优化的程序响应时间与最佳执行性能中取得平衡,而且无须等待本地代码输出才能执行程序,即时编译的时间压力也相对减小,这样有助于引入更多的代码优化技术,输出质量更高的本地代码。
HotSpot VM便成为了Sun JDK和OpenJDK两个实现极度接近的JDK项目的共同虚拟机。
在2008年和2009年,Oracle公司分别收购了BEA公司和Sun公司,这样Oracle就同时拥有了两款优秀的Java虚拟机:JRockit VM和HotSpot VM。Oracle公司宣布在不久的将来(大约应在发布JDK 8的时候)会完成这两款虚拟机的整合工作,使之优势互补。整合的方式大致上是在HotSpot的基础上,移植JRockit的优秀特性,譬如使用JRockit的垃圾回收器与MissionControl服务,使用HotSpot的JIT编译器与混合的运行时系统。
其他虚拟机(面对移动以及嵌入式市场的,只需了解)
(1)KVM
KVM中的K是“Kilobyte”的意思,它强调简单、轻量、高度可移植,但是运行速度比较慢。在Android、iOS等智能手机操作系统出现前曾经在手机平台上得到非常广泛的应用。
(2)CDC/CLDC HotSpot Implementation
CDC/CLDC全称是Connected(Limited)Device Configuration,在JSR-139/JSR-218规范中进行定义,它希望在手机、电子书、PDA等设备上建立统一的Java编程接口,而CDC-HI VM和CLDC-HI VM则是它们的一组参考实现。CDC/CLDC是整个Java ME的重要支柱,但从目前Android和iOS二分天下的移动数字设备市场看来,在这个领域中,Sun的虚拟机所面临的局面远不如服务器和桌面领域乐观。
(3)Squawk VM
Squawk VM由Sun公司开发,运行于Sun SPOT(Sun Small Programmable Object Technology,一种手持的WiFi设备),也曾经运用于Java Card。这是一个Java代码比重很高的嵌入式虚拟机实现,其中诸如类加载器、字节码验证器、垃圾收集器、解释器、编译器和线程调度都是Java语言本身完成的,仅仅靠C语言来编写设备I/O和必要的本地代码。
(4)JavaInJava
JavaInJava是Sun公司于1997年~1998年间研发的一个实验室性质的虚拟机,从名字就可以看出,它试图以Java语言来实现Java语言本身的运行环境,既所谓的“元循环”(Meta-Circular,是指使用语言自身来实现其运行环境)。它必须运行在另外一个宿主虚拟机之上,内部没有JIT编译器,代码只能以解释模式执行。在20世纪末主流Java虚拟机都未能很好解决性能问题的时代,开发这种项目,其执行速度可想而知。
(5)Maxine VM
Maxine VM和上面的JavaInJava非常相似,它也是一个几乎全部以Java代码实现(只有用于启动JVM的加载器使用C语言编写)的元循环Java虚拟机。这个项目于2005年开始,到现在仍然在发展之中,比起JavaInJava,Maxine VM就显得“靠谱”很多,它有先进的JIT编译器和垃圾收集器(但没有解释器),可在宿主模式或独立模式下执行,其执行效率已经接近了HotSpot Client VM的水平。
除了sun公司外,其他公司研发的虚拟机,规模最大、最著名的就是BEA和IBM公司了
JRockit VM
JRockit VM曾经号称“世界上速度最快的Java虚拟机”(广告词,貌似J9 VM也这样说过)。BEA公司将其发展为一款专门为服务器硬件和服务器端应用场景高度优化的虚拟机,由于专注于服务器端应用,它可以不太关注程序启动速度,因此JRockit内部不包含解析器实现,全部代码都靠即时编译器编译后执行。除此之外,JRockit的垃圾收集器和MissionControl服务套件等部分的实现,在众多Java虚拟机中也一直处于领先水平。
IBM J9 VM
BM J9 VM并不是IBM公司唯一的Java虚拟机,不过是目前其主力发展的Java虚拟机。与BEA JRockit专注于服务器端应用不同,IBM J9的市场定位与Sun HotSpot比较接近,它是一款设计上从服务器端到桌面应用再到嵌入式都全面考虑的多用途虚拟机,J9的开发目的是作为IBM公司各种Java产品的执行平台,它的主要市场是和IBM产品(如IBM WebSphere等)搭配以及在IBM AIX和z/OS这些平台上部署Java应用。
Azul VM/BEA Liquid VM
我们平时所提及的“高性能Java虚拟机”一般是指HotSpot、JRockit、J9这类在通用平台上运行的商用虚拟机,但其实Azul VM和BEA Liquid VM这类特定硬件平台专有的虚拟机才是“高性能”的武器。
Azul VM是Azul Systems公司在HotSpot基础上进行大量改进,运行于Azul Systems公司的专有硬件Vega系统上的Java虚拟机,每个Azul VM实例都可以管理至少数十个CPU和数百GB内存的硬件资源,并提供在巨大内存范围内实现可控的GC时间的垃圾收集器、为专有硬件优化的线程调度等优秀特性。
Apache Harmony /Google Android Dalvik VM
Apache Harmony是Apache软件基金会旗下的Java程序运行平台.但却没有获得TCK使用授权.自从Sun将JDK开源形成Open JDK以来,Apache Harmony 开源的优势被极大地削弱.虽然Harmony没有经过真正大规模的商业运用,但它的代码被先进入了IBM的JDK 7的实现及Google Android SDK之中,对Android的发展有很大的推动作用.
Android让Java语言真正走向了移动数码设备领域,Dalvik VM是Android平台的核心组成部分之一.它不是JVM,但却和JVM有着千丝万缕的联系.跟随着Android一起处于迅猛发展阶段,Android2.2中即时编译器的实现,使其在执行性能上有很大的提高.
Microsoft JVM及其他
Java语言诞生初期,它的主要应用之一是在浏览器中运行Java Applets程序,微软公司为了在IE3中支持Java Applets应用而开发了自己的JVM,虽然只有Windows平台下的版本.却是当时Windows下性能最好的JVM,好景不长,在1997年10月Sun公司把 微软公司告上法庭,其原因是侵犯Sun公司商标、不正当竞争等原因,最终向Sun公司赔偿2000万美元,并要求微软终止Java虚拟机等发展。
总结一下以上所列举的虚拟机,我们需要知道的是Sun Classic/Exact VM是世界第一台,HotSpot VM是目前国内主流,JRockit VM是曾经号称最快的,IBM J9 VM是IBM公司的。接下来本书后面内容只会对HotSpot VM进行讲解,如没有特指哪个虚拟机,泛指HotSpotVM。
这一小结主要让大家更清楚的认识Java都是哪些技术体系组成的,以及我们常说的JDK、JRE都是什么。
广义上讲,Groovy等基于JVM的语言及其相关的程序,都属于Java技术体系的一员;
狭义上讲,SUN官方定义的Java技术体系:
如图1-1所示,我们可以清楚的看出JDK和JRE分别都是由什么组成的。JDK是由 Java程序语言、Java虚拟机、Java类库组成的,是Java程序开发最小环境,即用来编译我们所写的Java代码。所以我们开发人员经常说的JDK就泛指了Java技术体系的全部内容。而JRE是由Java类库中的JavaSE API子集和Java虚拟机组成的,JRE是Java运行的标准环境,即可将字节码运行起来。
图 1-1 Java技术体系内容
以上是我们按照Java各个组成部分来划分的,下面我们按照业务和功能划分,可以分为四部分。
如果对上述内容还有些模糊的话那可以这样为您解释,虽然安卓使用Java语言开发的,但他并非Java ME,说直白点就是被淘汰了。Java SE就是我们刚开始学习Java所接触到的版本,包含了集合、数组、IO等基础知识,以及Java的核心API。Java EE就是我们开发后台程序用到的版本,包含常spring、servlet、jdbc、springboot等,主要适用于创建服务器应用程序。