在开始前,先说为什么我从冯·诺依曼计算机体系,追溯到了JVM,一切原来如此。因为一颗剽悍种子发现的一个问题,就是多数人对待知识总想问是什么,却常常很少问为什么(或者说知道了是什么后也很少再问为什么),正如这篇所要畅谈的JVM,看了很多文章"什么是JVM",我其实楞是没搞懂什么是JVM,或者说为什么JVM是要这样子呢?
直到回到知识历史的起点,再来看现在知识,一切原来如此。
(理解知识背后一整条脉络远比纯粹记住硬邦邦知识更为深刻,因为前者会带来思考上的愉悦,而后者只会让人丧失乐趣。)
谁说的?我一颗剽悍的种子眼里饱含泪水说的。
所以我回到冯·诺依曼的计算机体系再到操作系统去追溯 JVM 来看看这整条脉络。
回顾计算机发展历史,我们都知道被称为“现代计算机之父”的冯·诺依曼在1945提出并奠定到至今的冯·诺依曼计算机体系,也就是计算机结构。所以要知道一个真相是到至今为止不管在物理机之上构建的是什么样的操作系统、还是操作系统上构建什么样的虚拟机,或者再上层的应用,追溯到源头都离不开这套体系下。(通俗的说我们被笼罩在这套体系之下)
(所以为什么你总能在JVM虚拟机身上看到计算机结构熟悉的身影。)
计算机结构思想在计算机结构中由 输入设备、控制器、运算器、存储器、输出设备 这五大部分组成。而 控制器 运算器 就是我们再熟悉不过的CPU(中央处理器),存储器就是内存、磁盘等,输入设备例如:键盘、鼠标,输出设备如:显示器等。而整个计算机结构的运行如下图所示:
从上面可以看到,整个硬件已经布好了局,当一个程序被执行时,程序会被当成数据一样,所有组成结构都可以被看成数据/指令流、控制流(图下方箭头所示),程序就像数据(或者指令)一样,只要经过流就可以被牢牢操控。这也正是冯·诺依曼的思想 “程序应该像数据一样可以被存储”。
操作系统的本质在计算机结构之上还有一层,那就是操作系统,操作系统可以说是虚拟机的鼻祖,因为操作系统目的就是:如何操控物理机器。也就是如何将现实的物理资源(CPU、内存、磁盘)虚拟化成一台能被你通过盯着屏幕、敲着键盘、划着鼠标就能操控现实的物理资源。
不错,操作系统本质就是将 “物理资源虚拟化”!
(想想元宇宙的起点是不是从操作系统这里开始了呢?)
在我们最常用的操作系统有Windows和Linux这两种,不过这两个操作系统之间是不兼容的,那么就会存在编写的程序并不能同时运行在两个操作系统上,而开发程序时就得要分别开发。那么就会触发人类(程序员)的第一生产力 懒!
千万别笑!人类发明蒸汽机以来,就从未停止过释放重复劳动力的工作,人类发明洗衣机替代洗衣、洗碗机替代洗碗、汽车替代马车,以及再到20世纪30年代就提出,但至今仍在火的自动驾驶即将替代司机。但是它们并不具备通用性,就像问鼎了围棋界的谷歌机器 AlphaGo ,就算再厉害也只会下围棋这一件事(围棋曾被认为是计算机没法逾越的天花板,但被AlphaGo战胜,不过AlphaGo也只是属于弱人工智能),可是从整个人类科技发展来看,人类正在一步步开发着具备更通用性的人工智能,也就是有一天超越强人工智能而跨越起点的超人工智能,相信未来程序员唯一能做可能就是一段对话:
程序员:“ 嘿 Siri*:帮我开发一个掘金,顺便帮我安排一个叫 一颗剽悍的种子 的家伙写一篇JVM。”
程序员:“嘿,对了,Siri,看文章前别忘了给那家伙一键三连。”
Siri:“f*ck 又提需求。”
程序员:“什么?”
Siri:“安排”
(扯远了题外话,希望你能Get到人类追求通用性(懒)远不止在JVM中体现。)
JVM的全称Java Virtual Machine也就是java虚拟机,抛开Java虚拟机前缀Java,虚拟机其实就是在“虚拟(抽象)计算机”,也就是在操作系统之上再次虚拟出一台计算机,来屏蔽不同硬件和操作系统之间的差异(如果说操作系统是用户与物理资源之间的桥梁,那么JVM就是不同硬件和操作系统上的桥梁),JVM目的就是具备通用性,也就是我们常说的Java可以跨平台开发。
那么回到JVM这时容易懂了,JVM可以像计算机结构一样去运行所编写的程序,而JVM主要由:类装载器、运行时数据区、执行引擎、本地库接口这四个部分所构成。
我们知道一个可运行的程序其实不过是我们所定义的一个个 .java源代码文件组成(这些文件其实就是我们程序员对于事物的抽象,然后交由计算机帮我们实现)。而JVM只规定.class字节码文件格式,这样的好处很明显,那就是不仅只是Java可以运行在JVM上,而是只要是能生成.class字节码文件也都可以运行在JVM之上,所以Java虚拟机并不是Java语言专有的。所以JVM通过字节码存储格式统一了所有平台,字节码是构成平台无关性的基石。如:Python、Ruby、Scala等语言(可以说JVM野心真大!)。
所以.java文件想要在JVM上被执行,就必须先由javac编译器转成后.class再交给Class Loader 类装载器去进行类的加载等。而这也相当于开始像计算机结构一样的输入设备正式的进去到整个机器内部。如下图所示:
类装载器执行过程说到虚拟机类装载器,就不得不说类加载的机制,而一套机制就一定会有一个过程,也就是一个类进入入口(类装载器)到虚拟机中必经的整个生命周期:Loading 加载、Linking 连接、Initialization 初始化、Using 使用、Unlading 卸载。如下图所示: