溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JVM.dll裝載過程與源代碼的示例分析

發(fā)布時(shí)間:2021-10-23 16:45:31 來源:億速云 閱讀:168 作者:柒染 欄目:編程語言

今天就跟大家聊聊有關(guān)JVM.dll裝載過程與源代碼的示例分析,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

JVM.dll是一個(gè)包含可由多個(gè)程序同時(shí)使用的代碼和數(shù)據(jù)的庫。例如,在Windows操作系統(tǒng)中,Comdlg32DLL執(zhí)行與對話框有關(guān)的常見函數(shù)。

淺談JVM.dll裝載過程與源代碼分析

眾所周知java.exe是javaclass文件的執(zhí)行程序,但實(shí)際上java.exe程序只是一個(gè)執(zhí)行的外殼,它會(huì)裝載JVM.dll,這個(gè)動(dòng)態(tài)連接庫才是java虛擬機(jī)的實(shí)際操作處理所在。本文探究java.exe程序是如何查找和裝載JVM.dll動(dòng)態(tài)庫,并調(diào)用它進(jìn)行class文件執(zhí)行處理的。

JVM.dll源代碼

本文分析之代碼,《JavaTM2SDK,StandardEdition,v1.4.2fcsCommunitySourceRelease》,可從sun官方網(wǎng)站下載,主要分析的源代碼為:j2se\src\share\bin\java.cj2se\src\windows\bin\java_md.c

java.c是什么東西

‘java程序’源代碼所謂‘java程序’,包括jdk中的java.exe\javac.exe\javadoc.exe,java.c源代碼中通過JAVA_ARGS宏來控制生成的代碼,如果該宏沒定義則編譯文件控制生成java.exe否則編譯文件控制生成其他的‘java程序’。比如:j2se\make\java\javac\Makefile(這是javac編譯文件)中:$(CD)../../sun/javac;$(MAKE)$@RELEASE=$(RELEASE)FULL_VERSION=$(FULL_VERSION)j2se\make\sun\javac\javac\Makefile(由上面Makefile文件調(diào)用)中:JAVA_ARGS="{\"-J-ms8m\",\"com.sun.tools.javac.Main\"}"則由同一份java.c代碼生成的javac.exe程序就會(huì)直接調(diào)用java類方法:com.sun.tools.javac.Main,這樣使其執(zhí)行起來就像是直接運(yùn)行的一個(gè)exe文件,而未定義JAVA_ARGS的java.exe程序則會(huì)調(diào)用傳遞過來參數(shù)中的類方法。

從java.c的main入口函數(shù)說起

main()函數(shù)中前面一段為重新分配參數(shù)指針的處理。然后調(diào)用函數(shù):CreateExecutionEnvironment,該函數(shù)主要查找java運(yùn)行環(huán)境的目錄,和JVM.dll這個(gè)虛擬機(jī)核心動(dòng)態(tài)連接庫文件路徑所在。根據(jù)操作系統(tǒng)不同,該函數(shù)有不同實(shí)現(xiàn)版本,但大體處理邏輯相同,我們看看windows平臺該函數(shù)的處理(j2se\src\windows\bin\java_md.c)。

CreateExecutionEnvironment函數(shù)主要分為三步處理:a、查找jre路徑。b、裝載jvm.cfg中指定的虛擬機(jī)動(dòng)態(tài)連接庫(JVM.dll)參數(shù)。c、取JVM.dll文件路徑。

實(shí)現(xiàn):

◆a、查找jre路徑是通過java_md.c中函數(shù):GetJREPath實(shí)現(xiàn)的。

該函數(shù)首先調(diào)用GetApplicationHome函數(shù),GetApplicationHome函數(shù)調(diào)用windowsAPI函數(shù)GetModuleFileName取java.exe程序的絕對路徑,以我的jdk安裝路徑為例,為:“D:\java\j2sdk1.4.2_04\bin\java.exe”,然后去掉文件名取絕對路徑為:“D:\java\j2sdk1.4.2_04\bin”,之后會(huì)在去掉***一級目錄,現(xiàn)在絕對路徑為:“D:\java\j2sdk1.4.2_04”。然后GetJREPath函數(shù)繼續(xù)判斷剛剛?cè)〉穆窂?\bin\java.dll組合成的這個(gè)java.dll文件是否存在,如果存在則“D:\java\j2sdk1.4.2_04”為JRE路徑,否則判斷取得的“D:\java\j2sdk1.4.2_04”路徑+\jre\bin\java.dll文件是否存在,存在則“D:\java\j2sdk1.4.2_04\jre”為JRE路徑。如果上面兩種情況都不存在,則從注冊表中去查找(參見函數(shù)GetPublicJREHome)。

