JAVA中的JDK和JVM

轉自:http://www.iteye.com/topic/423505

1.任何一門語言的開發都需要提供基本的架構對其支持,在java中提供的是一個JDK的類庫,它是java運行的核心,是java運行的控制者,它產生程序運行所需要的結果,控制程序的走向,是所有指令和戰略的執行中心,它提供java完整的解決方案。它是一套完整的體系結構,包括JVM(java虛擬機)、核心API、集成API、Java工具

2.JVM是JDK的最底層,對java程序進行解釋和運行,負責與操作系統進行交互,用來屏蔽操作系統環境,提供一個完整的java運行環境。因此也就JAVA虛擬計算機。Java虛擬機有自己完善的硬件架構,如處理器、堆棧、寄存器等,還具有相應的指令系統。JVM屏蔽了與具體操作系統平臺相關的信息,使得Java程序只需生成在Java虛擬機上運行的目標代碼(字節碼),就可以在多種平臺上不加修改地運行。Java虛擬機在執行字節碼時,實際上最終還是把字節碼解釋成具體平臺上的機器指令執行。 每個JVM都有兩種機制,一個是裝載具有合適名稱的類(類或是接口),叫做類裝載子系統;另外的一個負責執行包含在已裝載的類或接口中的指令,叫做運行引擎

JVM體系結構:

 

 操作系統裝入jvm是通過jdk中java.exe來完成,通過下面4步來完成jvm環境.
1.創建jvm裝載環境和配置
2.裝載jvm.dll
3.初始化jvm.dll並掛界到JNIENV(JNI調用接口)實例
4.調用JNIEnv實例裝載並處理class類。

 

JVM:裝入過程:

一.jvm裝入環境,jvm提供的方式是操作系統的動態連接文件.既然是文件那就一個裝入路徑的問題,java是怎麼找這個路徑的呢?當你在調用java test的時候,操作系統會在path下在你的java.exe程序,java.exe就通過下面一個過程來確定jvm的路徑和相關的參數配置了.下面基於windows的實現的分析. 首先查找jre路徑,java是通過GetApplicationHome api來獲得當前的java.exe絕對路徑,c:\j2sdk1.4.2_09\bin\java.exe,那麼它會截取到絕對路徑c:\j2sdk1.4.2_09\,判斷c:\j2sdk1.4.2_09\bin\java.dll文件是否存在,如果存在就把c:\j2sdk1.4.2_09\作爲jre路徑,如果不存在則判斷c:\j2sdk1.4.2_09\jre\bin\java.dll是否存在,如果存在這c:\j2sdk1.4.2_09\jre作爲jre路徑.如果不存在調用GetPublicJREHome查HKEY_LOCAL_MACHINE\Software\JavaSoft\Java RuntimeEnvironment\“當前JRE版本號”\JavaHome的路徑爲jre路徑。 然後裝載jvm.cfg文件JRE路徑+\lib+\ARCH(CPU構架)+\jvm.cfgARCH(CPU構架

)的判斷是通過java_md.c中GetArch函數判斷的,該函數中windows平臺只有兩種

情況:WIN64的‘ia64’,其他情況都爲‘i386’。以我的爲

例:C:\j2sdk1.4.2_09\jre\lib\i386\jvm.cfg.主要的內容如下:
-client KNOWN
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR
在我們的jdk目錄中jre\bin\server和jre\bin\client都有jvm.dll文件存在,而java正是通過jvm.cfg配置文件來管理這些不同版本的jvm.dll的.通過文件我們可以定義目前jdk中支持那些jvm,前面部分(client)是jvm名稱,後面是參數,KNOWN表示jvm存在,ALIASED_TO表示給別的jvm取一個別名,WARN表示不存在時找一個jvm替代,ERROR表示不存在拋出異常.在運行java XXX是,java.exe會通過CheckJvmType來檢查當前的jvm類型,java可以通過兩種參數的方式來指定具體的jvm類型,一種按照jvm.cfg文件中的jvm名稱指定,第二種方法是直接指定,它們執行的方法分別是“java -J”、“java -XXaltjvm=”或“java-J-XXaltjvm=”。如果是第一種數傳遞方式,CheckJvmType函數會取參數‘-J’後面的jvm名稱,然後從已知的jvm配置參數中查找如果找到同名的則去掉該jvm名稱前的‘-’直接返回該值;而第二種方法,會直接返回“-XXaltjvm=”或“-J-XXaltjvm=”後面的jvm類型名稱;如果在運行java時未指定上面兩種方法中的任一一種參數,CheckJvmType會取配置文件中第一個配置中的jvm名稱,去掉名稱前面的‘-’返回該值。CheckJvmType函數的這個返回值會在下面的函數中匯同jre路徑組合成jvm.dll的絕對路徑。如果沒有指定這會使用jvm.cfg中第一個定義的jvm.可以通過set_JAVA_LAUNCHER_DEBUG=1在控制檯上測試. 最後獲得jvm.dll的路徑,JRE路徑+\bin+\jvm類型字符串+\jvm.dll就是jvm的文件路徑了,但是如果在調用java程序時用-XXaltjvm=參數指定的路徑path,就直接

用path+\jvm.dll文件做爲jvm.dll的文件路徑.

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

三:初始化jvm,獲得本地調用接口,這樣就可以在java中調用jvm的函數了.調

用InvocationFunctions->CreateJavaVM也就是jvm中JNI_CreateJavaVM方法獲得

JNIEnv結構的實例.

四:運行java程序.
java程序有兩種方式一種是jar包,一種是class. 運行jar,java -jar XXX.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主類中 “public static void main(String[] args)”方法,並判斷該方法是否爲public方法,然後調用JNIEnv實例的 CallStaticVoidMethod方法調用該java類的main方法。

 

JVM的運行過程



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