丨java編譯器一手寫有什么優(yōu)勢_第1頁
丨java編譯器一手寫有什么優(yōu)勢_第2頁
丨java編譯器一手寫有什么優(yōu)勢_第3頁
丨java編譯器一手寫有什么優(yōu)勢_第4頁
丨java編譯器一手寫有什么優(yōu)勢_第5頁
已閱讀5頁,還剩18頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

到現(xiàn)在,Java已經(jīng)是一門非常成語言了,而且它也在不斷進化,與時俱進,泛型、函與此同時,Java20對于一門、普及又不發(fā)新的語說,它的技術(shù)會帶來兩個好處:一方面Jaa編譯器所采用的技術(shù)肯定是比較成、靠譜的,你在實現(xiàn)自己的編譯功能時,完全可以去參考和借鑒;另一方面,你可以借此深入了解Java譯過程,借此去實現(xiàn)一些高級的功能,比方說,按需生成字節(jié)碼,就像pring4Java(javac)4時間在Java的JIT編譯器上。JavaJavaJava如何自己動手修改Java第一步,我們先初步了解一下Java初步了解JavaJavajavacJavaMyClasspublicclassMyClasspublicinta=publicintintb=a+return 7javac命令把MyClass.java代代1javac那這個javac的可執(zhí)行文件就是Java的編譯器嗎?并不是。javac只是啟動了一個Java虛擬機,執(zhí)行了一個Java程序,跟我們平常用“java”命令運行一個程序是一樣的。換句話說,Java編譯器本身也是用Java寫的。一門語言的編譯器,竟然可以用自己來實現(xiàn)。這種現(xiàn)象,叫做“自舉”(Bootstrap),JavaJavaJava譯器。比如,運行下面的示例代碼,也同樣可以編譯MyClass.java文件,生成MyClass.class文件:代代123456789importimportpublicclassCompileMyClasspublicstaticvoidmain(String[]args){pilercompiler=ToolProvideintresult=compiler.run(null,null,null,System.out.println("Compileresultcode="+}} piler就是Java編譯器的,屬于 piler模塊。這個模塊包含了Java語言的模型、注解的處理工具,以及Java編譯器的API。 piler的實現(xiàn)是 piler模塊中,這個模塊里才是Java不過,在探索Java編譯器的實現(xiàn)原理之前,你還需要從JDK的源代碼,我使用的版本是JDK14。在IDE中piler的執(zhí)行過程,你就會看到它一步一步地都是使用了哪個類的哪個方法。Java的IDE工具一般都比較友好,給我們的探openjdk的JDK。你還可以修改源代獲得了源代碼以后,我建議你重點關(guān)注這幾個地方的源代碼,這能幫助你迅速熟悉Java編首先是com.sun.source.tree包,這個包里面是Java語言的AST模型。我們在寫一個編譯器的時候,肯定要設(shè)計一個數(shù)據(jù)結(jié)構(gòu)來保存AST,那你就可以去參考一下Java是怎么做IfBlockTree圖1:com.sun.source.tree包里的Java語言的ASTcom.sun.tools.javac.parser.Lexer(詞法解析器接口),它可以把字符流變成一個個的Token,具體的實現(xiàn)在Scanner和JavaTokenizer類中。com.sun.tools.javac.parser.Parser(語法解析器接口),它能夠解析類型、語句和表達式,具體的實現(xiàn)在JavacParser類中。總結(jié)起來,Java語言中與編譯有關(guān)的功能放在了兩個模塊中:其中, piler模塊主 piler中有具體的實現(xiàn)。不過你要注意,像com.sun.tools.javac.parser包中的類,不是Java語言標準的組成部分,如果你直接使用這些類,可能導(dǎo)致代碼在不同的JDK版本中不兼容。現(xiàn)在,我們已經(jīng)熟悉了Jaa編譯器的概要信息。在瀏覽這兩個模塊的代碼時,我們會發(fā)現(xiàn)里面的內(nèi)容非常多。為了讓自己不會迷失在其中,我們需要找到一個方法。你已經(jīng)知道,編譯器的前端分為詞法分析、語法分析、語義分析等階段,那么我們就可以按照這個階段一塊一塊地去探索。首先,我們看看Java通過執(zhí)行,你會發(fā)現(xiàn)詞法分析器的具體實現(xiàn)在JavaTokenizer類中。你可以先找到這個類,在readToken()方法里打個斷點,讓程序運行到這里,然后查看詞法分析的執(zhí)行過圖2:一個有限自動機,能夠區(qū)分數(shù)字字面量(狀態(tài)1)和標識符(狀態(tài)那么實戰(zhàn)中,JavareadToken(個方法實現(xiàn)了主干的詞法分析邏輯,它能夠從字符流中識別出一個個的Token來。代代1234casecase556789caseA-Za-case0之后是X或x,或者1-casecaseisSpectial(),也就是%*+-|等特殊字符圖3:Java詞法分析器的有限自動機 第2講中我提到過,關(guān)鍵字和標識符的規(guī)則是的:標識符的規(guī)則是以A-Za-z_開頭,后續(xù)字符可以是A-Za-$_這種是詞法分析的一個,因為不到最后你不知道讀入的是一個關(guān)鍵字,還是一個普通的標識符。如果單純按照有限自動機的算法去做詞法分析,想要區(qū)分int關(guān)鍵字和其他標識符的話,你就會得到圖4那樣的一個有限自動機。當(dāng)輸入的字符串是“int”。如果這個時候遇到結(jié)束字符,就會提t(yī)關(guān)鍵字。除此之外,“i”(狀態(tài))、“in”3“intA”(狀態(tài)都屬于標識符。圖4:int但是關(guān)鍵字有很多,feetgassa是怎么處理這個問題的呢?Jaa編譯器的處理方式比較簡單,分成了兩步:首先把所有的關(guān)鍵字和標識符都作為標識通過這樣的代碼分析,你可以發(fā)現(xiàn):Java我建議你在IE中,采用調(diào)試模式執(zhí)行,看看每一步的執(zhí)行結(jié)果,這樣你能對Jaa法分析的過程和結(jié)果有更直觀的理解。另外,你還可以寫一個程序,直接使用詞法分析器做解析,并打印出一個個en。這會很有趣,你可以試試看!接下來,我們進一步研究一下Java下面的AST就是MyClass.java示例代碼對應(yīng)的AST(其中的JCXXX節(jié)點都是實現(xiàn)了com.sun.source.tree中的接口,比如JCBinary實現(xiàn)了BinaryTree接口,而J eral實現(xiàn)了Li lTree接口)。圖5:MyClass.java對應(yīng)的以LR那么,Java你可以打開com.sun.tools.javac.parser.JavacParser這個類看一下代碼。比如,你首先查看一下parseExpression()方法(也就是解析一個表達式)。閱讀代碼,你會看到這樣的調(diào)圖6:第1termterm是什么呢?其實,它就是賦值表達式,比如“a=2”或“b=3”等。算法里把這樣一個匹配過程又分為兩部分,賦值符號左邊的部分是term1,其他部分是termRest。其中,term1是必須匹配上的,termRest是可選的。如果匹配上了termRest,那么證明這是個賦值表達式;否則就只是左邊部分,也就是term1。另外,你可能還會對Rest這個單詞特別敏感。你還記得我們在什么地方提到過Rest這個詞匯嗎?是的,在第3講中,我把左遞歸改寫成右遞歸的時候,那個右遞歸的部分們一般就叫做XXXRest或XXXTail。第2步,匹配term1term1又是什么呢?term1是一個三元表達式,比如a>3?1:2。其中,比較操作符左邊的部分是term2,剩下的部分叫做term1Rest。其中term2是必須匹配的,term1Rest第3步,匹配term2term2term3term2Rest第4步,匹配term3term32第5步,匹配term2Rest首先匹配“+”操作符;然后匹配一個term3(),這里是返回一個字面量36term1()term1Rest,沒有匹配上。第7步,回到term()方法,試圖匹配termRest,也沒有匹配上。第8步,從term()方法返回一“2+3”的AST,如下圖所示圖7:“2+3”對應(yīng)的第一,這是一個遞歸下降算法。termterm1、代代1add->add+代代add->muladd'->+add'|如果我一下表達方式,就會變成Java語法解釋器里的代碼邏輯代代term2->term3term2Rest->+term3|語則生成的AS,乘法節(jié)點會在加法節(jié)點下面,因此先于加法節(jié)點計算,從而優(yōu)先級更高。實際上,Javat1->term2->term3的過程,也是優(yōu)先級逐步提高的過程。代代add->muladd'->+muladd'|mul->primul'->*primul'|在t2中,實際上它解析了所有的二元表達式,在語則上,它把使“&&”“+”“*”代代term2->term3term2Rest->(&&|>|+|*|...)term3|我們再來看看結(jié)合性。對于“2+3+4”這樣一個表達式,我在第3講,是把右遞歸調(diào)term2Rest3們都是用循環(huán)的方式,來處理連續(xù)加法或者連續(xù)乘法,并生成結(jié)合性正確的AST。Java于“2+3*5”這樣采用了多種不同優(yōu)先級的操作符的表達式,也能通過一個循環(huán)就處理掉了,并且還保證了優(yōu)先級的正確性。在123456"=="|7"<"|">""<="|8"<<"||9"+"|"-"*"|"/"如果按照常規(guī)的寫法,我們處理上面10級優(yōu)先級的操作符,需要寫10級嵌套的結(jié)構(gòu)。而Java用一級就解決了。這個就在term2Rest()的實現(xiàn)中。我們以“2*3+4*5”為例term2Rest()算法了一個操作數(shù)的棧(odStack)和操作符的棧(opStack),作為工作區(qū)。算根據(jù)odStack、opStack和后續(xù)操作符這三個信息,決定如何生成優(yōu)先級正確的AST。我把解析“2*3+4*5”時棧的變化,畫成了一張圖。圖8:解析“2*3+4*5”的時候,odStack、opStack在一步一步解析的過程中,當(dāng)opStack的棧頂運算符的優(yōu)先級大于等于后續(xù)運算符的優(yōu)先級時,就會基于odStack棧頂?shù)膬蓚€元素創(chuàng)建一棵二元表達式的子樹,就像第2步那樣。反過來的話,棧頂運算符的優(yōu)先級小于后續(xù)運算符的優(yōu)先級(像第4步那樣),就會繼續(xù)這就可以保證,優(yōu)先級高的操作符形成的子樹,總會在最后的AST的下層,從而優(yōu)先級更再仔細研究一下這個算法,你會發(fā)現(xiàn),它是借助一個工作區(qū),自底向上地組裝AST。是不是覺得很眼熟?是不是想到了LR沒錯,這就是一個簡單LR其實,這種處理表達式優(yōu)先級的解析方法,有一個專有的名字,就叫做rator-PrecedenceParse)”Java0的二元表達式的解析,同時又不用擔(dān)心左遞歸問題,確實很棒!本節(jié)課,我?guī)懔薐ava編譯器的一角,強調(diào)這樣幾個重點第一,你要大致熟悉一下Java語言中與編譯有關(guān)的模塊、包和類。這樣,在你需要的時候,可以通過編程來調(diào)用編譯器的功能,在運行時動態(tài)編譯Java程序,并動態(tài)加載運行。Java自頂向下的遞歸下降算法。在解決左遞歸問題時,也采用了標準的改寫文法的方法。但是,在處理二元表達式時,局部采用了自底向上級解析器,使得算法更簡潔。Java的詞法和語法解析功能的每個細節(jié)。生式。而你通過閱讀代碼,會了解Java的編譯器是如何解決這個問題的:它在一些語法上會預(yù)讀一個Token,在另外的語法上會預(yù)讀兩個、三個Token,以及加上一些與上下文有關(guān)的代碼,通過種種方式來減少回溯,提高編譯性能。這,實際上就是采用了LL(k)算法的思路,而k值是根據(jù)需要來增加的。通過今天的分析,你會發(fā)現(xiàn)Jaa編譯器在做詞法和語法分析的時候,總體上遵循了編譯原理中的知識點,比如構(gòu)造有限自動機、改寫左遞歸文法等等,但又巧妙地引入了不少的變化,包括解決詞則、融合了自頂向下算法和自底向上算法、根據(jù)情況靈活地預(yù)讀n等。我相信對你會大有啟發(fā)!像這樣的實戰(zhàn)知識,恐怕只有分析實際編譯器代代1

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論