— 本文參照 Learn Java for Android Development (第三版)
java程序的執(zhí)行需要通過一個(gè)工具去加載并且啟動(dòng)JVM(java虛擬機(jī)),并且它還會(huì)把程序的主類(包含啟動(dòng)入口)傳遞到主機(jī)。然后JVM會(huì)通過加載器把類文件加載到內(nèi)存中。
類文件加載完成以后,JVM的字節(jié)碼校驗(yàn)器會(huì)對(duì)這些文件進(jìn)行檢查,一旦有發(fā)現(xiàn)任何問題都會(huì)立馬終止運(yùn)行。如果文件都沒有問題,JVM就會(huì)開始進(jìn)行翻譯,將字節(jié)碼一條一條地翻譯成相應(yīng)的指令,并且執(zhí)行相應(yīng)的底層指令。這樣我們的程序就跑起來了,想干嘛就干嘛了。
注意:這里我們的代碼就好像平時(shí)我們的領(lǐng)導(dǎo)一樣,只是下了相應(yīng)的指令,具體的事情是需要我們這些底層的員工一件一件去完成的。我們的java程序也一樣,是屬于比較上層的東西,借助于JVM把我們想做的事情傳遞給底層處理器。這樣機(jī)器才能按照我們想要的方式去運(yùn)行。
當(dāng)解釋器發(fā)現(xiàn)如果一些指令在重復(fù)執(zhí)行的時(shí)候,它就會(huì)通知到JVM的及時(shí)編譯器,把這些頻繁執(zhí)行的指令編譯成機(jī)器碼。對(duì)于一個(gè)給定的字節(jié)碼序列及時(shí)編譯器其實(shí)只會(huì)編譯一次。相比于字節(jié)碼指令我們的機(jī)器指令執(zhí)行起來會(huì)迅速得多,這樣我們的程序執(zhí)行速度也會(huì)更快。 在程序執(zhí)行的過程中可能碰到一些情況,比如當(dāng)前正在執(zhí)行一個(gè)類文件的內(nèi)容,但是它可能依賴一些其他類文件的東西。這個(gè)時(shí)候就會(huì)先啟動(dòng)類加載器去加載相應(yīng)的類文件同時(shí)字節(jié)碼校驗(yàn)器會(huì)校驗(yàn)類文件的字節(jié)碼。只有校驗(yàn)通過才會(huì)去執(zhí)行這個(gè)新加載的類文件的內(nèi)容。
除了上面這種很常見的情況,我們的程序在執(zhí)行過程中還可能會(huì)有一些其他的處理情況。比如我們可能會(huì)去打開某個(gè)文件,在屏幕上顯示某些東西,或者啟動(dòng)一個(gè)其他的任務(wù)并且需要系統(tǒng)平臺(tái)進(jìn)行配合。這個(gè)時(shí)候JVM就會(huì)通過JNI去調(diào)用底層接口來響應(yīng)這些請(qǐng)求。作者給我們提供了一張清晰的結(jié)構(gòu)圖來告訴我們JVM究竟是怎么工作的:

看到?jīng)],圖中用方框括起來的就是JVM的主要工作,它提供了我們加載類文件、字節(jié)碼校驗(yàn)、解釋字節(jié)碼、及時(shí)編譯、執(zhí)行程序過程中可能用到的所有組件。它在這整個(gè)過程中就像一個(gè)大boss!你懂的。