JVM-程式編譯與代碼早期(編譯期)最佳化,jvm-編譯

來源:互聯網
上載者:User

JVM-程式編譯與代碼早期(編譯期)最佳化,jvm-編譯
 早期(編譯期)最佳化

一、Javac編譯器

  1.Javac的原始碼與調試

    Javac的原始碼放在JDK_SRC_HOME/langtools/src/shares/classes/com/sun/tools/javac中,除了JDK自身的API之外,就只引用了JDK_SRC_HOME/langtools/src/shares/classes/com/sun/*裡面的代碼,調試環境建立起來簡單方便,因為基本上不需要處理依賴關係。

    編譯過程大致可以分成3個過程:

    (1)解析與填充符號表過程

    (2)插入式注釋處理器的註解過程處理

    (3)分析與位元組碼產生過程

    Javac編譯動作的入口是com.sun.tools.javac.main,JavaCompikler類,上述3個過程的代碼邏輯集中在這個類的compiler()和compiler2()方法中。

 

  2.解析與填充符號表

    解析步驟包括詞法分析和文法分析兩個過程

  (1)詞法、文法分析

詞法分析是將原始碼的位元組流變成標記(Token)集合,單個字元是程式編碼過程的最小元素,而標記則是編譯過程的最小元素。

    在Javac的原始碼中,詞法分析過程由com.sun.tools.javac.parser.Scanner類來實現。

    詞法分析是根據Token序列構造抽象文法樹的過程,抽象文法是一種用來描述程式碼文法結構的樹形表示方式,文法樹的每一個節點都代表著程式碼中的一個文法結構。

    文法分析過程由com.sun.tools.javac.parser.Parse類來實現,這個階段產生出抽象文法樹有com.sun.tools.javac.tree.JTree類表示,經過這個步驟之後,編譯器就基本不會再對原始碼檔案進行操作了,後續的操作都建立在抽象文法樹上。

 

   (2)填充符號表

      符號表(Symbol Table)是由一組符號地址和符號資訊構成的表格。

      在文法分析中,符號表所登記的內容將用於文法分析檢查和產生中間代碼。

      在目標代碼產生階段,當對符號名進行地址分配時,符號表是地址分配的依據。

      在Javac原始碼中,填充符號表的過程由com.sun.tools.javac.compiler.Enter類來實現,此過程的出口是一個待處理列表(ToDoList),包含;了每一個編譯單元的抽象文法樹的頂級節點以及package-info-java的頂級節點。

 

  3.註解處理器

    在Javac源碼中,插入式註解處理器的初始化過程是在initProcessAnnotations()方法中完成的,而它的執行過程則是在ProcessAnnotations()方法中完成的。這個方法判斷是否有新的註解處理器需要執行,如果有的話,通過com.sun.tools.javac.Processing.JavacProvcessingEnviroment類的doProcessing()方法產生一個新的JavaCompiler對象對編譯的後續步驟進行處理。

 

  4.語義分析與位元組碼產生

    (1)標註檢查:內容包括諸如變數使用前後是否已被聲明,變數與賦值之間的資料類型是否能夠匹配等。在標註檢查步驟中,還有一個重要的動作,稱為常量摺疊。

      標註檢查步驟在javac原始碼中實作類別是com.sun.tools.javacComp.Attr類和com.sun.tools.javac.comp.Check類。

    (2)資料及控制分析

      對程式上下文邏輯更進一步的驗證,它可以檢查出諸如程式局部變數在使用前後是否有賦值,方法的每一條路徑是否都有傳回值,是否所有的受檢查異常都被正確出來了等問題。

      在Javac的原始碼中,資料及控制流程分析的入口是flow()方法,具體操作是由com.sun.tools.javac.comp.Flow類來完成的。

    (3)解文法糖

      文法糖(Syntatic Sugar),也稱糖衣文法,指在電腦語言中添加的某種文法,這種文法對語言的功能並沒有影響,但是更方便使用。

      在Javac的原始碼中,解文法糖的過程由的desugar()方法觸發,在com.dun.tools.javac.comp.TransTypes類和com.sun.tools.javac.comp.Lower類中完成。

    (4)位元組碼產生

      位元組碼產生是Javac編譯過程的最後一個階段,在Javac原始碼裡面有com.sun.tolls.javac.jvm.Gen類來完成。

  完成了文法樹的遍曆和調整之後,就會把填充了所有需要資訊的符號表交給com.sun.tolls.javac.jvm.ClassWrite類,由這個類的WiteClass()方法輸出位元組碼,產生最終的class檔案。到此為止整個編譯過程就結束了。 

 

二、Java文法糖

  1.泛型與類型擦除

    C#裡面泛型無論在程式源碼中,編譯後的IL中,貨值運行期的CLR中,都是切實存在的,List<int>與List<string>就兩個不同稍微類型,它們在系統運行期產生,有自己的虛方法表和,類型資料,這種實現機制稱為類型膨脹,基於這種方法實現的泛型稱為真是泛型。

    Java語言中的泛型不一樣,它只在程式原始碼中存在,在編譯後的位元組碼檔案中,就已經替換為原來的原生類型了,並且在相應的地方插入了強制轉型代碼,因此,對於運行期的Java語言來說,ArrayList<String>與ArrayList<int>就是同一個類,所以泛型技術實際上是Java語言的一顆文法糖,java語言中的泛型實現方法稱為類型擦除,基於這種方法的泛型稱為偽泛型。

    虛擬機器規範中引入了諸如Signature,LocalVariableType等新的屬性用於解決伴隨泛型而來的參數類型識別問題。

 

  2.自動裝箱、拆箱與遍曆迴圈

  自動裝箱、拆箱在編譯之後轉化成了對應的封裝盒還原方法,而遍曆迴圈則把代碼還原成迭代器的實現。

  封裝類的“==”運算在不遇到算術符運算的情況下不會自動拆箱,以及它們equals()方法不處理資料轉型的關係。

 

  3.條件編譯

  Java語言可以進行條件編譯,方法就是使用條件為常量的if語句。

  Java語言中條件編譯的實現是,Java語言的一顆文法糖,根據布爾常量的真假,編譯器將會把分支中不成立的代碼清除掉。這一項工作將在編譯器解除文法糖階段(com.sun.tools.javac.comp.Lower類中)實現。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.