函數(shù):GetPublicJREHome先查找HKEY_LOCAL_MACHINE\Software\JavaSoft\JavaRuntimeEnvironment\CurrentVersion鍵值“當(dāng)前JRE版本號”,判斷“當(dāng)前JRE版本號”是否為1.4做為版本號,如果是則取HKEY_LOCAL_MACHINE\Software\JavaSoft\JavaRuntimeEnvironment\“當(dāng)前JRE版本號”\JavaHome的路徑所在為JRE路徑。

我的JDK返回的JRE路徑為:“D:\java\j2sdk1.4.2_04\jre”。

◆b、裝載jvm.cfg虛擬機(jī)動(dòng)態(tài)連接庫配置文件是通過java.c中函數(shù):ReadKnownVMs實(shí)現(xiàn)的。

該函數(shù)首先組合jvm.cfg文件的絕對路徑,JRE路徑+\lib+\ARCH(CPU構(gòu)架)+\jvm.cfgARCH(CPU構(gòu)架)的判斷是通過java_md.c中GetArch函數(shù)判斷的,該函數(shù)中windows平臺只有兩種情況:WIN64的‘ia64’,其他情況都為‘i386’。我的為i386所以jvm.cfg文件絕對路徑為:“D:\java\j2sdk1.4.2_04\jre\lib\i386\jvm.cfg”。文件內(nèi)容如下:

##@(#)jvm.cfg 1.703/01/23##Copyright2003SunMicrosystems,Inc.Allrightsreserved.  #SUNPROPRIETARY/CONFIDENTIAL.Useissubjecttolicenseterms.  #####ListofJVMsthatcanbeusedasanoptiontojava,javac,etc.  #Orderisimportant--irstinthislististhedefaultJVM.  #NOTEthatthisboththisfileanditsformatareUNSUPPORTEDand  #WILLGOAWAYinafuturerelease.  ##YoumayalsoselectaJVMinanarbitrarylocationwiththe  #"-XXaltjvm="option,butthattooisunsupported  #andmaynotbeavailableinafuturerelease.  #-clientKNOWN-serverKNOWN-hotspotALIASED_TO-client-  classicWARN-nativeERROR-greenERROR

(如果細(xì)心的話,我們會(huì)發(fā)現(xiàn)在JDK目錄中我的為:“D:\java\j2sdk1.4.2_04\jre\bin\client”和“D:\java\j2sdk1.4.2_04\jre\bin\server”兩個(gè)目錄下都存在JVM.dll文件。而java正是通過jvm.cfg配置文件來管理這些不同版本的JVM.dll的。)

ReadKnownVMs函數(shù)會(huì)將該文件中的配置內(nèi)容讀入到一個(gè)JVM配置結(jié)構(gòu)的全局變量中,該函數(shù)首先跳過注釋(以‘#’開始的行),然后讀取以‘-’開始的行指定的jvm參數(shù),每一行為一個(gè)jvm信息,***部分為jvm虛擬機(jī)名稱,第二部分為配置參數(shù),比如行:“-clientKNOWN”則“-client”為虛擬機(jī)名稱,而“KNOWN”為配置類型參數(shù),“KNOWN”表示該虛擬機(jī)的JVM.dll存在,而“ALIASED_TO”表示為另一個(gè)JVM.dll的別名,“WARN”表示該虛擬機(jī)的JVM.dll不存在但運(yùn)行時(shí)會(huì)用其他存在的JVM.dll替代執(zhí)行,而“ERROR”同樣表示該類虛擬機(jī)的JVM.dll不存在且運(yùn)行時(shí)不會(huì)找存在的JVM.dll替代而直接拋出錯(cuò)誤信息。

在運(yùn)行java程序時(shí)指定使用那個(gè)虛擬機(jī)的判斷是由java.c中函數(shù):CheckJvmType判斷,該函數(shù)會(huì)檢查java運(yùn)行參數(shù)中是否有指定jvm的參數(shù),然后從ReadKnownVMs函數(shù)讀取的jvm.cfg數(shù)據(jù)結(jié)構(gòu)中去查找,從而指定不同的jvm類型(最終導(dǎo)致裝載不同JVM.dll)。有兩種方法可以指定jvm類型,一種按照jvm.cfg文件中的jvm名稱指定,第二種方法是直接指定,它們執(zhí)行的方法分別是“java-J”、“java-XXaltjvm=”或“java-J-XXaltjvm=”。如果是***種參數(shù)傳遞方式,CheckJvmType函數(shù)會(huì)取參數(shù)‘-J’后面的jvm名稱,然后從已知的jvm配置參數(shù)中查找如果找到同名的則去掉該jvm名稱前的‘-’直接返回該值;而第二種方法,會(huì)直接返回“-XXaltjvm=”或“-J-XXaltjvm=”后面的jvm類型名稱;如果在運(yùn)行java時(shí)未指定上面兩種方法中的任一一種參數(shù),CheckJvmType會(huì)取配置文件中***個(gè)配置中的jvm名稱,去掉名稱前面的‘-’返回該值。CheckJvmType函數(shù)的這個(gè)返回值會(huì)在下面的函數(shù)中匯同jre路徑組合成JVM.dll的絕對路徑。

比如:如果在運(yùn)行java程序時(shí)使用“java-J-clienttest”則ReadKnownVMs會(huì)讀取參數(shù)“-client”然后查找jvm.cfg讀入的參數(shù)中是否有jvm名稱為“-client”的,如果有則去掉jvm名稱前的“-”直接返回“client”;而如果在運(yùn)行java程序時(shí)使用如下參數(shù):“java-XXaltjvm=D:\java\j2sdk1.4.2_04\jre\bin\clienttest”,則ReadKnownVMs會(huì)直接返回“D:\java\j2sdk1.4.2_04\jre\bin\client”;如果不帶上面參數(shù)執(zhí)行如:“javatest”,因?yàn)樵趈vm.cfg配置文件中***個(gè)存在的jvm為“-client”,所以函數(shù)ReadKnownVMs也會(huì)去掉jvm名稱前的“-”返回“client”。其實(shí)這三中情況都是使用的“D:\java\j2sdk1.4.2_04\jre\bin\client\JVM.dll”這個(gè)jvm動(dòng)態(tài)連接庫處理test這個(gè)class的,見下面GetJVMPath函數(shù)。

◆c、取JVM.dll文件路徑是通過java_md.c中函數(shù):GetJVMPath實(shí)現(xiàn)的。

由上面兩步我們已經(jīng)獲得了JRE路徑和jvm的類型字符串。GetJVMPath函數(shù)判斷CheckJvmType返回的jvm類型字符串中是否包含了‘\’或‘/’如果包含則以該jvm類型字符串+\JVM.dll作為JVM的全路徑,否則以JRE路徑+\bin+\jvm類型字符串+\JVM.dll作為JVM的全路徑。

看看上面的例子,***種情況“java-J-clienttest”JVM.dll路徑為:JRE路徑+\bin+\jvm類型字符串+\JVM.dll按照我的JDK路徑則為:“D:\java\j2sdk1.4.2_04\jre”+“\bin”+“\client”+“\JVM.dll”。第二種情況“java-XXaltjvm=D:\java\j2sdk1.4.2_04\jre\bin\clienttest”路徑為:jvm類型字符串+\JVM.dll即為:“D:\java\j2sdk1.4.2_04\jre\bin\client”+“\JVM.dll”第三種情況“javatest”為:“D:\java\j2sdk1.4.2_04\jre”+“\bin”+“\client”+“\JVM.dll”與情況一相同。所以這三種情況都是調(diào)用的jvm動(dòng)態(tài)連接庫“D:\javaj2sdk1.4.2_04\jre\bin\client\JVM.dll”處理test類的。

我們來進(jìn)一步驗(yàn)證一下:打開cmd控制臺:

設(shè)置java裝載調(diào)試E:\work\java_research>set_JAVA_LAUNCHER_DEBUG=1

情況一E:\work\java_research>java-J-clienttest.ScanDirectory----_JAVA_LAUNCHER_DEBUG----

看完上述內(nèi)容,你們對JVM.dll裝載過程與源代碼的示例分析有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI