JVM概述

JVM是什麼

JVM全稱是Java Virtual Machine(Java虛擬機)。它之所以被稱之爲是“虛擬”的,就是因爲它僅僅是由一個規範來定義的抽象計算機。我們平時經常使用的Sun HotSpot虛擬機只是其中一個具體的實現(另外還有BEA JRockit、IBM J9等等虛擬機)。
JVM的設計目標是提供一個基於抽象規格描述的計算機模型,爲解釋程序開發人員提供很好的靈活性,同時也確保Java代碼可在符合該規範的任何系統上運行。JVM對其實現的某些方面給出了具體的定義,特別是對Java可執行代碼,即字節碼(Bytecode)的格式給出了明確的規格。這一規格包括操作碼和操作數的語法和數值、標識符的數值表示方式、以及Java類文件中的Java對象、常量緩衝池在JVM的存儲映象。這些定義爲JVM解釋器開發人員提供了所需的信息和開發環境。Java的設計者希望給開發人員以隨心所欲使用Java的自由。
JVM是java的核心和基礎,在java編譯器和os平臺之間的虛擬處理器。它是一種基於下層的操作系統和硬件平臺並利用軟件方法來實現的抽象的計算機,可以在上面執行java的字節碼程序。

JRE/JDK/JVM是什麼關係

JRE(JavaRuntimeEnvironment,Java運行環境),也就是Java平臺。所有的Java 程序都要在JRE下才能運行。普通用戶只需要運行已開發好的java程序,安裝JRE即可。
JDK(java Development Kit)是程序開發者用來來編譯、調試java程序用的開發工具包。JDK的工具也是Java程序,也需要JRE才能運行。爲了保持JDK的獨立性和完整性,在JDK的安裝過程中,JRE也是安裝的一部分。所以,在JDK的安裝目錄下有一個名爲jre的目錄,用於存放JRE文件。
JVM(JavaVirtualMachine,Java虛擬機)是JRE的一部分。它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。JVM有自己完善的硬件架構,如處理器、堆棧、寄存器等,還具有相應的指令系統。Java語言最重要的特點就是跨平臺運行。使用JVM就是爲了支持與操作系統無關,實現跨平臺。

JVM的生命週期

當啓動一個Java程序時,一個虛擬機實例也就誕生了。當該程序關閉退出,這個虛擬機實例也就隨之消亡。如果在同一臺計算機上同時運行三個Java程序,將得到三個Java虛擬機實例。每個Java程序都運行於它自己的Java虛擬機實例中。
JVM實例對應了一個獨立運行的java程序,它是進程級別。

1、啓動。
啓動一個Java程序時,一個JVM實例就產生了,任何一個擁有publicstatic void main(String[] args)函數的class都可以作爲JVM實例運行的起點

2、運行。
main()作爲該程序初始線程的起點,任何其他線程均由該線程啓動。JVM內部有兩種線程:守護線程和非守護線程,main()屬於非守護線程,守護線程通常由JVM自己使用,java程序也可以標明自己創建的線程是守護線程。

3、消亡。
當程序中的所有非守護線程都終止時,JVM才退出;若安全管理器允許,程序也可以使用Runtime類或者System.exit()來退出

JVM運行原理

操作系統裝入JVM是通過jdk中Java.exe來完成,通過下面4步來完成JVM環境。

1、JVM裝入環境。
JVM提供的方式是操作系統的動態連接文件。既然是文件那就存在一個裝入路徑的問題,Java是怎麼找這個路徑的呢?下面基於Windows的實現的分析。
首先查找jre路徑,Java是通過GetApplicationHomeapi來獲得當前的Java.exe絕對路徑,c:\jdk1.7.0_45\bin\Java.exe,然後截取到絕對路徑c:\jdk1.7.0_45\,判斷c:\jdk1.7.0_45\bin\Java.dll文件是否存在,如果存在就把c:\jdk1.7.0_45\作爲jre路徑,如果不存在則判斷c:\jdk1.7.0_45\jre\bin\Java.dll是否存在,如果存在這c:\jdk1.7.0_45\jre作爲jre路徑,如果不存在調用GetPublicJREHome查HKEY_LOCAL_MACHINE\Software\JavaSoft\JavaRuntime Environment\“當前JRE版本號”\JavaHome的路徑爲jre路徑。
然後裝載JVM.cfg文件。在我們的jdk目錄中jre\bin\server和jre\bin\client都有JVM.dll文件存在,而Java正是通過JVM.cfg配置文件來管理這些不同版本的JVM.dll的。
最後獲得JVM.dll的路徑,JRE路徑+\bin+\JVM類型字符串+\JVM.dll就是JVM的文件路徑了,但是如果在調用Java程序時用-XXaltJVM=參數指定的路徑path,就直接用path+\JVM.dll文件做爲JVM.dll的文件路徑。

2、裝載JVM.dll
通過第一步已經找到了JVM的路徑,Java通過LoadJavaVM來裝入JVM.dll文件。裝入工作很簡單,就是調用Windows API函數:
LoadLibrary裝載JVM.dll動態連接庫.然後把JVM.dll中的導出函數JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs掛接到InvocationFunctions變量的CreateJavaVM和GetDefaultJavaVMInitArgs函數指針變量上。JVM.dll的裝載工作宣告完成。

3、初始化JVM。
掛接到JNIENV(JNI調用接口)實例,獲得本地調用接口,這樣就可以在Java中調用JVM的函數了。調用InvocationFunctions->CreateJavaVM也就是JVM中JNI_CreateJavaVM方法獲得JNIEnv結構的實例。

4、運行Java程序.
Java程序有兩種方式一種是jar包,一種是class。運行jar(Java -jarXXX.jar)的時候,Java.exe調用GetMainClassName函數,該函數先獲得JNIEnv實例然後調用Java類Java.util.jar.JarFileJNIEnv中方法getManifest()並從返回的Manifest對象中取getAttributes(“Main-Class”)的值即jar包中文件:META-INF/MANIFEST.MF指定的Main-Class的主類名作爲運行的主類。之後main函數會調用Java.c中LoadClass方法裝載該主類(使用JNIEnv實例的FindClass)。main函數直接調用Java.c中LoadClass方法裝載該類。如果是執行class方法。main函數直接調用Java.c中LoadClass方法裝載該類。
然後main函數調用JNIEnv實例的GetStaticMethodID方法查找裝載的class主類中“publicstatic void main(String[] args)”方法,並判斷該方法是否爲public方法,然後調用JNIEnv實例的CallStaticVoidMethod方法調用該Java類的main方法。

JVM體系結構
JVM的體系結構圖如下:
這裏寫圖片描述

主要包括兩個子系統和兩個組件: Classloader(類裝載器) 子系統,Execution engine(執行引擎) 子系統;Runtime data area (運行時數據區域)組件, Native interface(本地接口)組件。

Class loader子系統:根據給定的全限定名類名(如java.lang.Object)來裝載class文件的內容到 Runtime data area中的method area(方法區域)。

Execution engine子系統:執行classes中的指令。方法的字節碼是由Java虛擬機的指令序列構成的。每一條指令包含一個單字節的操作碼,後面跟隨0個或多個操作數。執行引擎執行字節碼時,首先取得一個操作碼,如果操作碼有操作數,取得它的操作數。它執行操作碼和跟隨的操作數規定的動作,然後再取得下一個操作碼。這個執行字節碼的過程在線程完成前將一直持續。任何JVM實現的核心是Execution engine,換句話說:Sun 的JDK 和IBM的JDK好壞主要取決於他們各自實現的Execution engine的好壞。

Native interface組件 :與nativelibraries交互,是其它編程語言交互的接口。Java裏聲明爲native的方法多數在jdk/src//native裏可以找到。其中可以是share,也就是平臺中立的代碼;也可以是某個具體平臺。這個native目錄裏的結構跟Java源碼結構一樣是按包名來組織的。不過需要提醒的是,這些native方法不是“JVM”的,是“類庫”的,不在JVM裏面。
Runtime data area 組件:Java虛擬機定義了若干種程序運行時使用到的運行時數據區,有一些是隨虛擬機的啓動而創建,隨虛擬機的退出而銷燬,如堆、方法區。第二種則是與線程一一對應,隨線程的開始和結束而創建和銷燬,如Java棧,PC寄存器。

感謝

本文非原創,經作者同意後轉載!
感謝作者冰河winner

http://blog.csdn.net/u012152619/article/details/46923185
JVM概述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章