接下来,我会向大家简单介绍一下Java语言和JVM,虽然大家对此比较清楚了,但是还是有几个问题是需要明确的。
首先,我们来看一下Java语言在市面上所有语言中的一个排名,这个排名我们可以在一个比较权威的语言热度排行榜的网站(即TIOBE)上看到,该网站每个月都会更新一次当月的语言热度排行榜。大家通过https://www.tiobe.com/tiobe-index/这个链接便能进入到该网站中,如下图所示,可以看到最新的一个语言热度排行榜,即2022年7月份,和去年的7月份想比,Java语言的排名还下降了一位,但无论怎么降,都降不出前三,关于这点相信大家已经早就习惯了。
从上图还可以看到,排第二位的是出现比较早的C语言,而且相较于去年同期,它的涨幅还要比Java语言高出些许。
由于C语言占据着系统软件(包括嵌入式系统)等大部分的市场份额,另外又伴随着现在物联网(即IoT)的崛起,以及大量小型智能设备的出现,所以我们才能看到它现在还有一个向上的涨幅,可谓是增长潜力源源不断啊!
作为一个开发人员,不知道你有没有听说过这样一句话,即世界上没有最好的编程语言,只有最适用于具体应用场景的编程语言,但有时候我们会经常听到有人讲PHP才是世界上最美的编程语言,写到这里我不禁会心一笑,不好意思啊,各位,相信大家对于谁才是世界上最美的编程语言这个问题心里应该都有自己的答案。
回过头来,我们再来说一说这个Java语言,从上面大家也能看到Java语言是长期占据着前三的位置的,甚至有很长的一段时间还是排名第一的,相信大家对此已经见怪不怪了。但是,每隔一段时间我们就会听到网上传出XX语言未来会取代Java这样的一些新闻,这个XX有Kotlin、Go、Python以及JavaScript等,我想之所以会有这样的新闻出现,就是因为Java语言长期占据着编程语言排行榜前三的位置所导致的,因为排名太靠前,总会引来各种嫉妒,免不了挑战者相伴,在武侠小说里面我们已经看过太多太多这样的事情了。
Java语言长期占据编程语言排行榜前三位置是有底气的,这份底气主要是来自于Java庞大的用户群和积极成熟的软件生态,而并不在于Java的语法有多么的先进,这不是在朝夕之间就能被其他语言所撼动的,像上面我们提到的几个语言,它们都在各自的领域中发挥发热,例如互联网基于JavaScript、人工智能基于Python、云原生基于Go等,其实大家都很清楚,不太可能说哪一门语言都能够在每一个领域当中占据优势,只能是说Java是距离这个目标最近的一门语言而已。
其实,上面也从侧面说明了Java是目前应用最为广泛的软件开发平台之一。随着Java以及Java社区的不断壮大,现在Java也早已不再是简简单单的一门计算机语言了,它更是一个平台、一种文化、一个社区。
作为一个平台,Java虚拟机扮演着举足轻重的作用,而这也正是我们一直想要强调的点。另外,还有一点需要大家知道,就是Groovy、Scala、JRuby、Kotlin等都是Java平台的一部分。
作为一种文化,Java几乎成了“开源”的代名词,这是因为一方面基于Java的第三方开源软件和框架非常的多,例如有Tomcat、Struts、MyBatis、Spring等等;一方面就是连JDK和JVM自身也有不少开源的实现,如OpenJDK、Harmony。
这里我得给大家说道说道OpenJDK和Harmony这俩玩意。原来有一个公司叫Sun,相信大家都听说过,只不过现在它已经被Oracle收购了,Oracle这个公司相信大家已经如雷贯耳了,我就不再说了,我想说的是Oracle现在发布的JDK是有两个版本的,一个版本是OpenJDK,一个版本是OracleJDK,它俩Oracle号称所用的类库是一样的,只不过基于的是不同的协议,其中OracleJDK版本是商业化的,就是如果你想要再更新的话,那么可能你就需要进行付费了。
说完OpenJDK,再来给大家说一下Harmony。Harmony是Apache旗下的一款开源JVM产品,它主要是由IBM和英特尔这俩公司主导研发的。
作为一个社区,Java拥有全世界最多的技术拥护者和开源社区支持,有数不清的论坛和资料。从桌面应用软件、嵌入式开发到企业级应用、后台服务器、中间件,都可以看到Java的身影。其应用形式之复杂、参与人数之众多也令人咋舌。
总之,Java拥有非常活跃的开源社区,你理解成是Java拥有最活跃的开源社区也是丝毫没有任何问题的,就像当年出现的安卓一样,谷歌为了能够尽快的建立起一套安卓应用的生态圈,就吸引了大量的Java程序员入驻,而且当时也将Java作为了一门安卓开发的主流语言。
通常我们一说到Java,就会提到它是一门跨平台的语言,注意,这里我们重点强调的是Java的跨平台性。
相信大家都听说过这样一句话,即write once, run anywhere.
,翻译过来便是一次编译到处运行,大家不妨看一下下面这张图,相信大家对此并不陌生。
我想大家应该很清楚,我们编写的Java程序都是以.java
结尾的源文件,这些源文件经过编译以后就会生成字节码文件,而字节码文件是可以在不同的平台(即所谓的操作系统)上解释运行的,当然,我们得针对不同的平台(即所谓的操作系统)安装不同版本的JVM,这是因为只有JVM才能去解释运行字节码文件。
其实上面也从侧面说明了,我们是没有必要去考虑生成的字节码文件的兼容性的,这是因为所有Java虚拟机全部都遵守JVM规范,从而,所有Java虚拟机都可以解释运行.java
源文件编译以后生成的字节码文件,这也就是说字节码文件本身其实就具有跨平台性。
聊完跨平台的语言Java之后,接下来我们就要来聊聊跨语言的平台JVM了。
如果要对Java虚拟机进行追本溯源的话,那么我们就得从官方JVM规范入手了。
之前大家都下载了各个版本的JVM规范了吧!还不知道如何下载的,请看上一讲,这里我就不再赘述了。有一点需要大家注意的是,由于我们这套JVM系列教程主要是基于Java 8
而写就的,所以这里我们主要参考的是Java SE 8
这个版本的JVM规范。
大家打开Java SE 8
这个版本的JVM规范,然后迅速找到1.2 The Java Virtual Machine
这一章节,因为这一章节就对Java虚拟机进行了详细的介绍,如下图所示。
关于Java虚拟机,JVM规范中有两段对其的描述,在上面我已经给大家标注出来了,下面我会分别来对这两段描述进行解读。
先来看第一段描述,如下所示。
The Java Virtual Machine is the cornerstone of the Java platform. It is the component of the technology responsible for its hardware- and operating system-independence, the small size of its compiled code, and its ability to protect users from malicious programs.
这里,我给大家简单翻译一下,如有翻译得不好的地方,还请大家指出,我来及时更正。
这段的意思是说Java虚拟机是Java平台的基石,是整个Java技术的一个组成部分,主要来负责硬件和操作系统的独立性,以及保证编译以后生成的字节码文件的一个小尺寸,而且Java虚拟机还具有保护用户免受恶意程序攻击的能力。
可以看到,开篇就给了Java虚拟机一个很高的定位,可能有些童鞋对保证编译以后生成的字节码文件的一个小尺寸这句话不甚理解,不理解没关系,这里我会举一个例子来向大家进行解释。
在编写Java程序的过程中,相信大家都有用过String
类吧,亦或者用到过基本数据类型种种变量吧,甚至于还用到过一些其他第三方的类吧,总之不管怎样,真正编译以后生成的字节码文件中都会对应着有一个常量池,运行的时候对应的便是运行时常量池了,正是通过这样一些常量的指向,我们才避免了在字节码文件当中去加载大量的类这种情况的发生,从而也就保证了字节码文件的一个小尺寸。
不知我这样解释,大家能明白嘛,要是不明白,那就算了,可能后面你学着学着就会搞懂了。
看完第一段描述,我们再来看第二段描述,第二段描述如下所示。
The Java Virtual Machine is an abstract computing machine. Like a real computing machine, it has an instruction set and manipulates various memory areas at run time. It is reasonably common to implement a programming language using a virtual machine; the best-known virtual machine may be the P-Code machine of UCSD Pascal.
这段的意思是说Java虚拟机是一台抽象的计算机。就像一台真实的计算机一样,它也有它相应的指令级和在运行时控制的各种内存区域······。
后面我就不打算翻译下去了,主要是怕我翻译的有什么不对之处,如果要是大家英文够好的话,不妨自行翻译翻译后面的那句话,嘻嘻😊,我得承认我英文不是太好,老是要借助百度翻译,不好意思啊,各位。
看完官方JVM规范中对Java虚拟机最直接的描述之后,我们再来看一下下面这张图,下面这张图我想给大家说明的一个问题就是Java虚拟机是一个跨语言的平台。
上面我们说Java是一门跨平台的语言,这里我们又说Java虚拟机是一个跨语言的平台,感觉有点绕啊,希望大家好好缕一缕思路,不要被表面语言给绕晕了。其实我有点好奇,难道大家真的不能从上图中清晰地看出来Java虚拟机是一个跨语言的平台吗?
从上图中我们也能看到Java虚拟机起始的原材料就是字节码文件,字节码文件下面要对接的正是我们后面要讲解的类加载子系统(即Class Loader Subsystem),然后后面才是内存的一个分配情况。其实,字节码文件是可以由不同的编程语言来提供的,这一点大家从上图中也能看到,到目前为止,除了Java语言之外,像Kotlin、Clojure、Groovy、Scala、Jython、JRuby、JavaScript等语言,都可以在Java虚拟机平台上解释运行。
也就是说,现在我们称之为是Java虚拟机可能有点不太合适了,因为现在Java虚拟机不仅能够用来解释运行Java程序,而且还能够用来解释运行其他编程语言程序了,前提就是不同的编程语言需要提供各自的编译器,而且经过它们各自的编译器编译生成的字节码文件都得遵循Java虚拟机的规范,如此,Java虚拟机才能去解释运行。
如果大家后面想去打开字节码文件看一看它里面的内容的话,那么你会发现Java虚拟机所识别的字节码文件的开头都是CA FE BA BE
,即任何字节码文件的前四个字节的内容都是CA FE BA BE
,一般我们称之为是魔术,通过它我们就能识别字节码文件是否有效。
总之,大家需要知道的一点是,只要不同的编程语言经过它们各自的编译器编译生成的字节码文件遵循Java虚拟机的规范,那么Java虚拟机就可以来解释运行对应的编程语言程序了,也就是说Java虚拟机其实并不要求源程序必须得用Java语言来编写。
这就有点像大家每天早上喝的牛奶一样,你并不会去关心今天所喝的牛奶到底是内蒙的牛,还是东北的牛,还是新疆的牛生产的,而是只会去关心今天所喝的牛奶是不是新鲜的、有没有坏,里边的营养成分是不是足够,细菌有没有超标。Java虚拟机也是一样,它只关心字节码文件是不是符合它的规范,是不是一个有效的字节码文件,而并不要求字节码文件一定是要来源于Java程序。
为何会如此呢?这里我给大家找到了这样一个解释,原来是随着Java 7的正式发布,Java虚拟机的设计者们通过JSR-292规范基本实现了在Java虚拟机平台上运行非Java语言编写的程序。
至此,相信大家也不难得出这样一个结论,即Java虚拟机根本不关心运行在其内部的程序到底是使用何种编程语言编写的,它只关心字节码文件。也就是说Java虚拟机拥有语言无关性,并不会单纯地与Java语言“终身绑定”,只要其他编程语言的编译结果满足并包含Java虚拟机的内部指令集、符号表以及其他的辅助信息,那么它就是一个有效的字节码文件,就能够被虚拟机所识别并装载运行。
讲到这里,相信大家对Java虚拟机是一个跨语言的平台这句话应该无比理解了。接下来,我就来说说我个人的一点感受。
初中时我们都学过函数,如下图所示。
以上中间红色盒子里面的就是一个函数,或者称作对应法则也行,入口处是自变量,当然这个自变量是可以有多个的,自变量放到红色盒子里面的函数中一顿运算,便会出来一个结果,这一整个过程相信大家都已无比熟悉了,所以我也就不再多说什么了,这里我想说的是这一整个过程其实有点像字节码文件被加载到Java虚拟机中去解释运行并最终输出一个结果一样,上图中的函数就相当于是Java虚拟机,自变量就相当于是字节码文件,并且Java虚拟机并不关心字节码文件的来源,而是只会关心字节码文件本身。
总结一下就是,虽然Java不是最强大的语言,但是Java虚拟机却是最强大的虚拟机。这句话听着还是比较嚣张的,哈哈哈😊,确实是比较嚣张啊,但嚣张有嚣张的资本,时至今日其实毫不夸张的说,Java虚拟机实际上是一个比Java语言本身更成功、更优秀乃至于说更伟大的产品。
最后我想给大家说的一点是,其实关于Java虚拟机是一个跨语言的平台这样的一个总结性的结论在官方JVM规范中都有描述,如下图所示,大家可以在1.2 The Java Virtual Machine
这一章节中找到这样的描述。
这里我把这段描述摘抄出来了,如下所示。
For the sake of security, the Java Virtual Machine imposes strong syntactic and structural constraints on the code in a class file. However, any language with functionality that can be expressed in terms of a valid class file can be hosted by the Java Virtual Machine. Attracted by a generally available, machine-independent platform, implementors of other languages can turn to the Java Virtual Machine as a delivery vehicle for their languages.
这段的意思是说为了安全起见,Java虚拟机会对字节码文件施加一些强类型语法的规范和结构性的约束。然而,任何具有可以被表示成有效字节码文件的功能的编程语言都可以被Java虚拟机所托管。受普遍可用的、独立于机器的平台的吸引,其他语言的实践者可以将Java虚拟机作为其语言的可交付工具。
他妈的,英文翻译成中文,还真他妈够恶心人的,感觉很多翻译出来的语句都不通顺,可能是我的英文功力太差劲了吧!唉😥,我也只能翻译成上面这样了,他妈的还是借助了百度翻译,算了,大家就凑合着看吧!
翻译出来就完事了吗?No,才不会呢,这不是我的风格,我得每一句话每一句话给大家讲解清楚才行。
先来看这句话,即为了安全起见,Java虚拟机会对字节码文件施加一些强类型语法的规范和结构性的约束,关于这句话我真的表示很遗憾,这里我实在无法向大家讲解清楚,因为这得等到讲到后面的字节码与类的加载这一篇章时,大家才能知晓其中的意思,对不住各位了。
再来看下这句话,即然而,任何具有可以被表示成有效字节码文件的功能的编程语言都可以被Java虚拟机所托管,这句话相信大家也不难理解,说的无非就是只要任何一门编程语言的编译结果满足并包含Java虚拟机的内部指令集、符号表以及其他的辅助信息,那么它就是一个有效的字节码文件,就能够被虚拟机所识别并装载运行。
最后再来看下这句话,即受普遍可用的、独立于机器的平台的吸引,其他语言的实践者可以将Java虚拟机作为其语言的可交付工具,这句话中就提到了Java虚拟机具有跨语言的平台的这样一个特征,正是基于这样一个特征,其他语言的实践者就可以使用他们各自的语言来编写程序,然后交付Java虚拟机来解释运行了。