Java虛擬機(jī)(JVM)執(zhí)行的文件是經(jīng)過(guò)編譯生成的.class字節(jié)碼文件。這些字節(jié)碼文件是Java源代碼文件(.java)通過(guò)Java編譯器(如javac)編譯后生成的中間表示形式,它是一種硬件和操作系統(tǒng)無(wú)關(guān)的二進(jìn)制格式,存儲(chǔ)了類的結(jié)構(gòu)信息、方法信息以及字段信息等。
在Java程序的執(zhí)行過(guò)程中,JVM并不直接運(yùn)行.java源代碼文件,而是加載并執(zhí)行.class字節(jié)碼文件。具體來(lái)說(shuō),JVM的工作流程如下:
編譯階段:Java源代碼文件(.java)首先被編譯器(如javac)編譯成.class字節(jié)碼文件。這個(gè)字節(jié)碼文件包含了程序的抽象指令集,以及類的結(jié)構(gòu)信息,例如類名、方法名、變量名等。
加載階段:JVM通過(guò)類加載器(ClassLoader)將.class文件加載到內(nèi)存中。加載階段包括定位.class文件、驗(yàn)證其合法性以及將字節(jié)碼存儲(chǔ)到運(yùn)行時(shí)數(shù)據(jù)區(qū)的方法區(qū)中。
驗(yàn)證階段:JVM對(duì)加載的字節(jié)碼進(jìn)行一系列檢查,確保其符合Java語(yǔ)言規(guī)范,包括語(yǔ)法正確性、類型安全性和安全性等。
準(zhǔn)備和解析階段:JVM為類變量分配內(nèi)存并設(shè)置默認(rèn)值,并解析符號(hào)引用,將其轉(zhuǎn)換為直接引用。
初始化階段:JVM執(zhí)行類構(gòu)造器<clinit>()方法,完成類變量的初始化。
執(zhí)行階段:JVM通過(guò)執(zhí)行引擎(Execution Engine)解釋或即時(shí)編譯(JIT Compiler)字節(jié)碼,將其轉(zhuǎn)換為特定平臺(tái)的機(jī)器碼并執(zhí)行。執(zhí)行過(guò)程中,JVM會(huì)管理程序運(yùn)行時(shí)的數(shù)據(jù)區(qū)域,包括堆(Heap)、棧(Stack)、方法區(qū)(Metaspace)等。
卸載階段:當(dāng)類不再被需要時(shí),JVM會(huì)卸載該類的字節(jié)碼文件。
需要注意的是,雖然JVM執(zhí)行的是.class字節(jié)碼文件,但也可以通過(guò)jar文件運(yùn)行Java程序。jar文件是一種壓縮格式的文件,可以包含多個(gè).class文件以及其他資源文件。在運(yùn)行jar文件時(shí),JVM會(huì)從classpath中找到所需的.class文件并加載執(zhí)行。
Java虛擬機(jī)執(zhí)行的核心是.class字節(jié)碼文件,它作為Java程序的中間表示形式,使得Java程序能夠在任何支持JVM的平臺(tái)上運(yùn)行,真正實(shí)現(xiàn)了“一次編寫,到處運(yùn)行”的理念。