jvm

每個程序員都該瞭解的JVM - JAVA虛擬機介紹

JAVA虛擬機介紹

這篇是關於JVM的High Level介紹 我們會介紹

虛擬機歷史

虛擬機命名理由

虛擬機大概念

虛擬機流程圖

準備好踏上理解艱澀JVM的旅程了嗎 Let’s go!

前世今生

1991年 太陽電腦(Sun MicroSystems, 2010年被Oracle收購)想要開發可以操控智慧型家電(微波爐 電視機)或是讓智慧型家電彼此溝通的新技術 於是設立了一個團隊來研發 並把這個計畫稱為綠色計畫(Green Project)

這個計畫難是難在對象是家電 有許多的限制如下

1.嵌入式系統的記憶體少:所以程式必須盡可能消耗少點的記憶體

2.跨平台性:我們不想要一個程式寫完後 拿到每個裝置去編譯才能執行 我們希望編譯一次 到處執行

3.安全性:程式在裝置間傳輸的過程 即使被惡意修改 也要確保裝置不會損壞

4.多線程支援

編譯器

最初 團隊打算使用C++ 但是C++無法達到跨平台的要求 比如說你在Linux系統編譯得到的Hello.exe不能直接拿到Window執行

Alt text

所以雖然C++在當時非常普及 但因為不符合要求 首先淘汰

直譯器

也許你會說 要跨平台還不簡單 我用直譯器就好啦

Alt text

直譯器可以讓你的高階語言不需經過編譯器 每跑一行就執行一行 比如說常聽到的Python跟Ruby 都是使用直譯器

所以只要每個裝置都有我的程式語言的直譯器 就可以達到跨平台啦

Alt text

但眾所皆知的 直譯器很慢 很慢 非常慢 因為他每跑一行才執行一行 有些編譯器做的最佳化它都不能做

那有沒有辦法又跨平台 又快呢 簡單 參在一起做撒尿牛丸

編譯器+直譯器

Alt text

Hello.class裡面存的就是Java bytecode 當然這個bytecode的格式我們會有另一個章節來介紹 現在你可以想成是C裡面的機器語言bytecode

bytecode是被編譯 壓縮並且最佳化過的 這樣跑起來就快多了 然後再把bytecode丟給每個平台專屬的JVM 他就會隨著硬體跟作業系統的不同做不一樣的處理 得到一樣的結果

這就是JAVA如何達成跨平台 不過當時想出這個方法的時候這個語言還不叫Java 叫做Oak

綠計畫後續

發明出Oak之後 原本想把這個語言用在電視機 電話等家電上面 但最後結論是這個語言太強 會給電視的使用者太多權限 而且當時對於智能家電的需求根本就不高 結果綠計畫胎死腹中

1994年 綠計畫一夥人發現當紅的全球資訊網world wide web的中心思想跟他們一開始對家電的想法很接近 都是資料在裝置之間傳來傳去 於是就把他們新發明的語言改名為Java 並寫了一個小型全球資訊網瀏覽器HotJava 1995年在SunWorld大會上公布了這個改變軟體生態已經30年的程式語言

比較重要的名字 是James Gosling 人稱Java之父 就是綠計畫的一員

JAVA問世之後 大家發現Java的風格跟C++挺像的 都是面向對象的語言 但Java沒有C++裡頭繁瑣的指針pointer 改成引用reference 還移除多重繼承 並增加垃圾回收的功能 最重要的當然就是一次編寫 到處運行的特性

1998年 推出JDK1.2 改名為Java 2 Platform 不僅如此 還相當有野心 連推三個版本

J2SE 標準版 進攻Desktop

J2EE 企業版 進攻伺服器

J2ME 微型版 進攻機上盒 行動電話和PDA

多麼有遠見 基本上目標就是 有一個方向成功就從此一帆風順

可想而知 最成功的就是J2EE 搭上互聯網順風車 所有特性都符合物聯網的伺服器需求

跨平台 安全 快 容易使用(面向對象)

Alt text

開發者數目快速擴張 一些支持C語言的巨頭都紛紛表示有興趣 其中IBM更是其中霸主 快速推出網頁伺服器WebSphere 再推出一個巨砲IDE - Eclipse 加上自身早就很強的硬體 直接一條龍的產品線(硬體+軟體+伺服器) IBM當時的三駕馬車完全就有如十年前谷歌的三駕馬車(MapReduce, BigTable, GFS) 直接營收一飛沖天

之後不少異軍突起 想佔領伺服器的這塊大餅 比較有名的就是Ruby on rails跟PHP 但基本對Java構不成太大威脅

2006年Hadoop橫空出世 底層也是使用Java來完成map/reduce 此後海量數據的運算崛起也助了Java一臂之力

2008年Android降臨地表 Google的大力支持 讓Java再度來到前所未有的高峰

2020年 每個程序員都要懂的JVM 粉墨登場 讓大家對於Java底層的未知領域一清二楚 降低了Java 30年來學習的門檻 揭開了JVM長年以來的神秘面紗

那為什麼JAVA虛擬機要叫JAVA虛擬機

我看了很多關於虛擬機的書 幾乎沒有人回答這個問題 我認為要先了解這個問題的答案 對於之後的理解有極大的幫助

首先 要先知道什麼是虛擬機 顧名思義 虛擬機就不是實體機器 他是用軟體模擬(實作)一個具有完整功能的硬體 這個模擬硬體的東西就叫虛擬機 虛擬機可以像實體機器一樣執行程式

用日常生活的例子 即使你買的是Window的電腦 你也常聽到有人用虛擬機安裝Linux的作業系統 安裝完後你就可以在虛擬機中執行Linux的程序指令 就好像再用Linux一樣 你完全不用管實際底層到底是什麼硬體

鋪梗鋪得有點明顯 看到上面一段你大概知道下一段要接什麼了 沒錯!這個理念跟我們的跨平台根本一模一樣 所以JAVA也用了跟虛擬機一樣的理念 不管你的底層是什麼硬體什麼作業系統 只要你有了Java虛擬機 你就可以在Java虛擬機中執行java bytecode 你完全不用管實際底層到底是什麼硬體

所以你寫java 你編譯java不是為了要讓你的程序跑在特定Linux或是某台Window上 你是為了要讓你的程序跑在JVM上

原來虛擬機這麼方便

但為了要達成這個 編寫一次 到處執行 JVM必須要有很嚴謹的規範 才能更讓每一個不同機器上的JVM拿到一樣的bytecode跑出一樣的結果

JAVA 虛擬機三個概念

規範 實作 跟 運行時實例

規範(specification):

所有人寫Java程式不再需要考慮是在哪個機器上或是作業系統上跑 只需要對JVM編寫 要達成這個目的 就有許多嚴格的要求必須遵守 Oracle發布的Java Virtual Machine Specification就是所有要實作JVM的人必須要遵守的規範 只要你照著規範走 任何人都可以實作自己的虛擬機

實作(implementation):

有規範就有實作 其中實作的最有名的就屬以下兩位仁兄

Oracle HotSpot JVM

IBM’s JVM

(你在你的終端機輸入 java -version 就可以看到你的虛擬機是誰實作的)

運行時實例(runtime instance):

有實作就有運行時實例 當你在執行 java Hello的時候 一個JVM的instance就會被創建在記憶體裡面 然後開始加載Hello文件

注意每一個運行時實例只會跑一個java應用 所以要是你在終端機連輸入五次java Hello 會生出五個運行時實例去跑五個程式

JVM 架構

下圖是組成一個JVM的所有主要元件

Alt text

不用擔心 我們會討論所有的元件 讓JVM從此不再可怕