編譯器、直譯器與執行期環境(概覽)
這三個詞,指的是讓你的原始碼真正「動起來」的幾位幫手,而初學者老是把它們搞混。快速比喻:編譯器是一位譯者,交給你一本翻好的成書;直譯器是一位現場口譯員,邊走邊念出來;執行期環境則是後勤——場地、麥克風、燈光——這場演出要能進行,它就非在場不可。
編譯器是一個讀取原始碼、事先把它翻譯成另一種形式(通常是機器碼)的程式,產生一個你日後可執行的檔案。直譯器是一個讀取原始碼(或一種半成品形式、叫位元組碼)並在程式執行時逐步直接實現其意義的程式——不會產生獨立的可執行檔。執行期環境(或執行期系統)則是你的程式在執行時所需的支援程式碼與服務:例如記憶體管理、標準函式庫中必須在場的部分、垃圾回收,或一台虛擬機。即使是編譯好的 C 程式,也倚靠一小段 C 執行期,在 main 開始前先把環境設好。
為何重要:把它們分清楚,能解釋許多令人困惑的情境。為什麼 Java 程式需要安裝 JVM(那是它的執行期環境兼直譯器/JIT)?為什麼編譯好的 C 程式仍需要系統上有 C 函式庫(那是它執行期的一部分)?為什麼同一個 .py 檔在兩台機器上表現不同(直譯器版本不同)?一言以蔽之:編譯器=執行前翻譯;直譯器=執行時邊翻邊做;執行期環境=執行時必須存在的支援。許多真實系統三者並用。
跑一個 Java 應用程式三者並用:編譯器把 MyApp.java 變成位元組碼;JVM 充當執行期環境,直譯或 JIT 編譯那段位元組碼;而執行期環境也在程式執行時提供垃圾回收與核心函式庫。
先編譯,再跑在一個會直譯/JIT 的執行期環境上——三種角色,常常同時出現。
一個程式可以扮演好幾種角色:gcc 是編譯器,但它也會跑前置處理器並呼叫連結器;一個 JIT 同時直譯又編譯。這些標籤指的是「正在做的工作」,而不是彼此互斥的盒子。