亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

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

lavor / 1010人閱讀

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

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

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

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

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

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

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

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

與眾不同的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);
    }
}

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

代碼編譯

類加載

類執(zhí)行

代碼編譯

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

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

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

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

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

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

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

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

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

類加載

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

說說四種類加載器

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

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

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

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

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

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

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

說說類加載的過程

網(wǎng)上找了張圖片,簡單明了。雖說是簡單明了,不過確實異常重要的,因為是面試熱點(diǎn)(????)

加載

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

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

鏈接

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

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

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

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

private static String word = "Hello World!";

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

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

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

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

類執(zhí)行

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


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

類加載子系統(tǒng)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/75097.html

相關(guān)文章

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

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

    Keven 評論0 收藏0
  • 所不知道 ? Blockchain

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

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

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

    liujs 評論0 收藏0
  • 所不知道 ? URL

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

    weizx 評論0 收藏0
  • 前端面試所不知道系列

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

    Julylovin 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<