目錄
- Java 的平臺無關性(一次編譯,到處運行)如何實作?
Java 的平臺無關性(一次編譯,到處運行)如何實作?
總所周知,通常把 Java 分為編譯時和運行時,
對于編譯時會使用到 javac 指令,將源代碼編譯生成位元組碼,并存盤到對應的 .class 檔案之中,舉一個例子:
首先先在 IDEA 中創建一個專案創建包后撰寫以下代碼以便進行后續的操作:
package cn.xilikeli.javabasic.bytecode;
/**
* <p>
* 示例代碼
* </p>
*
* @author 踏雪彡尋梅
* @version 1.0
* @date 2020/8/9 - 21:39
* @since JDK1.8
*/
public class ByteCodeSample {
public static void main(String[] args) {
int i = 1;
i++;
System.out.println(i);
}
}
撰寫好代碼之后,通過使用 javac 指令對該原始碼檔案進行編譯,如下圖所示:

從上圖中,可以看到這個類編譯之后,就產生了一個 .class 檔案,
對于 .class 檔案,其中保存著 .java 檔案翻譯成的二進制位元組碼,也就是說 Java 類檔案中的屬性、方法以及類中的常量資訊等都會分別存盤到 .class 檔案中,除此之外還會添加一個公有的靜態常量屬性 .class,這個屬性記錄了類的相關資訊,即型別資訊,是 Class 類的一個實體,
class 檔案存在的意義就是: 跨平臺,即它為跨平臺的基礎,各種不同平臺的虛擬機都統一使用這種相同的程式存盤格式,不同平臺的 JVM 決議相同的 .class 檔案在不同平臺上運行,
所以以上源檔案編譯之后生成 .class 檔案之后,就可以使用 java 指令讓 JVM 去決議對應的 class 檔案,將里面的位元組碼內容加載進記憶體,最終轉換成本作業系統能夠識別的機器碼去運行程式了,如下圖所示:

那么 class 檔案中到底放了什么東西呢,可以通過使用 javap 指令反編譯 .class 檔案查看其內容,javap 是 JDK 自帶的反匯編器,可以查看編譯期產生的位元組碼,我們可以通過比較位元組碼和源代碼,了解很多知識,例如可以了解編譯器內部作業的機制,如下圖所示:

上圖中顯示的這些指令,是真正加載 class 檔案去執行時用到的虛指令,通過這些指令可以了解到程式的具體細節,這里就不再闡述了,
對于這個 class 檔案,如果在其他平臺上直接使用 java 指令去執行也是可以的,這也體現出了跨平臺的特性,如下圖所示(下圖的環境為 Linux,上面示例的環境為 macOS):

了解了以上知識之后,就可以回到 Java 的平臺無關性(一次編譯,到處運行)如何實作 這個問題了,
通過上面的示例,對于這個問題就可以這樣解釋:
Java 原始碼首先被編譯成位元組碼,再由不同平臺上的 JVM 進行決議,編譯之后在不同的平臺上運行時不需要進行重新編譯,Java 虛擬機在執行位元組碼的時候,把位元組碼轉換成具體平臺上的機器指令進行執行,
對于上面的問題, 還可以衍生出這個問題: 為什么 JVM 不直接將原始碼決議成機器碼去執行呢?
對于這個問題,可以這樣看待,如果直接將原始碼決議成機器碼去執行,那么每次執行都需要各種語法之類的檢查,即檢查結果不會被保留下來,都要重新編譯重新分析,整體性能會受影響,做很多重復的作業,所以引入了中間位元組碼,能夠保證在編譯成位元組碼之后,多次執行程式不需要再經過重復的各種檢查校驗,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/30797.html
標籤:Java
上一篇:暢購商城(十一):訂單
