程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Javac編譯的四個過程

Javac編譯的四個過程

編輯:JAVA綜合教程

Javac編譯的四個過程


??Javac編譯過程大致分為4個過程,分別是:

詞法分析語法分析語義分析代碼生成

詞法分析

??詞法分析是將源代碼的字符流轉變為標記(Token)集合,單個字符是程序編寫過程的最小元素,而標記則是編譯過程的最小元素,關鍵字、變量名、字面量、運算符都可以成為編輯,如“int a+b=2”這句代碼中包含了6個標記,分別是int、a、=、b、+、2,雖然關鍵字int由三個字符構成,但是它只是一個Token,不可再拆分。在Javac的源碼中,詞法分析過程由com.sun.tools.javac.parser.Scanner類來實現。


語法分析

??詞法分析器的作用是將Java源文件的字符流轉變成對應的Token流。而語法分析器是將詞法分析器分的Token流組件成更加結構化的語法樹,也就是將一個個單詞組裝成一句話,一個完整的語句。哪些詞語組合在一起是主語,哪些是謂語、哪些是賓語、哪些是定語等沒要做進一步區分。
??語法分析是根據Token序列構造抽象語法樹的過程,抽象語法樹是一種用來描述程序代碼語法結構的樹形表示方式,語法樹的每一個節點都代表著程序代碼中的一個語法結構,例如包、類型、修飾符、運算符、接口、返回值甚至代碼注釋等都可以是一個語法結構。語法分析過程由com.sun.tools.javac.parser.Parser類實現,這個階段產出的抽象語法樹由com.sun.tools.javc.tree.JCTree類表示,經過這個步驟之後,編譯器就基本不會再對源碼文件進行操作了,後續的操作都是建立在抽象語法樹上。


語義分析

??語法分析之後,編譯器獲得了程序代碼的抽象語法樹表示,語法樹能表示一個結構正確的源程序的抽象,但無法保證源程序是符合邏輯的。語義分析是要在語法樹的基礎上再做一些處理,如給類添加默認的構造函數,檢查變量在使用前是否已經初始化,將一些常量進行合並處理,檢查操作變量類型是否匹配,檢查所有的操作語句是否可達,檢查checked exception是否正確處理。
??語義分析階段分為:填充符號表、標注檢查、數據及控制流分析。

填充符號表
??符號表是由一組符號地址和符號信息構成的表格,讀者可以把它想象成哈希表K-V值對的形式。符號表中所登記的信息在編譯的不同階段都要用到。在語義分析中,符號表所登記的內容將用於語義檢測和產生中間代碼。在目標代碼生成階段,當對符號名進行地址分配時,符號表是地址分配的依據。在Javac源碼中,填充符號表的過程由com.sun.tools.javac.comp.Enter類實現。
??一個類除了類本身會定義一些符號變量如類名稱、變量名稱和方法名稱等,還有一些符號是引用其它類的,這些符號會調用其它類的方法或者變量等,還有一些類可能會繼承或者實現超類和接口等。這些符號都是在其他類中定義的,那麼就需要將這些類的符號也解析到符號表中。
??在Enter類解析這一步驟中,還有一個重要的步驟就是添加默認的構造函數。如果代碼中沒有提供任何構造函數,那麼編譯器將會添加一個沒有參數、訪問下與當前一致的默認構造函數。

標注檢查
??檢查的內容包括諸如變量的類型是否匹配、變量在使用前是否已經初始化、能夠推導出泛型方法的參數類型、字符串常量的合並(常量折疊)。在標注檢查步驟中一個重要的動作稱為常量折疊,如果我們在代碼中寫了如下定義:

int a=1+2;

??那麼在語法樹上仍然能看到字面量1、2以及操作符+,但是在進過常量折疊之後,他們將會被折疊為字面量3.實現的類是com.sun.tools.javac.comp.Attr類和com.sun.tools.javac.comp.Check類。

數據流分析
??數據流主要完成如下工作:

檢查變量在使用前是否都已經被正確賦值。保證final修飾的變量不會被重復賦值。要確定方法的返回值類型。這裡需要檢查方法的返回值類型是否確定,並檢查接受這個方法返回值的引用類型是否匹配,如果沒有返回值,則不能有任何引用類型指向方法的這個返回值。所有的Checked Exception都要捕獲或者向上拋出。所有的語句都要被執行到。這裡會檢查是否有語句出現在一個return方法的後面,因為在return方法後面的語句永遠也不會被執行到。

控制流分析
??控制流主要完成如下工作:

去掉無用的代碼,比如永假的if代碼塊。變量的自動轉換,比如自動裝箱拆箱。去除語法糖。解語法糖的過程由desugar()方法觸發,在com.sun.tools.javac.comp.TransTypes和com.sun.tools.javac.comp.Lower類中完成。
數據流及控制流的分析入口是flow()方法,具體操作由com.sun.tools.javac.comp.Flow類來完成。

字節碼生成

??由com.sun.tools.javac.jvm.Gen類來完成。字節碼階段不僅僅把前面各個步驟所生成的信息(語法樹、符號表)轉化成字節碼寫到磁盤中,編譯器還進行了少量的代碼添加和轉換工作。
實例構造器方法和類構造器方法就是在這個階段添加到語法樹中的。
??生成java字節碼需要經過以下兩個步驟:

將java方法中的代碼塊轉化成符合JVM語法的命令形式,JVM的操作都是基於棧的,所有的操作都必須經過出站和進展來完成。按照JVM的文件組織格式將字節碼輸出到以class為擴展名的文件中。

??在jdk1.5之後,java語言提供了對注解(Annotation)的支持,這些注解與普通的Java代碼一樣,是在運行期間發揮作用的。在Jdk1.6中提供了一組插入式注解處理器的標准API在編譯期間對注解進行處理,我們可以把它看做是一組編譯器的插件,在這些插件裡面,可以讀取、修改、添加抽象語法樹中的任意元素。如果這些插件在處理注解期間對語法樹進行了修改,編譯器將回到解析及填充符號表的過程重新處理,直到所有插入式注解處理器都沒有再對語法樹進行修改為止。對注解的處理是在填充符號表之後及在標注注解之前發生的。


   

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