一、簡(jiǎn)述
Java代碼編譯和執(zhí)行的整個(gè)過程包含了三個(gè)重要的機(jī)制:①Java源碼編譯機(jī)制;②類加載機(jī)制;③類執(zhí)行機(jī)制
二鳍怨、Java源碼編譯機(jī)制
Java代碼編譯是由Javac編譯器來完成,流程如圖:Javac是一種編譯器跪妥,能將一種語言規(guī)范轉(zhuǎn)化成另外一種語言規(guī)范,通常編譯器都是將便于人理解的語言規(guī)范轉(zhuǎn)化成機(jī)器容易理解的語言規(guī)范声滥,如C/C++或者匯編語言都是將源代碼直接編譯成目標(biāo)機(jī)器碼眉撵,這個(gè)目標(biāo)機(jī)器代碼是CPU直接執(zhí)行的指令集合。這些指令集合也就是底層的一種語言規(guī)范落塑。
Javac的編譯器也是將Java這種對(duì)人非常友好的編程語言編譯成對(duì)所有機(jī)器都非常友好的一種語言纽疟。這種語言不是針對(duì)某種機(jī)器或某個(gè)平臺(tái)。怎么消除不同種類憾赁,不同平臺(tái)之間的差異這個(gè)任務(wù)就有JVM來完成污朽,而Javac的任務(wù)就是將Java源代碼語言轉(zhuǎn)化為JVM能夠識(shí)別的一種語言,然后由JVM將JVM語言再轉(zhuǎn)化成當(dāng)前這個(gè)機(jī)器能夠識(shí)別的機(jī)器語言龙考。
Javac的任務(wù)就是將Java源代碼編譯成Java字節(jié)碼蟆肆,也就是JVM能夠識(shí)別的二進(jìn)制代碼,從表面看是將.java文件轉(zhuǎn)化為.class文件晦款。而實(shí)際上是將Java源代碼轉(zhuǎn)化成一連串二進(jìn)制數(shù)字炎功,這些二進(jìn)制數(shù)字是有格式的,只有JVM能夠真確的識(shí)別到底代表什么意思缓溅。
編譯器把一種語言規(guī)范轉(zhuǎn)化為另一種語言規(guī)范的這個(gè)過程需要哪些步驟蛇损?參照《編譯原理》,總結(jié)過程如下:
1??詞法分析:讀取源代碼坛怪,一個(gè)字節(jié)一個(gè)字節(jié)的讀進(jìn)來淤齐,找出這些詞法中定義的語言關(guān)鍵詞如:if、else袜匿、while等更啄,識(shí)別哪些if是合法的哪些是不合法的。這個(gè)步驟就是詞法分析過程居灯。
詞法分析的結(jié)果:就是從源代碼中找出了一些規(guī)范化的token流锈死,就像人類語言中贫堰,給你一句話你要分辨出哪些是一個(gè)詞語,哪些是標(biāo)點(diǎn)符號(hào)待牵,哪些是動(dòng)詞其屏,哪些是名詞。
2??語法分析:就是對(duì)詞法分析中得到的token流進(jìn)行語法分析缨该,這一步就是檢查這些關(guān)鍵詞組合在一起是不是符合Java語言規(guī)范偎行。如if的后面是不是緊跟著一個(gè)布爾型判斷表達(dá)式。
語法分析的結(jié)果:就是形成一個(gè)符合Java語言規(guī)定的抽象語法樹贰拿,抽象語法樹是一個(gè)結(jié)構(gòu)化的語法表達(dá)形式蛤袒,它的作用是把語言的主要詞法用一個(gè)結(jié)構(gòu)化的形式組織在一起。這棵語法樹可以被后面按照新的規(guī)則再重新組織膨更。
3??語義分析:語法分析完成之后也就不存在語法問題了妙真,語義分析的主要工作就是把一些難懂的,復(fù)雜的語法轉(zhuǎn)化成更簡(jiǎn)單的語法荚守。就如難懂的文言文轉(zhuǎn)化為大家都懂的白話文珍德,或者是注釋一下一些不懂的成語。
語義分析結(jié)果:就是將復(fù)雜的語法轉(zhuǎn)化為簡(jiǎn)單的語法矗漾,對(duì)應(yīng)到Java就是將foreach轉(zhuǎn)化為for循環(huán)锈候,還有一些注釋等。最后生成一棵抽象的語法樹敞贡,這棵語法樹也就更接近目標(biāo)語言的語法規(guī)則泵琳。
從上面的描述中得知編譯就是將一種語言通過分析分解蛔垢,再按照一定的方式先形成一個(gè)簡(jiǎn)單的框架(將Java源文件的字節(jié)流轉(zhuǎn)化為對(duì)應(yīng)的token流)蛛倦。然后再通過詳細(xì)的分析按照一定的規(guī)定在這個(gè)框架里添加?xùn)|西使這個(gè)token流形成更加結(jié)構(gòu)化的語法樹(就是將前面生成的token流中的一個(gè)個(gè)單詞組裝成一句話),但是這棵樹離目標(biāo)———Java字節(jié)碼還有點(diǎn)差距啦桌,所以再進(jìn)行語義分析使那顆粗糙的樹更加完整完善(給類添加默認(rèn)的構(gòu)造函數(shù)溯壶,檢查變量在使用前有沒有初始化,檢查操作變量類型是否匹配)甫男,然后javac編譯器調(diào)用com.sun.tools.javac.jvm.Gen類遍歷這棵語法樹將java方法中的代碼塊轉(zhuǎn)換成符合JVM語法的命令形式的二進(jìn)制數(shù)據(jù)且改。按照J(rèn)VM的文件組織格式將字節(jié)碼輸出到以class為擴(kuò)展名的文件中,也就是生成最終的java字節(jié)碼板驳。詞法分析就是將關(guān)鍵詞組織成token流即檢查源碼中的的關(guān)鍵詞是否正確并組織成token流又跛,而語法分析就是檢查源碼是否符合java語法規(guī)范并將詞組成語句。語義分析就是簡(jiǎn)化復(fù)雜的添加缺少的若治,檢查變量類型是否合法慨蓝。代碼生成器就是遍歷這棵樹生成符合JVM規(guī)范的代碼感混。
最后生成的class文件由以下部分組成:
①結(jié)構(gòu)信息。包括class文件格式版本號(hào)及各部分的數(shù)量與大小的信息礼烈。
②元數(shù)據(jù)弧满。對(duì)應(yīng)于Java源碼中聲明與常量的信息。包含類此熬、繼承的超類庭呜、實(shí)現(xiàn)的接口的聲明信息、域與方法聲明信息和常量池犀忱。
③方法信息募谎。對(duì)應(yīng)Java源碼中語句和表達(dá)式對(duì)應(yīng)的信息。包含字節(jié)碼阴汇、異常處理器表数冬、求值棧與局部變量區(qū)大小、求值棧的類型記錄搀庶、調(diào)試符號(hào)信息拐纱。
三、類執(zhí)行機(jī)制
Java字節(jié)碼的執(zhí)行是由JVM執(zhí)行引擎來完成地来,流程圖如下:
JVM是基于棧的體系結(jié)構(gòu)來執(zhí)行class字節(jié)碼的。線程創(chuàng)建后熙掺,都會(huì)產(chǎn)生程序計(jì)數(shù)器和棧未斑,程序計(jì)數(shù)器存放下一條要執(zhí)行的指令。棧中存放一個(gè)個(gè)棧幀币绩,每個(gè)棧幀對(duì)應(yīng)著每個(gè)方法的每次調(diào)用蜡秽,而棧幀又是由局部變量區(qū)和操作數(shù)棧兩部分組成,局部變量區(qū)用于存放方法中的局部變量和參數(shù)缆镣,操作數(shù)棧中用于存放方法執(zhí)行過程中產(chǎn)生的中間結(jié)果芽突。棧的結(jié)構(gòu)如下圖: