01 - JVM 與 Java 體系結構
1 - 前言
大部分 Java 開發人員,除會在項目中使用到與 Java 平台相關的各種高精尖技術,對於 Java 技術的核心 Java 虛擬機了解甚少。
開發人員如何看待上層框架:
- 一些有一定工作經驗的開發人員,打心眼兒里覺得 SSM 、微服務等上層技術才是重點,基礎技術並不重要,這其實是一種本末倒置的“病態”。
- 如果我們把核心類庫的 AP エ比做數學公式的話,那么 Java 虛擬機的知識就好比公式的推導過程。
計算機系統體系對我們來說越來越遠,在不了解底層實現方式的前提下,通過高級語言很容易編寫程序代碼。但事實上計算機並不認識高級語言。
我們為什么要學習 JVM ?
- 面試的需要( BATJ 、 TMD 、 PKQ 等面試都愛問)
- 中高級程序員必備技能
- 項目管理、調優的需要
- 追求極客的精神
- 比如:垃圾回收算法、 JIT 、底層原理
2 - 面向人群及參考書目
官方參考書目:
- The Java Virtual Machine Specification-JavaSE7
- The Java Virtual Machine Specification-JavaSE8
- The Java Virtual Machine Specification-JavaSE11
Java 8 和 11 是長期支持版本,目前國內主流是 8,之后會是 11。
中文參考書目:
-
Java 虛擬機規范(Java SE 8版)
官方文檔漢化,僅適合平時參考
-
深入理解 Java 虛擬機
-
深入理解 JVM & G1 GC
-
揭秘 Java 虛擬機
-
Java 虛擬機基礎教程
-
實戰 Java 虛擬機
-
Java 虛擬機精講
-
碼出高效 Java 開發手冊
3 - Java 及 JVM 簡介
Java 長期占據 TIOBE 語言熱度排行榜第一(現在已被 C 反超),不是說明 Java 語言多么優越,只是因為龐大的生態、夠用的功能、沒有致命的缺陷。
世界上沒有最好的編程語言,只有最適用於具體應用場景的編程語言。
Java : 跨平台的語言
JVM : 跨語言的平台
-
隨着 Java 7 的正式發布,Java 虛擬機的設計者們通過 JSR-292 規范基本實現在 Java 虛擬機平台上運行非 Java 語言編寫的程序。
-
Java 虛擬機根本不關心運行在其內部的程序到底是使用何種編程語言編寫的,它只關心 “字節碼” 文件。也就是說 Java 虛擬機擁有語言無關性,並不會單純地與 Java 語言 “終身綁定”,只要其他編程語言的編譯結果滿足並包含 Java 虛擬機的內部指令集、符號表以及其他的輔助信息,它就是一個有效的字節碼文件,就能夠被虛擬機所識別並裝載運行。
Java 不是最強大的語言,但是 JVM 是最強大的虛擬機。
字節碼
-
我們平時說的 java 字節碼,指的是用 java 語言編譯成的字節碼。准確的說任何能在 JVM 平台上執行的字節碼格式都是一樣的。所以應該統稱為 jvm 字節碼
-
不同的編譯器,可以編譯出相同的字節碼文件,字節碼文件也可以在不同的 JVM 上運行。
-
Java 虛擬機與 Java 語言並沒有必然的聯系,它只與特定的二進制文件格式 —— Class 文件格式所關聯, Class 文件中包含了 Java 虛擬機指令集(或者稱為字節碼、 Bytecodes )和符號表,還有一些其他輔助信息。
多語言混合編程
Java 平台上的多語言混合編程正成為主流,通過特定領域的語言去解決特定領域的問題是當前軟件開發應對日趨復雜的項目需求的一個方向。
試想一下,在一個項目之中,並行處理用 Clojure 語言編寫,展示層使用 JRuby/Rails ,中間層則是 Java ,每個應用層都將使用不同的編程語言來完成,而且,接口對每一層的開發者都是透明的,各種語言之間的交互不存在任何困難,就像使用自己語言的原生 API 一樣方便,因為它們最終都運行在一個虛擬機之上。
對這些運行於 Java 虛擬機之上、 Java 之外的語言,來自系統級的、底層的支持正在迅速增強,以 JSR-292 為核心的一系列項目和功能改進(如 DaVinci Machine 項目、 Nashore 引擎、 InvokeDynamic 指令、 java.lang.invoke
包等),推動 Java 虛擬機從 “Java 語言的虛擬機” 向 “多語言虛擬機” 的方向發展。
4 - Java 發展的重大事件
-
1990 年,在 Sun 計算機公司中,由 Patrick Naughton 、 Mike Sheridan 及 James Gosling 領導的小組 Green Team ,開發出的新的程序語言,命名為 Oak ,后期命名為 Java
-
1995 年,Sun 正式發布 Java 和 HotJava 產品,Java 首次公開亮相。
-
1996 年 1 月 23 日 Sun Microsystems 發布了 JDK 1.0 。
-
1998 年, JDK 1.2 版本發布。同時,Sun發布了 JSP/Servlet 、 EJB 規范,以及將 Java 分成了 J2EE 、 J2SE 和 J2ME 。這表明了 Java 開始向企業、桌面應用和移動設備應用 3 大領域挺進。
-
2000 年, JDK 1.3 發布, Java HotSpot Virtual Machine 正式發布,成為 Java 的默認虛擬機。
-
2002 年, JDK 1.4 發布,古老的 Classic 虛擬機退出歷史舞台。
-
2003 年年底,Java 平台的 Scala 正式發布,同年 Groovy 也加入了 Java 陣營。
-
2004 年, JDK 1.5 發布。同時 JDK 1.5 改名為 JavaSE 5.0 。
-
2006 年, JDK 6 發布。同年,Java 開源並建立了 OpenJDK 。順理成章, Hotspot 虛擬機也成為了 OpenJDK 中的默認虛擬機。
-
2007 年, Java 平台迎來了新伙伴 Clojure
-
2008 年, Oracle 收購了 BEA ,得到了 JRockit 虛擬機。
-
2009 年, Twitter 宣布把后台大部分程序從 Ruby 遷移到 Scala ,這是 Java 平台的又ー次大規模應用。
-
2010 年, Oracle 收購了 Sun ,獲得 Java 商標和最具價值的 HotSpot 虛擬機。此時, Oracle 擁有市場占用率最高的兩款虛擬機 HotSpot 和 JRockit ,並計划在未來對它們進行整合: HotRockit
-
2011 年, JDK 7發布。在 JDK 1.7u4 中,正式啟用了新的垃圾回收器 G1 。
-
2017 年, JDK 9發布。將 G1 設置為默認 GC ,替代 CMS
-
同年,IBM 的 J9 開源,形成了現在的 Open J9 社區
-
2018 年, Android 的 Java 侵權案判決, Goggle 賠償 Oracle 88 億美元
-
同年, Oracle 宣告 JavaEE 成為歷史名詞, JDBC 、 JMS 、 Servlet 贈予 Eclipse 基金會
-
同年, JDK 11 發布,LTS 版本的 JDK ,發布革命性的 ZGC,調整 JDK 授權許可
-
2019 年,JDK 12 發布,加入 Redhat 領導開發的 Shenandoah GC
OpenJDK 和 OracleJDK:
在 JDK11 之前, OracleJDK 中還會存在一些 OpenJDK 中沒有的、閉源的功能。但在 JDK11 中,我們可以認為 OpenJDK 和 OracleJDK 代碼實質上已經完全一致的程度。
5 - 虛擬機與 Java 虛擬機
虛擬機
所謂虛擬機( Virtual Machine ),就是一台虛擬的計算機。它是一款軟件,用來執行一系列虛擬計算機指令。大體上,虛擬機可以分為系統虛擬機和程序虛擬機
-
大名鼎鼎的 Visual Box , Vmware 就屬於系統虛擬機,它們完全是對物理計算機的仿真,提供了一個可運行完整操作系統的軟件平台。
-
程序虛擬機的典型代表就是 Java 虛擬機,它專門為執行單個計算機程序而設計,在 Java 虛擬機中執行的指令我們稱為 Java 字節碼指令
無論是系統虛擬機還是程序虛擬機,在上面運行的軟件都被限制於虛擬機提供的資源中
Java 虛擬機
- Java 虛擬機是一台執行 Java 字節碼的虛擬計算機,它擁有獨立的運行機制,其運行的 Java 字節碼也未必由 Java 語言編譯而成。
- JVM 平台的各種語言可以共享 Java 虛擬機帶來的跨平台性、優秀的垃圾回器,以及可靠的即時編譯器。
- Java 技術的核心就是 Java 虛擬機( JVM , Java Virtual Machine ),因為所有的 Java 程序都運行在 Java 虛擬機內部。
作用
Java 虛擬機就是二進制字節碼的運行環境,負責裝載字節碼到其內部,解釋/編譯為對應平台上的機器指令執行。每一條 Java 指令,Java 虛擬機規范中都有詳細定義,如怎么取操作數,怎么處理操作數,處理結果放在哪里。
特點
- 一次編譯,到處運行
- 自動內存管理
- 自動垃圾回收功能
JVM 的位置
JVM 是運行在操作系統之上的,它與硬件沒有直接的交互。
6 - JVM 的整體結構
- HotSpot VM 是目前市面上高性能虛擬機的代表作之一。
- 它采用解釋器與即時編譯器並存的架構。
- 在今天, Java 程序的運行性能早已脫胎換骨,已經達到了可以和 C/C++ 程序一較高下的地步。
7 - Java 代碼執行流程
8 - JVM 的架構模型
Java 編譯器輸入的指令流基木上是一種基於棧的指令集架構,另外一種指令集架構則是基於寄存器的指令集架構。
具體來說,這兩種架構之間的區別:
- 基於棧式架構的特點
- 設計和實現更簡單,適用於資源受限的系統;
- 避開了寄存器的分配難題:使用零地址指令方式分配。
- 指令流中的指令大部分是零地址指令,其執行過程依賴於操作棧。指令集更小,編譯器容易實現。
- 不需要硬件支持,可移植性更好,更好實現跨平台
- 基於寄存器架構的特點
- 典型的應用是 x86 的二進制指令集:比如傳統的 PC 以及 Android 的 Davlik 虛擬機。
- 指令集架構則完全依賴硬件,可移植性差
- 性能優秀和執行更高效
- 花費更少的指令去完成一項操作。
- 在大部分情況下,基於寄存器架構的指令集往往都以一地址指令、二地址指令和三地址指令為主,而基於棧式架構的指令集卻是以零地址指令為主。
總結:
由於跨平台性的設計, Java 的指令都是根據棧來設計的。不同平台 CPU 架構不同,所以不能設計為基於寄存器的。優點是跨平台,指令集小,編譯器容易實現,缺點是性能下降,實現同樣的功能需要更多的指令。
時至今日,盡管嵌入式平台已經不是 Java 程序的主流運行平台了(准確來說應該是 HotSpotVM 的宿主環境己經不局限於嵌入式平台了),那么為什么不將架構更換為基於寄存器的架構呢?
原因:設計和實現更簡單;在非資源受限的環境中,基於棧的設計仍然可用。
棧:跨平台性、指令集小、指令多;執行性能比寄存器差
9 - JVM 的生命周期
-
虛擬機的啟動
Java 虛擬機的啟動是通過引導類加載器( bootstrap class loader )創建個初始類( initial class )來完成的,這個類是由虛擬機的具體實現指定的。
-
虛擬機的執行
- 一個運行中的 Java 虛擬機有着一個清晰的任務:執行 Java 程序。
- 程序開始執行時他才運行,程序結束時他就停止。
- 執行一個所謂的 Java 程序的時候,真真正正在執行的是一個叫做 Java 虛擬機的進程。
-
虛擬機的退出
有如下的幾種情況:
-
程序正常執行結束
-
程序在執行過程中遇到了異常或錯誤而異常終止
-
由於操作系統出現錯誤而導致中 Java 虛擬機進程終止
-
某線程調用 Runtime 類或 System 類的 exit 方法,或 Runtime 類的 halt 方法,並且 Java 安全管理器也允許這次 exit 或 halt 操作。
-
除此之外, JNI ( Java Native Interface )規范描述了用 JNI Invocation API 來加載或卸載 Java 虛擬機時,Java 虛擬機的退出情況
-
10 - JVM 發展歷程
Sun Classic VM
- 早在 1996 年 Java 1.0 版本的時候, Sun 公司發布了一款名為 Sun Classic VM 的 J ava 虛擬機,它同時也是世界上第一款商用 Java 虛擬機, JDK1.4 時完全被淘汰。
- 這款虛擬機內部只提供解釋器。如果使用 JIT 編譯器,就需要進行外掛。但是一旦使用了 J 編譯器, J エ T 就會接管虛擬機的執行系統。解釋器就不再工作。解釋器和編譯器不能配合工作
- 現在 hotspot 內置了此虛擬機。
Exact VM
-
為了解決上一個虛擬機問題,jdk1.2 時, sun 提供了此虛擬機。
-
Exact Memory Management :准確式內存管理
-
也可以叫 Non-Conservative / Accurate Memory Management
-
虛擬機可以知道內存中某個位置的數據具體是什么類型。
-
-
具備現代高性能虛擬機的雛形
- 熱點探測
- 編譯器與解釋器混合工作模式
-
只在 Solaris 平台短暫使用,其他平台上還是 classic vm
-
英雄氣短,終被 Hotspot 虛擬機替換
SUN 公司的 Hotspot VM
- Hotspot 歷史
- 最初由一家名為 “ Longview Technologies " 的小公司設計
- 1997 年,此公司被 Sun 收購; 2009 年, Sun 公司被甲骨文收購。
- JDK 1. 3 時, Hotspot VM 成為默認虛擬機
- 目前 Hotspot 占有絕對的市場地位,稱霸武林。
- 不管是現在仍在廣泛使用的 JDK 6,還是使用比例較多的 JDK 8中,默認的虛擬機都是 Hotspot
- Sun / Oracle JDK 和 OpenJDK 的默認虛擬機
- 因此本課程中默認介紹的虛擬機都是 Hotspot,相關機制也主要是指 Hotspot 的 GC 機制。(比如其他兩個商用虛擬機都沒有方法區的概念)
- 從服務器、桌面到移動端、嵌入式都有應用。
- 名稱中的 Hotspot 指的就是它的熱點代碼探測技術。
- 通過計數器找到最具編譯價值代碼,觸發即時編譯或棧上替換
- 通過編譯器與解釋器協同工作,在最優化的程序響應時間與最佳執行性能中取得平衡
BEA 的 JRockit
- 專注於服務器端應用
- 它可以不太關注程序啟動速度,因此 JRockit 內部不包含解析器實現,全部代碼都靠即時編譯器編譯后執行。
- 大量的行業基准測試顯示, JRockit JVM 是世界上最快的 JVM 。
- 使用 JRockit 產品,客戶已經體驗到了顯著的性能提高(一些超過了 70%)和硬件成本的減少(達 50%)。
- 優勢:全而的 Java 運行時解決方案組合
- JRockit 面向延遲敏感型應用的解決方案 JRockit Real Time 提供以毫秒或微秒級的 JVM 響應時間,適合財務、軍事指揮、電信網絡的需要
- MissionControl 服務套件,它是一組以極低的開銷來監控、管理和分析生產壞境中的應用程序的工具。
- 2008 年, BEA 被 Oracle 收購
- Oracle 表達了整合兩大優秀虛擬機的工作,大致在 JDK8 中完成。整合的方式是在 Hotspot 的基礎上,移植 JRockit的優秀特性。
- 高斯林:目前就職於谷歌,研究人工智能和水下機器人
IBM 的 J9
- 全稱:IBM Technology for Java Virtual Machine ,簡稱 IT4J ,內部代號: J9
- 市場定位與 Hotspot 接近,服務器端、桌而應用、嵌入式等多用途 VM
- 廣泛用於 IBM 的各種 Java 產品。
- 目前,有影響力的三大商用虛擬機之一,也號稱是世界上最快的Java虛擬機。
- 2017 年左右,IBM 發布了開源 J9 VM ,命名為 OpenJ9,交給 Eclipse 基金會管理,也稱為 Eclipse OpenJ9
KVM 和 CDC/CLDC Hotspot
- Oracle 在 Java ME 產品線上的兩款虛擬機為: CDC/CLDC Hotspot Implementation VM
- KVM(Kilobyte )是 CLDC-HI 早期產品
- 目前移動領域地位尷尬,智能平機被 Android 和 IOS 二分天下。
- KVM 簡單、輕量、高度可移植,面向更低端的設備上還維持自己的一片市場
- 智能控制器、傳感器
- 老人手機、經濟欠發達地區的功能手機
- 所有的虛擬機的原則:一次編譯,到處運行。
Azul VM
- 前面三大 “高性能 Java 虛擬機” 使用在通用硬件平台上
- 這里 Azul VM 和 BEA Liquid VM 是與特定硬件平台綁定、軟硬件配合的專有虛擬機
- 高性能 Java 虛擬機中的戰斗機。
- Azul VM 是 Azul Systems 公司在 Hotspot 基礎上進行大量改進,運行於 Azul Systems 公司的專有硬件 Vega 系統上的 Java 虛擬機。
- 每個 Azul VM 實例都可以管理至少數十個 CPU 和數百 GB 內存的硬件資源,並提供在巨大內存范圍內實現可控的 GC 時間的垃圾收集器、專有硬件優化的線程調度等優秀特性
- 2010 年,Azul Systems 公司開始從硬件轉向軟件,發布了自己的 Zing JVM ,可以在通用 x86 平台上提供接近於 Vega 系統的特性。
Liquid VM
- 高性能 Java 虛擬機中的戰斗機。
- BEA 公司開發的,直接運行在自家 Hypervisor 系統上
- Liquid VM 即是現在的 JRockit VE( Virtual Edition ), Liquid VM 不需要操作系統的支持,或者說它自己本身實現了一個專用操作系統的必要功能,如線程調度、文件系統、網絡支持等。
- 隨着 JRockit 虛擬機終止開發, Liquid VM項目也停止了。
Apache Harmony
- Apache 也曾經推出過與 JDK 1.5 和 JDK 1.6 兼容的 Java 運行平台 Apache Harmony
- 它是 IBM 和 Intel 聯合開發的開源 JVM ,受到同樣開源的 OpenJDK 的壓制,Sun 堅決不讓 Harmony 獲得 JCP 認證,最終於 2011 年退役, IBM 轉而參與 OpenJDK
- 雖然目前並沒有 Apache Harmony 被大規模商用的案例,但是它的 Java 類庫代碼吸納進了 Android SDK。
Microsoft JVM
- 微軟為了在工 E3 瀏覽器中支持 Java Applets ,開發了 Microsoft JVM 。
- 只能在 Windows 平台下運行。但確是當時 Windows 下性能最好的 Java VM 。
- 1997 年, Sun 以侵犯商標、不正當競爭罪名指控微軟成功,賠了 Sun 很多錢。微軟在 Windows SP3 中抹掉了其 VM 。現在 Windows 上安裝的 JDK 都是 Hotspot
TaobaoJVM
- 由 Ali JVM團隊發布。阿里,國內使用 Java 最強大的公司,覆蓋雲計算、金融、物流電商等眾多領域,需要解決高並發、高可用、分布式的復合問題。有大量的開源產品
- 基於 OpenJDK 開發了自己的定制版本 AlibabaJDK ,簡稱 AJDK。是整個阿里 Java體系的基石。
- 基於 OpenJDK Hotspot VM 發布的國內第一個優化、深度定制且開源的高性能服務器版 Java虛擬機。
- 創新的 GCIH( GC invisible heap )技術實現了 off-heap ,即將生命周期較長的 Java對象從 heap 中移到heap 之外,並且 GC 不能管理 GCIH 內部的 Java對象,以此達到降低 GC 的回收頻率和提升 GC 的回收效率的目的
- GCIH 中的對象還能夠在多個 Java虛擬機進程中實現共享
- 使用 crc32 指令實現 JVM intrinsic 降低 JNI 的調用開銷 \
- PMU hardware 的 Java profiling tool 和診斷協助功能
- 針對大數據場景的 ZenGC
- taobao vm 應用在阿里產品上性能高,硬件嚴重依賴 intel 的 cpu ,損失了兼容性,但提高了性能
- 目前已經在淘寶、天貓上線,把 Oracle 官方 JVM版木全部替換了。
Dalvik VM
- 谷歌開發的,應用於 Android 系統,並在 Android 2.2 中提供了 JIT ,發展迅猛。
- Dalvik vm 只能稱作虛擬機,而不能稱作“Java虛擬機”,它沒有遵循Java虛擬機規范
- 不能直接執行 Java 的 Class 文件
- 基於寄存器架構,不是 jvm 的棧架構
- 執行的是編譯以后的 dex( Dalvik Executable )文件。執行效率比較高
- 它執行的 dek( Dalvik Executable )文件可以通過 class 文件轉化而來,使用 Java 語法編寫應用程序,可以直接使用大部分的 Java api 等。
- Android 5. 0 使用支持提前編譯( Ahead of Time Compilation , AOT )的 ART VM 替換 Dalvik VM 。
Graal VM
- 2018 年 4 月, Oracle Labs 公開了 Graal VM,號稱 " Run Programs Faster Anywhere ",勃勃野心。
- 與 1995 年 Java 的 " write once, run anywhere " 遙相呼應。
- Graal VM 在 Hotspot VM 基礎上増強而成的跨語言全棧虛擬機,可以作為 “任何語言” 的運行平台使用。語言包括: Java 、Scala 、 Groovy 、 Kotlin ; C 、 C ++、 JavaScript、 Ruby、 Python 、 R 等
- 支持不同語言中混用對方的接口和對象,支持這些語言使用已經編寫好的本地庫文件
- 工作原理是將這些語言的源代碼或源代碼編譯后的中間格式,通過解釋器轉換為能被 Graal VM 接受的中間表示。Graal VM 提供 Truffle 工具集快速構建面向一種新語言的解釋器。在運行時還能進行即時編譯優化,獲得比原生編譯器更優秀的執行效率。
- 如果說 HotSpot 有一天真的被取代,Graal VM 希望最大。但是 Java 的軟件生態沒有絲毫變化
總結
還有許多其他 JVM
具體 JVM 的內存結構,其實取決於其實現,不同廠商的 JVM ,或者同一廠商發布的不同版本,都有可能存在一定差異。本套課程主要以 Oracle Hotspot VM 為默認虛擬機。