Java語言是" 解釋執行" 的語言嗎
本篇來自周志明的<<深入理解java虛擬機器>>
許多Java虛擬機器的執行引擎在執行Java程式碼的時候都有解釋執行(通過直譯器執行)和編譯執行(通過即時編譯器產生原生代碼執行)兩種選擇,在本章中,我們先來探討一下在解釋執行時,虛擬機器執行引擎是如何工作的。
解釋執行
Java語言經常被人們定位為“解釋執行”的語言,在Java初生的JDK 1.0時代 ,這種定義還算是比較準確的, 但當主流的虛擬機器中都包含了即時編譯器後,Class檔案中的程式碼到底會被解釋執行還是編譯執行,就成了只有虛擬機器自己才能準確判斷的事情。再後來 ,Java也發展出了可以直接生成原生代碼的編譯器[如GCJ」(GNU Compiler for the Java )],而C/C++語言也出現了通過直譯器執行的版本(如CINT) ,這時候再籠統地說“解釋執行”,對於整個 Java語言來說就成了幾乎是沒有意義的概念,只有確定了談論物件是某種具體的Java實現版本和執行引擎執行模式時,談解釋執行還是編譯執行才會比較確切。
一、你可以說它是編譯型的。因為所有的Java程式碼都是要編譯的,.java不經過編譯就什麼用都沒有。
二、你可以說它是解釋型的。因為java程式碼編譯後不能直接執行,它是解釋執行在JVM上的,所以它是解釋執行的,那也就算是解釋的了。
三、但是,現在的JVM為了效率,都有一些JIT優化。它又會把.class的二進位制程式碼編譯為本地的程式碼直接執行,所以,又是編譯的。
不論是解釋還是編譯,也不論是物理機還是虛擬機器,對於應用程式,機器都不可能如人那樣閱讀、理解 ,然後就獲得了執行能力。大部分的程式程式碼到物理機的目的碼或虛擬機器能執行的指令集之前,都需要經過圖8-4中的各個步驟。如果讀者對編譯原理的相關課程還有印象的話,很容易就會發現圖8-4中下面那條分支,就是傳統編譯原理中程式程式碼到目標機器程式碼的生成過程,而中間的那條分支,自然就是解釋執行的過程。
如今,基於物理機、Java虛擬機器,或者非Java的其他高階語言虛擬機器(HLLVM )的語 言 ,大多都會遵循這種基於現代經典編譯原理的思路,在執行前先對程式原始碼進行詞法分析和語法分析處理,把原始碼轉化為抽象語法樹( Abstract Syntax Tree,AST)。對於一門具體語言的實現來說,詞法分析、語法分析以至後面的優化器和目的碼生成器都可以選擇獨立於執行引擎,形成一個完整意義的編譯器去實現,這類代表是C/C++語言。也可以選擇把其中一部分步驟(如生成抽象語法樹之前的步驟)實現為一個半獨立的編譯器,這類代表是Java 語言。又或者把這些步驟和執行引擎全部集中封裝在一個封閉的黑匣子之中,如大多數的JavaScript執行器。
圖8-4 編譯過程
Java語言中 ,Javac編譯器完成了程式程式碼經過詞法分析、語法分析到抽象語法樹,再遍歷語法樹生成線性的位元組碼指令流的過程。因為這一部分動作是在Java虛擬機器之外進行的, 而直譯器在虛擬機器的內部,所以Java程式的編譯就是半獨立的實現。