程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> JVM-程序編譯與代碼早期(編譯期)優化,jvm-編譯

JVM-程序編譯與代碼早期(編譯期)優化,jvm-編譯

編輯:JAVA綜合教程

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類中)實現。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved