国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

你所不知道的HelloWorld背后的原理

lavor / 952人閱讀

摘要:今日最佳對(duì)于程序員而言,所謂的二八定律指的是花百分之八十的時(shí)間去學(xué)習(xí)日常研發(fā)中不常見(jiàn)的那百分之二十的原理。

【今日最佳】對(duì)于程序員而言,所謂的二八定律指的是 花百分之八十的時(shí)間去學(xué)習(xí)日常研發(fā)中不常見(jiàn)的那百分之二十的原理。

據(jù)說(shuō)阿里某程序員對(duì)書(shū)法十分感興趣,退休后決定在這方面有所建樹(shù)。于是花重金購(gòu)買了上等的文房四寶。

一日,飯后突生雅興,一番磨墨擬紙,并點(diǎn)上了上好的檀香,頗有王羲之風(fēng)范,又具顏真卿氣勢(shì),定神片刻,潑墨揮毫,鄭重地寫(xiě)下一行字:hello world。

當(dāng)然了,這是個(gè)專屬程序員的段子哈哈哈。

那么問(wèn)題來(lái)了,寫(xiě)了這么久的Hello World,大家確定自己了解自己寫(xiě)的東西背后是什么原理嗎?(o???)

【給出2分鐘,該知識(shí)點(diǎn)涉及到了Java程序執(zhí)行流程,包括編譯、加載和執(zhí)行,你是否能夠理清呢?】

接下來(lái)進(jìn)入嚴(yán)肅時(shí)間 (@ ̄ー ̄@)

與眾不同的Hello World
public class Main {

    private static String word = "Hello World!";

    public static void main(String[] args) {
        new Main().say();
    }

    private void say() {
        System.out.println(word);
    }
}

整個(gè)代碼的執(zhí)行過(guò)程可以分為三個(gè)階段:

代碼編譯

類加載

類執(zhí)行

代碼編譯

代碼編譯的作用就是將我們編寫(xiě)的 Main.java文件轉(zhuǎn)化為Main.class文件,.class在這里又被稱為字節(jié)碼文件,打開(kāi)就是一堆的火星文【反正就是看不懂】,在這里我們可以將編譯的過(guò)程看作生產(chǎn)JVM原料的過(guò)程,使用的工具就是jdk提供的工具javac。
大致流程如下:

詞法分析,即將源代碼的字符流轉(zhuǎn)變?yōu)門oken集的過(guò)程。白話文描述下,就是在我們實(shí)際編程中,單個(gè)字符是最小單位,而實(shí)際上在編程過(guò)程中,標(biāo)記才是最小單位,如關(guān)鍵字、變量名、字面量、運(yùn)算符等都可以成為Token,貌似還是有點(diǎn)蒙蔽,舉個(gè)例子(>﹏<),比如整型int在我們編程中它就是三個(gè)字符組成的,就是i、n、t 三個(gè)字符,而在編譯過(guò)程中它就是一個(gè)Token,不可拆分。

這個(gè)過(guò)程對(duì)我們來(lái)說(shuō)其實(shí)是完全屏蔽的,但是實(shí)際上它是現(xiàn)代經(jīng)典編譯原理的
套路,詞法分析也是為了給后面編譯做準(zhǔn)備的】

語(yǔ)法分析,通過(guò)詞法分析拿到Token集后,下一步就是構(gòu)建抽象語(yǔ)法樹(shù)了,所謂的抽象語(yǔ)法樹(shù)其實(shí)就是一種用來(lái)描述程序代碼語(yǔ)法結(jié)構(gòu)的樹(shù)形表示方式,其中語(yǔ)法樹(shù)的每一個(gè)節(jié)點(diǎn)都代表著程序代碼中的一個(gè)語(yǔ)法結(jié)構(gòu),如包、類型、修飾符、運(yùn)算符等。

在我們眼中,Main.java已經(jīng)可以清晰理解到底寫(xiě)的是什么東西了,但是對(duì)于JVM來(lái)說(shuō)還是一臉懵逼的,所以才需要構(gòu)建成語(yǔ)法樹(shù),在這一步后就不會(huì)再對(duì)源碼文件進(jìn)行操作了,后續(xù)的操作都建立在抽象語(yǔ)法樹(shù)上

填充符號(hào)表,符號(hào)表是由一組符號(hào)地址和符號(hào)信息構(gòu)成的表格,這個(gè)表格在編譯的不同階段都會(huì)被用到,如在目標(biāo)代碼生成階段,會(huì)對(duì)符號(hào)名進(jìn)行地址分配,而符號(hào)表就是地址分配的依據(jù)。

語(yǔ)義分析,語(yǔ)義分析階段也可以說(shuō)是語(yǔ)義檢測(cè)階段,上面說(shuō)到語(yǔ)法分析會(huì)構(gòu)建一棵語(yǔ)法樹(shù),那么這棵語(yǔ)法樹(shù)是否是正確合理的,就由語(yǔ)義分析來(lái)做了,語(yǔ)義分析會(huì)通過(guò)標(biāo)注檢查和數(shù)據(jù)及控制流分析檢查兩步入手,在生成字節(jié)碼的最后一步信息把關(guān)。

字節(jié)碼生成,這是javac編譯過(guò)程的最后一個(gè)階段了,字節(jié)碼生成階段并不只是簡(jiǎn)簡(jiǎn)單單的將前面各個(gè)步驟生成的信息轉(zhuǎn)化成字節(jié)碼然后放入磁盤中,還進(jìn)行了少量的代碼添加和轉(zhuǎn)換工作,如我們自己重載的構(gòu)造函數(shù)。

編譯期到這里就結(jié)束了,那么由誰(shuí)來(lái)將這些原料傳輸給JVM虛擬機(jī)呢?這個(gè)時(shí)候就要看看類加載的過(guò)程了。

類加載

類加載簡(jiǎn)單來(lái)說(shuō)就是將由類加載器將編譯后的字節(jié)碼文件【Main.class】加載到虛擬機(jī)中
,那么自然而然的,要先介紹下四種類加載器

說(shuō)說(shuō)四種類加載器

可以從上圖中看出,類加載器可以分為四種,而第四種是由我們自己實(shí)現(xiàn)的,那么其他三種由JVM提供的類加載在我們啟動(dòng)該Main程序的過(guò)程中起到了什么作用呢?

首先說(shuō)說(shuō)啟動(dòng)類加載器 Bootstrap ClassLoader ,啟動(dòng)類加載器的作用主要是加載 %JAVA_HOME%jrelibrt.jar 類庫(kù),將其加載到虛擬機(jī)內(nèi)存中,那么rt.jar類庫(kù)到底有什么作用呢?rt.jar下包含了Java的基礎(chǔ)類庫(kù),也就是Java doc里面看到的所有的類的class文件,感興趣的朋友可以自己打開(kāi)目錄看下。

其次是擴(kuò)展類加載器 Extension ClassLoader ,擴(kuò)展類加載器的作用主要是負(fù)責(zé)加載JAVA_HOMEjrelibext目錄下的所有類庫(kù),主要是載入擴(kuò)展包。

再者是系統(tǒng)類加載器 Application ClassLoader, 也稱之為應(yīng)用程序類加載器,負(fù)責(zé)加載用戶類路徑(也就是我們配置的CLASSPATH)上所指定的類庫(kù),是應(yīng)用程序中默認(rèn)的類加載。

看完以上三個(gè)類加載器的簡(jiǎn)單描述過(guò)程,是不是有種終于知道了我們配置的jdk環(huán)境的最終作用了吧,是的,就是讓類加載器識(shí)別到后加載各種類庫(kù)。

那么問(wèn)題來(lái)了?是哪個(gè)類加載器加載了我們的Hello World程序呢?是的,就是應(yīng)用程序中默認(rèn)的類加載器 Application ClassLoader。

知道了類加載器后,那接下來(lái)總要了解下類加載器怎么加載的吧?

說(shuō)說(shuō)類加載的過(guò)程

網(wǎng)上找了張圖片,簡(jiǎn)單明了。雖說(shuō)是簡(jiǎn)單明了,不過(guò)確實(shí)異常重要的,因?yàn)槭敲嬖嚐狳c(diǎn)(????)

加載

其實(shí)就是上文說(shuō)到的系統(tǒng)類加載器 Application ClassLoader將編譯后的Main.class文件加載到內(nèi)存中。

【思考】拋出個(gè)問(wèn)題,所謂的加載到內(nèi)存中,我們都知道JVM把內(nèi)存分成了幾大模塊,那么請(qǐng)問(wèn)是加載到哪個(gè)模塊中?熱點(diǎn)面試題,答案見(jiàn)文末

鏈接

鏈接中包含了三部曲,總的作用就是負(fù)責(zé)將Main.class的二進(jìn)制數(shù)據(jù)合并到JRE中。

關(guān)于三部曲,其實(shí)很好理解;

首先是驗(yàn)證階段,類加載器將二進(jìn)制字節(jié)流加載到虛擬機(jī)中,肯定是需要進(jìn)行驗(yàn)證的,避免危害虛擬機(jī)自身安全,而這也是驗(yàn)證階段存在的價(jià)值;

接下來(lái)是準(zhǔn)備階段,準(zhǔn)備階段是正式為類變量分配內(nèi)存并且設(shè)置類變量默認(rèn)值的地方,比如上面HelloWorld程序中的

private static String word = "Hello World!";

注意我描述的第一個(gè)是類變量,也就是static所描述的變量,其次是默認(rèn)值,也就是上面的word的默認(rèn)值null,如果是數(shù)字則為0。

最后是解析階段,解析階段的作用主要是將常量池內(nèi)的符號(hào)引用替換為直接引用的過(guò)程,解析階段其實(shí)有點(diǎn)難理解,至少是比上面的兩個(gè)階段要難理解的,我這里盡量直白點(diǎn);

所謂的符號(hào)引用指的是包含了類的信息、方法名、方法參數(shù)等信息的字符串,而當(dāng)?shù)谝淮芜\(yùn)行時(shí),JVM會(huì)根據(jù)這行字符串去檢索到對(duì)應(yīng)的方法入口,而為了下次不用再做同樣的檢索,在第一次運(yùn)行的時(shí)候就會(huì)將符號(hào)引用替換成直接引用,這樣后面就可以省去一定的消耗了;這里的直接引用其實(shí)就是指偏移量,虛擬機(jī)可以通過(guò)偏移量直接找到方法入口,不再需要做檢索了。

初始化
終于來(lái)到初始化階段了,上面我們有說(shuō)到word默認(rèn)值是null,是系統(tǒng)賦的默認(rèn)值,而在初始化階段,則是根據(jù)我們?nèi)藶榈某跏蓟愖兞亢推渌Y源,比如上面的word則被我初始化成了"Hello World!"。

類執(zhí)行

上面說(shuō)到Main.class被加載到了Java虛擬機(jī)內(nèi)存中,那么接下來(lái)便是執(zhí)行的過(guò)程了。那么由誰(shuí)來(lái)執(zhí)行這一過(guò)程呢?
如圖


實(shí)際上,一個(gè)Java虛擬機(jī)在運(yùn)行的時(shí)候可以劃分為三個(gè)子系統(tǒng):

類加載子系統(tǒng)

執(zhí)行引擎子系統(tǒng)

垃圾收集子系統(tǒng)

很明顯、很清晰,圖中的類加載子系統(tǒng)在上面已經(jīng)談了,執(zhí)行引擎子系統(tǒng)就是負(fù)責(zé)執(zhí)行這一部分的,那么過(guò)程是怎么樣的呢?

其實(shí)很簡(jiǎn)單,執(zhí)行引擎會(huì)把字節(jié)碼轉(zhuǎn)換為機(jī)器碼【what?竟然還要轉(zhuǎn)換。拜托<(ˉ^ˉ)>,字節(jié)碼是被JVM識(shí)別的語(yǔ)言,字節(jié)碼才是最終被操作系統(tǒng)識(shí)別的語(yǔ)言】

然后操作系統(tǒng)才可以真正調(diào)用,很多學(xué)或者做Java的人都聽(tīng)過(guò)JIT,但是都不知道具體是干嘛的,沒(méi)錯(cuò)說(shuō)的就是你。

這里終于可以解釋下了,字節(jié)碼轉(zhuǎn)換成機(jī)器碼的翻譯工作使用的就是JIT(Just In Time)即時(shí)編譯器(對(duì)熱代碼整段編譯)和Java字節(jié)碼解釋器(一行一行解釋字節(jié)碼)來(lái)完成的。
這里給下JIT編譯的工作流程:

JVM字節(jié)碼 -> 機(jī)器無(wú)關(guān)優(yōu)化 -> 中間代碼 -> 機(jī)器相關(guān)優(yōu)化 -> 中間代碼 -> 寄存器分配器 -> 中間代碼 -> 目標(biāo)機(jī)器碼生成器 -> 目標(biāo)機(jī)器碼

最后執(zhí)行引擎會(huì)找到main()這個(gè)入口方法,并且執(zhí)行其中的字節(jié)碼指令。

最后,關(guān)于HelloWorld執(zhí)行過(guò)程,基本上闡述完畢了,關(guān)于執(zhí)行程序期間,JVM內(nèi)存分配問(wèn)題,是一個(gè)比較大的模塊,欲知詳情,請(qǐng)關(guān)注公眾號(hào),我們下次再聊!!!

【思考解惑】加載階段完成后,虛擬機(jī)會(huì)將Main.class的二進(jìn)制字節(jié)流按照虛擬機(jī)所需的格式存儲(chǔ)在方法區(qū)之中,然后在內(nèi)存中實(shí)例化一個(gè)java.lang.Class類的對(duì)象,作為程序訪問(wèn)方法區(qū)中的這些類型數(shù)據(jù)的外部接口,實(shí)例化后的java.lang.Class類的對(duì)象也是存放在方法區(qū)中的。

公眾號(hào)主營(yíng):服務(wù)端編程相關(guān)技術(shù)解說(shuō),具體可以看歷史文章。

公眾號(hào)副業(yè):各種陪聊吹水,包括技術(shù)、就業(yè)、人生經(jīng)歷、大學(xué)生活、內(nèi)推等等。

歡迎關(guān)注,一起侃大山

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/75097.html

相關(guān)文章

  • 【好好面試】學(xué)完Aop,連動(dòng)態(tài)代理原理都不懂?

    摘要:總結(jié)動(dòng)態(tài)代理的相關(guān)原理已經(jīng)講解完畢,接下來(lái)讓我們回答以下幾個(gè)思考題。 【干貨點(diǎn)】 此處是【好好面試】系列文的第12篇文章。文章目標(biāo)主要是通過(guò)原理剖析的方式解答Aop動(dòng)態(tài)代理的面試熱點(diǎn)問(wèn)題,通過(guò)一步步提出問(wèn)題和了解原理的方式,我們可以記得更深更牢,進(jìn)而解決被面試官卡住喉嚨的情況。問(wèn)題如下 SpringBoot默認(rèn)代理類型是什么 為什么不用靜態(tài)代理 JDK動(dòng)態(tài)代理原理 CGLIB動(dòng)態(tài)代理...

    Keven 評(píng)論0 收藏0
  • 所不知道 ? Blockchain

    前言 未來(lái)的公司形態(tài)會(huì)不斷地演化,去中心化,分布式,強(qiáng)化合作,適應(yīng)變化,直到徹底地被網(wǎng)絡(luò)化。終極公司的形式將會(huì)變得與生物體相同,無(wú)縫地集成到生態(tài)圈中,成為其中的一個(gè)環(huán)節(jié)。—— 凱文·凱利《失控》 小劇場(chǎng) 小二: 糖糖,我愛(ài)你哦~ 糖糖: 你騙人!男人的話能信母豬能上樹(shù)。 小二: 我可以向全世界證明,我說(shuō)的是真的~ 糖糖: 那你怎么證明啊~ 小二: 我可以用 區(qū)塊鏈 寫(xiě)下 糖糖我愛(ài)你哦~...

    Tecode 評(píng)論0 收藏0
  • 所不知道同比和環(huán)比真正區(qū)別

    摘要:給百度百科給的環(huán)比定義為環(huán)比,統(tǒng)計(jì)學(xué)術(shù)語(yǔ),是表示連續(xù)個(gè)統(tǒng)計(jì)周期比如連續(xù)兩月內(nèi)的量的變化比。二你所不知道的同比環(huán)比兩種方式的核心區(qū)別判斷兩個(gè)數(shù)據(jù)到底是同比還是環(huán)比。 ...

    liujs 評(píng)論0 收藏0
  • 所不知道 ? URL

    你所不知道的 URL 0.說(shuō)明 第一幕 產(chǎn)品:大叔有用戶反映賬戶不能綁定公眾號(hào)。大叔:啊咧咧?怎么可能,我看看?大叔:恩?這也沒(méi)問(wèn)題啊,魏蝦米。大叔:還是沒(méi)問(wèn)題啊,挖叉類。大叔:T T,話說(shuō)產(chǎn)品姐姐是不是Java提供接口的時(shí)候,沒(méi)有對(duì)URL進(jìn)行encodeURI。產(chǎn)品:啊咧咧?我問(wèn)問(wèn)看? 第二幕 大叔:小二你給我過(guò)來(lái)!小二:啊咧咧?怎么了大叔?大叔:知道在URL中的+有時(shí)候會(huì)變成什么嗎?小二:啊咧...

    weizx 評(píng)論0 收藏0
  • 前端面試所不知道系列

    摘要:請(qǐng)注意是創(chuàng)建一個(gè)全局對(duì)象的屬性,而不是聲明了一個(gè)全局變量。由于變量聲明自帶不可刪除屬性,比較跟,前者是變量聲明,帶不可刪除屬性,因此無(wú)法被刪除后者為全局變量的一個(gè)屬性,因此可以從全局變量中刪除。下期預(yù)告前端面試你所不知道系列偽類和偽元素 寫(xiě)在開(kāi)始 又到了一年的伊始,很多人可能因?yàn)楦鞣N原因想換一份工作,而找工作難免遇到各種各樣頭痛的面試題,于是我打算寫(xiě)一個(gè)系列,關(guān)于面試中最常見(jiàn)或者前端一...

    Julylovin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<