对JVM的理解
操作系統(tǒng)內(nèi)核是至高無尚的內(nèi)功心法,只有掌握了內(nèi)功,學(xué)習(xí)其他的武功才會輕而易舉。
現(xiàn)在我們來談?wù)刯ava。JVM其實是操作系統(tǒng)中運行的進(jìn)程,JVM有操作系統(tǒng)進(jìn)程的所有共性,但是它卻不是一個普通的進(jìn)程,它有它特殊的地方,它將許多本來屬于操作系統(tǒng)管理范疇的東西,移植到了JVM內(nèi)部,減少系統(tǒng)調(diào)用的開銷。
1.在普通程序(如C++)中,如果new一個對象,會產(chǎn)生一個系統(tǒng)調(diào)用,由操作系統(tǒng)線程根據(jù)對象的大小分配好空間后返回;若要釋放對象,也需要detele產(chǎn)生一個系統(tǒng)調(diào)用,通知操作系統(tǒng) 對象所占用的空間已經(jīng)可以回收。但是JVM堆中,只需要在最開始進(jìn)行一次系統(tǒng)調(diào)用,向操作系統(tǒng)申請一整段區(qū)域作為java程序的堆,之后創(chuàng)建和銷毀對象都不需要再進(jìn)行系統(tǒng)調(diào)用,而是直接由JVM在內(nèi)部按需分配,這樣大大減少了系統(tǒng)調(diào)用的開銷。同時C++需要明確調(diào)用delete進(jìn)行內(nèi)存回收,如果程序員忘了就很容易造成內(nèi)存泄露,然而在JVM中有垃圾回收器負(fù)責(zé)回收內(nèi)存。
2.應(yīng)用程序通常不直接和內(nèi)核內(nèi)存打交道,內(nèi)核內(nèi)存由操作系統(tǒng)進(jìn)行管理和使用;不過隨著Linux對性能的關(guān)注及改進(jìn),一些新的特性使得應(yīng)用程序(JVM)可以使用內(nèi)核內(nèi)存,或者是映射到內(nèi)核空間。Java NIO正是在這種背景下誕生的。在java NIO中,為了減少讀寫IO系統(tǒng)調(diào)用的開銷,使用到了內(nèi)核的內(nèi)存。當(dāng)應(yīng)用程序想將磁盤文件的數(shù)據(jù)發(fā)送網(wǎng)卡,不需要先進(jìn)行系統(tǒng)調(diào)用讀入用戶空間,再系統(tǒng)調(diào)用輸出到內(nèi)核空間,而是直接在內(nèi)核空間就完成整個操作了,大大減少了系統(tǒng)調(diào)用的次數(shù)
?
?
我們可以把JVM看成一臺虛擬的機(jī)器,這臺機(jī)器可以按需加載可執(zhí)行二進(jìn)制文件(字節(jié)碼文件),然后由虛擬機(jī)執(zhí)行引擎解釋執(zhí)行字節(jié)碼,將其翻譯成cpu可以識別的指令。在jvm的邏輯地址空間中,有方法區(qū)(用來存放可執(zhí)行文件),堆(用于存放對象和數(shù)組,jvm垃圾回收器動態(tài)分配和回收該區(qū)域的內(nèi)存空間),棧(保存線程的方法調(diào)用關(guān)系,數(shù)據(jù)),常量池(存放常量)等。因此,一個Java虛擬機(jī)實例在運行過程中有三個子系統(tǒng)來保障它的正常運行,分別是類加載器子系統(tǒng), 執(zhí)行引擎子系統(tǒng)和垃圾收集子系統(tǒng)。字節(jié)碼文件相當(dāng)于食物,類加載器相當(dāng)于嘴,執(zhí)行引擎相當(dāng)于胃,垃圾回收器相當(dāng)于排泄系統(tǒng)。????
執(zhí)行引擎包括字節(jié)碼解釋器和JIT(just-in-time)及時編譯器,解釋器將字節(jié)碼文件一行一行邊解釋邊執(zhí)行(解釋成cpu能識別的指令),而JIT編譯器則是將整個字節(jié)碼文件編譯成cpu能夠識別的指令,也就是在執(zhí)行前全部被翻譯為機(jī)器碼,這樣做的好處是將熱點代碼緩存起來,下次使用的時候cpu直接執(zhí)行,而不用再逐行解釋。
?
為什么要引入java虛擬機(jī)呢?是為了讓java能夠跨平臺。
在c語言中,只需要gcc將源代碼文件編譯后,操作系統(tǒng)就可以識別該執(zhí)行文件了。但是在java中,當(dāng)編譯成字節(jié)碼文件后,操作系統(tǒng)是無法直接運行的,因為不識別,所以引入了JVM,由JVM負(fù)責(zé)加載字節(jié)碼文件,然后在JVM中解釋執(zhí)行,將其翻譯成cpu可以識別的指令。這樣一來,只需要讓JVM平臺相關(guān)就可以了,不同操作系統(tǒng)安裝對應(yīng)版本的JVM,然后由JVM負(fù)責(zé)和操作系統(tǒng)打交道,從而讓java代碼變成平臺無關(guān)的。只需要一次編譯,就能夠到處執(zhí)行。
java HelloWorld,該命令會首先啟動一個虛擬機(jī)進(jìn)程,將HelloWorld的可執(zhí)行文件加載到該進(jìn)程的地址空間,然后解釋執(zhí)行。在Java虛擬機(jī)執(zhí)行過程中,只有當(dāng)需要一個類的時候,才會調(diào)用類加載器來加載這個類,并不會在開始運行時加載所有的類。這種類的動態(tài)加載機(jī)制造就了java的多態(tài)。
?
轉(zhuǎn)載于:https://www.cnblogs.com/james111/p/7249617.html
超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生總結(jié)
- 上一篇: velocity 的 escape实现
- 下一篇: Win7下Anaconda3+Tenso