關於Java平臺無關性你該知道這些

一、什麼是平臺無關性

  • Java語言是一款跨平臺的語言,不管是在windows還是在Linux又或者是mac os,它都可以支持並在上邊運行,秉持着一次編譯,隨處運行(Compile Once,Run Anywhere)的原則。
  • Java程序可以編譯成.class二進制文件,通過ClassLoader裝載進系統,然後由各個平臺的JVM(Java虛擬機)解析進行連接、初始化等操作,從而達到不改變程序代碼實現各個平臺運行的目的,這也是Java迅速風靡、建立龐大生態圈的一個重要原因。

二、平臺無關性的實現

具體流程大概就是

  1. xxx.java文件進行編譯生成xxx.class(JVM所能理解的字節碼文件文件),這也是跨平臺的基礎
  2. 很多平臺都有匹配JVM虛擬機,CLassLoader將.class文件裝載進JVM
  3. JVM對.class文件進行解析,轉換成特定平臺的執行指令
    在這裏插入圖片描述

我們舉個小例子

package com.mtli.javabasic;

/**
 * @Description:平臺無關性測試
 * @Author: Mt.Li
 * @Create: 2020-04-25 08:55
 */
public class ByteCodeSample {
    public static void main(String[] args) {
        int i= 1,j=5;
        // 故意寫錯,看javac信息
        i++;
        ++j;
        System.out.println(i);
        System.out.println(j);
    }
}

在idea的Terminal或者系統cmd中對java程序進行編譯(我這裏用的是idea)

Terminal用bash/內嵌cmd運行cd java_basic/src/com/mtli/javabasic,然後javac ByteCodeSample.java,我們來看看結果
在這裏插入圖片描述
編譯不通過,我們對源碼進行修改:

package com.mtli.javabasic;

/**
 * @Description:
 * @Author: Mt.Li
 * @Create: 2020-04-25 08:55
 */
public class ByteCodeSample {
    public static void main(String[] args) {
        int i= 1,j=5;
        // 故意報錯,看javac信息
        //i++++;
        i++;
        ++j;
        System.out.println(i);
        System.out.println(j);
    }
}

再次編譯,發現.java下邊生成了.class文件
在這裏插入圖片描述
然後在javabasic目錄下執行該class文件:java com.mtli.javabasic.ByteCodeSample,結果如下:
在這裏插入圖片描述
有的人會問爲什麼.class文件點進去能看到源碼呢?不應該是字節碼文件嗎?那是因爲我們查看的時候,idea自動爲我們進行反編譯了,想看字節碼的可以去資源目錄裏面找到該文件,打開後:
在這裏插入圖片描述
爲了更方便我們剖析,我們使用javap -c com/mtli/javabasic/ByteCodeSample進行反彙編:

Compiled from "ByteCodeSample.java" // 由ByteCodeSample.java編譯而來
public class com.mtli.javabasic.ByteCodeSample {
  public com.mtli.javabasic.ByteCodeSample(); // 無參構造函數,下面的code就是無參構造執行的內容
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Obj // 執行super
ect."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1 // 常量1放到棧頂
       1: istore_1 // 將棧頂的值放到局部變量i中(出棧)
       2: iconst_5 // 將5放到棧頂
       3: istore_2 // 將棧頂的值放到j中
       4: iinc          1, 1 // 變量1+1
       7: iinc          2, 1 // 變量2+1
      10: getstatic     #2   // 獲取靜態域               // Field java/lang/System.out:Ljava/io/PrintStream;
      13: iload_1  // 將變量1放到棧頂(入棧)
      14: invokevirtual #3   // 打印               // Method java/io/PrintStream.println:(I)V
      17: getstatic     #2   // 獲取靜態域               // Field java/lang/System.out:Ljava/io/PrintStream;
      20: iload_2
      21: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      24: return
}

回到正題,我們接下來將.class文件放到服務器上(linux)上面執行(linux得預先安裝linux版本的jdk1.8x,我的是win下1.8x下編譯的,服務器也要裝1.8x,只要是1.8就行),首先我們需要創建好包,也就是創建對應的文件夾了
在這裏插入圖片描述

我比較懶,直接將src放上去了,然後回到命令行,cd /src——>java com.mtli.javabasic.ByteCodeSample,可以看到
在這裏插入圖片描述
我們源碼是沒有改動的,通過linux平臺匹配的JVM就可以直接運行,可以說Java語言移植性是很不錯的。

三、爲什麼JVM不直接將源碼解析成機器碼去執行

講到這裏,可能有的朋友會有這個疑惑,編譯過程是比較繁瑣的,需要進行各種檢查,如果把這個事兒都交給JVM幹,別個不得累死,直接把它看得懂的文件給它不更好嗎。再說了,統一成字節碼文件給JVM也有利於其他語言的兄弟移植啊。總結成兩點:

  • 避免繁瑣的準備工作即每次執行都要各種檢查
  • 兼容性:也可以將別的語言解析成字節碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章