簡體   English   中英

Java 編譯與 Perl 編譯

[英]Java Compilation vs Perl Compilation

Java 和 Perl 的編譯過程有何不同? 兩者都產生一個字節碼,但之后會發生什么? perl 中的解釋和 java 中從目標代碼到機器代碼的轉換是否完全不同? 如果是這樣,那么為什么 Java 不能成為腳本語言?

這個問題沒有明確的答案,但無論如何我都會嘗試。

Java 可以更積極地編譯代碼,因為它不像 Perl 那樣動態。 Java 不適合作為腳本語言的原因是

  • 你必須編寫相當多的代碼才能做一些簡單的事情。 例如,“hello world”是 5 行。
  • 與 Perl 相比,文件和字符串操作相對復雜。
  • 很難從 Java 運行另一個程序。
  • 您可以使用 BeanShell 或 Groovy 編寫 Java 腳本,但您不會,因為有一長串語言是更好的選擇。 例如 bash 開始。

Java 和 Perl 本身不是編譯或解釋的語言,但兩者都只有一個主要實現。

爪哇

Java 源代碼提前編譯為可移植的字節碼。 在此步驟中應用了一些優化。 該字節碼隨后由 JVM 執行,通過解釋或 JIT 編譯,由 JVM 選擇。 該語言中沒有任何內在的東西會阻止編譯 + 執行。

珀爾

在 perl 解釋器中,VM 和編譯器是緊密集成的。 即使在解析源代碼期間,某些部分也可能已經執行。 每個可執行單元產生一個“操作碼樹”,它同時具有 AST 和字節碼的作用。 這種增量編譯意味着不可能真正將編譯與執行分開,盡管有時可以緩存編譯結果,或緩存到 optree 的 JIT 部分。 然后解釋操作碼。

比較

Perl 的編譯速度比 Java 快得多,但只應用了很少的優化,例如常量折疊或刪除不必要的操作碼。 更復雜的優化對於腳本使用來說太昂貴了。 缺乏 JIT 支持和高級優化也意味着 Perl 通常比 Java 慢得多。

原則上,兩個 VM(JVM 和 perl)也可用於其他語言。 缺乏正式規范和以 Perl 為中心的實現意味着沒有其他語言將 perl 解釋器用作 VM,而許多語言可以編譯為 JVM 字節碼(示例包括 Python、Ruby、Perl6、Clojure 等語言)。

但是,JVM 針對服務器軟件或桌面應用程序等長時間運行的程序進行了優化。 這使得執行代價高昂的優化成為一種可行的權衡。 OTOH Perl 不僅用於大型程序,還用於啟動成本很重要的小型工具。 因此,簡單的 Perl 腳本可能只需要 2 MB 的內存,並且可以比 JVM 單獨啟動所需的速度更快。 雖然 JVM用於編寫腳本,但啟動成本和極端內存使用量通常使其缺乏吸引力。

術語說明:腳本是在不手動編譯的情況下執行程序。 這與解釋與編譯無關。 在 Unix 中, shebang可用於指定腳本的解釋器。

首先要注意的是,“編譯過程”不是各自語言所固有的。 相反,它們是相應語言的特定實現的方面。 (即使是 Java 字節碼、JVM 和相關的東西也是實現細節……並不是所有 Java 語言的實現都通用。)

編譯為字節碼后的“接下來會發生什么”是……依賴於實現。

  • 對於 Java,字節碼通常會被解釋一點(以收集一些統計信息),然后編譯為本機代碼。 但不總是; 例如查找java -int命令選項。 從技術上講,甚至不需要在圖片的任何地方都有字節碼。 (雖然使用商標“Java”存在法律問題......)

  • 對於 Perl,我的理解是字節碼通常只是被解釋。 但其他問題是 Perl 編譯器可以生成其他形式的代碼,並且 Perl 可以直接解釋 Perl 編譯器前端生成的“內部形式”。

所以回答你的問題:

Java 和 Perl 的編譯過程有何不同?

看上面。 在這兩種情況下,它都比您描述的要復雜。

兩者都產生一個字節碼......

同樣,不一定正確。

……但是在那之后會發生什么? perl 中的解釋和 java 中從目標代碼到機器代碼的轉換是否完全不同?

由於各自“虛擬機”的性質,“字節碼”指令集必然會有所不同。 JVM 本質上是一種靜態類型的東西,其中每個變量和表達式的形式類型都是已知的……可以是原始類型或某種對象類型。 相比之下,由於 Perl 語言的性質,Perl VM 需要(更多)動態類型化。

如果是這樣,那么為什么 Java 不能成為腳本語言?

很明顯,“如果是這樣”部分不滿足......存在顯着差異。

但是(IMO)Java 不是一個好的腳本語言有更充分的理由:

  • Java相對冗長
  • Java 堅持聲明類型和變量
  • Java本質上是靜態類型檢查的
  • Java 對函數式編程(例如一等和高階函數)的支持傳統上很差(盡管這正在改進......)
  • Java 擴展語言核心的能力有限(就像典型的腳本語言一樣)
  • (典型)JVM 的啟動時間比常規腳本語言要長得多。

這些因素結合在一起使 Java 成為編寫腳本的糟糕選擇1, 2 但另一方面,它們使 Java 成為需要更高性能和提高靜態編譯時類型可靠性的情況的不錯選擇。

(從某種意義上說,字節碼的使用和編譯過程的性質對於腳本與非腳本而言在很大程度上無關緊要......前提是編譯不太慢......在錯誤的時間。)


1 - Java 9 版本引入了“jshell”命令,它允許您以交互方式運行 Java。 不幸的是,它並不真正適合腳本編寫,因為“jshell”腳本無法訪問命令行參數。

2 - Java 11 版本允許您使用如下命令編譯和運行單個 Java 源文件: java SomeCommand.java 這仍然存在 JVM 啟動緩慢的問題,以及字節碼編譯步驟源的額外開銷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM