隨着Java以及Java社區的不斷壯大,Java也早已再也不是簡簡單單的一門計算機語言了,它更是一個平臺、一種文化、一個社區。java
做爲一個平臺,Java虛擬機扮演着舉足輕重的做用編程
做爲一種文化,Java幾乎成爲了「開源」的代名詞。bootstrap
做爲一個社區緩存
每一個語言都須要轉換成字節碼文件,最後轉換的字節碼文件都能經過Java虛擬機進行運行和處理。安全
隨着Java7的正式發佈,Java虛擬機的設計者們經過JSR-292規範基本實如今Java虛擬機平臺上運行非Java語言編寫的程序。bash
Java虛擬機根本不關心運行在其內部的程序究竟是使用何種編程語言編寫的,它只關心「字節碼」文件。也就是說Java虛擬機擁有語言無關性,並不會單純地與Java語言「終身綁定」,只要其餘編程語言的編譯結果知足幷包含Java虛擬機的內部指令集、符號表以及其餘的輔助信息,它就是一個有效的字節碼文件,就可以被虛擬機所識別並裝載運行。服務器
字節碼網絡
咱們平時說的java字節碼,指的是用java語言編譯成的字節碼。準確的說任何能在jvm平臺上執行的字節碼格式都是同樣的。因此應該統稱爲:jvm字節碼。架構
不一樣的編譯器,能夠編譯出相同的字節碼文件,字節碼文件也能夠在不一樣的JVM上運行。併發
Java虛擬機與Java語言並無必然的聯繫,它只與特定的二進制文件格式——Class文件格式所關聯,Class文件中包含了Java虛擬機指令集(或者稱爲字節碼、Bytecodes)和符號表,還有一些其餘輔助信息。
多語言混合編程
Java平臺上的多語言混合編程正成爲主流,經過特定領域的語言去解決特定領域的問題是當前軟件開發應對日趨複雜的項目需求的一個方向。
試想一下,在一個項目之中,並行處理用clojure語言編寫,展現層使用JRuby/Rails,中間層則是Java,每一個應用層都將使用不一樣的編程語言來完成。並且,接口對每一層的開發者都是透明的,各類語言之間的交互不存在任何困難,就像使用本身語言的原生API同樣方便,由於它們最終都運行在一個虛擬機之上。
對這些運行於Java虛擬機之上Java以外的語言,來自系統級的、底層的支持正在迅速加強,以JSR-292爲核心的一系列項目和功能改進(如Da Vinci Machine項目、Nashorn引擎、InvokeDynamic指令、java.lang.invoke包等),推進Java虛擬機從「Java語言的虛擬機」向 「多語言虛擬機」的方向發展。
虛擬機(Virtual Machine),就是一臺虛擬的計算機。它是一款軟件,用來執行一系列虛擬計算機指令。大致上,虛擬機能夠分爲系統虛擬機和程序虛擬機。
不管是系統虛擬機仍是程序虛擬機,在上面運行的軟件都被限制於虛擬機提供的資源中。
Java虛擬機是一臺執行Java字節碼的虛擬計算機,它擁有獨立的運行機制,其運行的Java字節碼也未必由Java語言編譯而成。
JVM平臺的各類語言能夠共享Java虛擬機帶來的跨平臺性、優秀的垃圾回器,以及可靠的即時編譯器。
Java技術的核心就是Java虛擬機(JVM,Java Virtual Machine),由於全部的Java程序都運行在Java虛擬機內部。
Java虛擬機就是二進制字節碼的運行環境,負責裝載字節碼到其內部,解釋/編譯爲對應平臺上的機器指令執行。每一條Java指令,Java虛擬機規範中都有詳細定義,如怎麼取操做數,怎麼處理操做數,處理結果放在哪裏。
特色:
JVM是運行在操做系統之上的,它與硬件沒有直接的交互。
Java的體系結構:
執行引擎包含三部分:解釋器,及時編譯器,垃圾回收器。
只是能生成被Java虛擬機所能解釋的字節碼文件,那麼理論上就能夠本身設計一套代碼了
Java編譯器輸入的指令流基本上是一種基於棧的指令集架構,另一種指令集架構則是基於寄存器的指令集架構。
這兩種架構之間的區別:
基於棧式架構的特色
基於寄存器架構的特色
舉例1
一樣執行2+3這種邏輯操做,其指令分別以下:
基於棧的計算流程(以Java虛擬機爲例):
0: iconst_2 // 常量2入棧 1: istore_1 2: iconst_3 // 常量3入棧 3: istore_2 4: iload_1 5: iload_2 6: iadd // 常量2/3出棧,執行相加 7: istore_3 // 結果5入棧 8: return
而基於寄存器的計算流程:
mov eax,2 //將eax寄存器的值設爲1 add eax,3 //使eax寄存器的值加3
字節碼反編譯
咱們編寫一個簡單的代碼,而後查看一下字節碼的反編譯後的結果:
public class StackStruTest { public static void main(String[] args) { int i = 2 + 3; } }
而後咱們找到編譯後的 class文件,使用下列命令進行反編譯:
javap -v StackStruTest.class
獲得的文件爲:
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: iconst_5 1: istore_1 2: return LineNumberTable: line 10: 0 line 14: 2 LocalVariableTable: Start Length Slot Name Signature 0 3 0 args [Ljava/lang/String; 2 1 1 i I
假若代碼爲:
public class StackStruTest { public static void main(String[] args) { int i = 2; int j = 3; int k = i + j; } }
咱們找到編譯後的 class文件,使用下列命令進行反編譯獲得後的文件:
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: iconst_2 1: istore_1 2: iconst_3 3: istore_2 4: iload_1 5: iload_2 6: iadd 7: istore_3 8: return LineNumberTable: line 11: 0 line 12: 2 line 13: 4 line 14: 8 LocalVariableTable: Start Length Slot Name Signature 0 9 0 args [Ljava/lang/String; 2 7 1 i I 4 5 2 j I 8 1 3 k I
總結
因爲跨平臺性的設計,Java的指令都是根據棧來設計的。不一樣平臺CPU架構不一樣,因此不能設計爲基於寄存器的。
棧的特色:
Java虛擬機的啓動是經過引導類加載器(bootstrap class loader)建立一個初始類(initial class)來完成的,這個類是由虛擬機的具體實現指定的。
有以下的幾種狀況:
HotSpot歷史最初由一家名爲「Longview Technologies」的小公司設計。1997年,此公司被sun收購;2009年,Sun公司被甲骨文收購。
在JDK1.3版本時,HotSpot VM就成爲默認虛擬機。
目前Hotspot佔有絕對的市場地位,是絕對的主流。
HotSpot指的就是它的熱點代碼探測技術。
JRockit專一於服務器端應用。
大量的行業基準測試顯示,JRockit JVM是世界上最快的JVM。
優點:全面的Java運行時解決方案組合。
2008年,JRockit被Oracle收購。
Oracle表達了整合兩大優秀虛擬機的工做,大體在JDK8中完成。整合的方式是在HotSpot的基礎上,移植JRockit的優秀特性。
全稱:IBM Technology for Java Virtual Machine,簡稱IT4J,內部代號:J9。
市場定位與HotSpot接近,服務器端、桌面應用、嵌入式等多用途VM普遍用於IBM的各類Java產品。
目前,有影響力的三大商用虛擬機之一,也號稱是世界上最快的Java虛擬機。
2017年左右,IBM發佈了開源J9VM,命名爲openJ9,交給EClipse基金會管理,也稱爲Eclipse OpenJ9。
前面三大「高性能Java虛擬機」使用在通用硬件平臺上這裏Azu1VW和BEALiquid VM是與特定硬件平臺綁定、軟硬件配合的專有虛擬機I
Azul VM是Azu1Systems公司在HotSpot基礎上進行大量改進,運行於Azul Systems公司的專有硬件Vega系統上的ava虛擬機。
每一個Azu1VM實例均可以管理至少數十個CPU和數百GB內存的硬件資源,並提供在巨大內存範圍內實現可控的GC時間的垃圾收集器、專有硬件優化的線程調度等優秀特性。
2010年,AzulSystems公司開始從硬件轉向軟件,發佈了本身的zing JVM,能夠在通用x86平臺上提供接近於Vega系統的特性。
Oracle在Java ME產品線上的兩款虛擬機爲:CDC/CLDC HotSpot Implementation VM KVM(Kilobyte)是CLDC-HI早期產品目前移動領域地位尷尬,智能機被Angroid和IOS二分天下。
KVM簡單、輕量、高度可移植,面向更低端的設備上還維持本身的一片市場。
早在1996年Java1.0版本的時候,Sun公司發佈了一款名爲sun classic VM的Java虛擬機,它同時也是世界上第一款商用Java虛擬機,JDK1.4時徹底被淘汰。
這款虛擬機內部只提供解釋器。如今還有及時編譯器,所以效率比較低,而及時編譯器會把熱點代碼緩存起來,那麼之後使用熱點代碼的時候,效率就比較高。
若是使用JIT編譯器,就須要進行外掛。可是一旦使用了JIT編譯器,JIT就會接管虛擬機的執行系統。解釋器就再也不工做。解釋器和編譯器不能配合工做。
如今hotspot內置了此虛擬機。
Apache也曾經推出過與JDK1.5和JDK1.6兼容的Java運行平臺Apache Harmony。
它是IElf和Inte1聯合開發的開源JVM,受到一樣開源的openJDK的壓制,Sun堅定不讓Harmony得到JCP認證,最終於2011年退役,IBM轉而參與OpenJDK
雖然目前並無Apache Harmony被大規模商用的案例,可是它的Java類庫代碼吸納進了Android SDK。
由AliJVM團隊發佈。阿里,國內使用Java最強大的公司,覆蓋雲計算、金融、物流、電商等衆多領域,須要解決高併發、高可用、分佈式的複合問題。有大量的開源產品。
基於openJDK開發了本身的定製版本AlibabaJDK,簡稱AJDK。是整個阿里Java體系的基石。
基於openJDK Hotspot VM發佈的國內第一個優化、深度定製且開源的高性能服務器版Java虛擬機。
taobao vm應用在阿里產品上性能高,硬件嚴重依賴inte1的cpu,損失了兼容性,但提升了性能。
目前已經在淘寶、天貓上線,把oracle官方VM版本所有替換了。
谷歌開發的,應用於Android系統,並在Android2.2中提供了JIT,發展迅猛。
Dalvik y只能稱做虛擬機,而不能稱做「Java虛擬機」,它沒有遵循 Java虛擬機規範
不能直接執行Java的Class文件
基於寄存器架構,不是jvm的棧架構。
執行的是編譯之後的dex(Dalvik Executable)文件。執行效率比較高。
Android 5.0使用支持提早編譯(Ahead of Time Compilation,AoT)的ART VM替換Dalvik VM。
2018年4月,oracle Labs公開了GraalvM,號稱 "Run Programs Faster Anywhere",勃勃野心。與1995年java的」write once,run anywhere"遙相呼應。
GraalVM在HotSpot VM基礎上加強而成的跨語言全棧虛擬機,能夠做爲「任何語言」
的運行平臺使用。語言包括:Java、Scala、Groovy、Kotlin;C、C++、Javascript、Ruby、Python、R等
支持不一樣語言中混用對方的接口和對象,支持這些語言使用已經編寫好的本地庫文件
工做原理是將這些語言的源代碼或源代碼編譯後的中間格式,經過解釋器轉換爲能被Graal VM接受的中間表示。Graal VM提供Truffle工具集快速構建面向一種新語言的解釋器。在運行時還能進行即時編譯優化,得到比原生編譯器更優秀的執行效率。
總結
具體JVM的內存結構,其實取決於其實現。不一樣廠商的JVM,或者同一廠商發佈的不一樣版本,都有可能存在必定差別。咱們學習及開發都主要以Oracle HotSpot VM爲默認虛擬機。