
文章插圖
概覽計(jì)算機(jī)能識(shí)別的是機(jī)器指令碼,簡(jiǎn)稱(chēng)機(jī)器碼 。機(jī)器碼是二進(jìn)制的,計(jì)算機(jī)可以直接識(shí)別,但與人類(lèi)的語(yǔ)言差別太大,不容易被人理解和記憶 。后來(lái),就誕生了各種高級(jí)語(yǔ)言,人們用高級(jí)語(yǔ)言編寫(xiě)程序,然后通過(guò)把程序解釋或編譯成機(jī)器碼 。
比如python,就是一種解釋型語(yǔ)言 。Python程序源碼不需要編譯,可以直接從源代碼運(yùn)行程序 。Python解釋器將源代碼轉(zhuǎn)換為字節(jié)碼,然后把編譯好的字節(jié)碼轉(zhuǎn)發(fā)到Python虛擬機(jī)(PVM)中進(jìn)行執(zhí)行 。
而C語(yǔ)言就是典型的編譯型語(yǔ)言,需要先用編譯器編譯成機(jī)器碼,比如我們通常用gcc來(lái)編譯C語(yǔ)言程序:
$ gcc hello.c # 編譯$ ./a.out # 執(zhí)行hello world!那Java是解釋型語(yǔ)言還是編譯型語(yǔ)言呢?
Java是兼具編譯型語(yǔ)言與解釋型語(yǔ)言的特點(diǎn)的 。程序員寫(xiě)好Java程序后,需要先用javac編譯成JVM可以使用的字節(jié)碼class文件 。然后JVM加載class文件,逐條解釋執(zhí)行 。在運(yùn)行過(guò)程中,部分熱點(diǎn)代碼會(huì)被即時(shí)編譯器編譯成機(jī)器碼 。
源代碼到字節(jié)碼Java語(yǔ)言的源代碼是.java為后綴的文件 。當(dāng)然現(xiàn)在有很多其它高級(jí)語(yǔ)言也架構(gòu)在JVM上,比如groovy、kotlin等 。源代碼是給人看的,易于閱讀、理解、維護(hù) 。
源代碼經(jīng)過(guò)編譯后得到字節(jié)碼,字節(jié)碼是給JVM用的,易于理解和識(shí)別 。字節(jié)碼是以.class為后綴,其格式是JVM的一套規(guī)劃,字節(jié)碼人類(lèi)對(duì)照文檔也是勉強(qiáng)能看懂的,只是相對(duì)Java代碼來(lái)說(shuō)要難以理解一些而已 。
Java與Python不同,Python不需要編譯字節(jié)碼文件(當(dāng)然,Python也提供了這種操作),編譯是一個(gè)自動(dòng)的過(guò)程,一般不會(huì)在意它的存在 。而Java會(huì)先編譯好字節(jié)碼文件,這樣JVM直接讀字節(jié)碼文件,可以節(jié)省加載模塊的時(shí)間,提高效率 。同時(shí)字節(jié)碼的形式也增加了反向工程的難度,可以保護(hù)源代碼(當(dāng)然,也可以被反編譯) 。
熟悉JVM的小伙伴都知道,它有一個(gè)“類(lèi)加載過(guò)程”,可以說(shuō)是老八股文了,經(jīng)常會(huì)被面試官問(wèn)到 。類(lèi)加載過(guò)程其實(shí)就是指的JVM從讀取一個(gè)class文件到準(zhǔn)備好這個(gè)類(lèi),以及最后銷(xiāo)毀的整個(gè)過(guò)程 。
所以class文件其實(shí)是以“類(lèi)”為單位的,這跟java文件有一些不同 。如果我們?cè)谝粋€(gè)Java文件里面聲明多個(gè)類(lèi),用Javac編譯出來(lái)會(huì)發(fā)現(xiàn)有多個(gè)class文件 。比如我們聲明一個(gè)One.java文件:
public class One {public class OneInner {}private class OnePrivateInner {}public static class OneStaticInner {}private static class OneprivateStaticInner {}}class Two{}用Javac編譯后,會(huì)出現(xiàn)6個(gè)class文件
?$ ls'One$OneInner.class''One$OneStaticInner.class'One.classTwo.class'One$OnePrivateInner.class''One$OneprivateStaticInner.class'One.java字節(jié)碼到機(jī)器碼加載和使用字節(jié)碼前面提到,JVM會(huì)加載class文件,然后加載后的Java類(lèi)會(huì)被存放于方法區(qū)(Method Area)中 。從指定的類(lèi)的main方法作為入口開(kāi)始運(yùn)行 。實(shí)際運(yùn)行時(shí),虛擬機(jī)會(huì)執(zhí)行方法區(qū)內(nèi)的代碼,JVM會(huì)使用堆和棧來(lái)存儲(chǔ)運(yùn)行時(shí)數(shù)據(jù) 。
每當(dāng)進(jìn)入一個(gè)方法,Java虛擬機(jī)會(huì)在當(dāng)前線程的棧中生成一個(gè)棧幀,存放局部變量以及字節(jié)碼的操作數(shù),這個(gè)棧幀的大小是提前計(jì)算好的 。
退出方法時(shí),不管是正常返回還是異常返回,Java虛擬機(jī)均會(huì)彈出當(dāng)前線程的當(dāng)前棧幀,并將之舍棄 。
Java虛擬機(jī)需要將字節(jié)碼翻譯成機(jī)器碼,才能讓機(jī)器執(zhí)行 。這個(gè)過(guò)程有兩種形式,一種是解釋執(zhí)行,即逐條將字節(jié)碼翻譯成機(jī)器碼并執(zhí)行;另一種是即時(shí)編譯(Just-In-Time compilation,JIT),即將一個(gè)方法中包含的所有字節(jié)碼編譯成機(jī)器碼后再執(zhí)行 。
以上關(guān)于本文的內(nèi)容,僅作參考!溫馨提示:如遇健康、疾病相關(guān)的問(wèn)題,請(qǐng)您及時(shí)就醫(yī)或請(qǐng)專(zhuān)業(yè)人士給予相關(guān)指導(dǎo)!
「愛(ài)刨根生活網(wǎng)」www.malaban59.cn小編還為您精選了以下內(nèi)容,希望對(duì)您有所幫助:- 2021Java學(xué)習(xí)路線 java開(kāi)發(fā)學(xué)習(xí)路線
- javascript選擇器推薦 javascript選擇器有哪些
- iis運(yùn)行php慢解決方法 iis運(yùn)行php久了非常慢
- java開(kāi)發(fā)常用的框架 java框架都有哪些
- java語(yǔ)法基礎(chǔ) java結(jié)束循環(huán)的語(yǔ)句
- java中數(shù)組的定義與使用 java數(shù)組聲明和使用
- java點(diǎn)餐系統(tǒng)源碼 微信積分系統(tǒng)源碼
- 經(jīng)濟(jì)運(yùn)行的基礎(chǔ)是什么 經(jīng)濟(jì)是如何運(yùn)行的
- 達(dá)利歐經(jīng)濟(jì)機(jī)器是如何運(yùn)行的 經(jīng)濟(jì)機(jī)器是如何運(yùn)行的
- windows下運(yùn)行jar程序 jar文件打不開(kāi)怎么辦
