成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

騰訊三面:什么是 JVM 字節(jié)碼?它是如何工作的?

開發(fā)
本文,我們分析了什么是JVM?字節(jié)碼,如何查看JVM?字節(jié)碼以及JVM如何執(zhí)行字節(jié)碼。

作為 Java程序員都知道 Java是跨平臺的語言,編譯一次到處運行,這得益于 JVM字節(jié)碼,這篇文章,我們將一起分析什么是JVM字節(jié)碼?如何查看 JVM字節(jié)碼?JVM字節(jié)碼是如何工作的?

什么 JVM 字節(jié)碼?

Java 源代碼經(jīng)過編譯器編譯后,就會生成 JVM 字節(jié)碼,它是一種基于棧的低級、中立于平臺的指令架構(gòu),每個字節(jié)碼指令都會在 JVM 上執(zhí)行一系列的操作,如加載、存儲、運算、跳轉(zhuǎn)等。它使用基于操作數(shù)棧和局部變量表的執(zhí)行模型。

JVM 字節(jié)碼具有以下特點:

  • 獨立于具體的硬件和操作系統(tǒng),不同平臺上的 JVM 可以解釋和執(zhí)行相同的字節(jié)碼文件。
  • 相對于機器碼和源代碼,JVM 字節(jié)碼是一種更高級別的抽象,并且比機器碼更容易閱讀和編寫。
  • JVM 字節(jié)碼通過運行時的即時編譯器或解釋器執(zhí)行。

因此,只要在不同平臺上安裝相應的 JVM,就能在這些平臺上運行相同的字節(jié)碼,這種特性為 Java 程序提供了很高的可移植性和兼容性。值得注意的是,其他編程語言也可以編譯成 JVM 字節(jié)碼,利用 JVM 的優(yōu)勢。這些編程語言叫做基于 JVM 的語言,例如 Kotlin、Groovy 等。

如何查看 JVM 字節(jié)碼?

通過 javap -c ClassName指令就可以查看 JVM字節(jié)碼,為了更好的說明,下面通過一個簡單的 Java程序和對應的 JVM字節(jié)碼示例來進行演示:

1.示例代碼

如下代碼,在控制臺輸出“Hello, World”:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

使用 javac 命令編譯上述 Java 源代碼后會生成一個 HelloWorld.class 文件,然后使用javap -c HelloWorld命令查看字節(jié)碼,內(nèi)容如下:

Compiled from "HelloWorld.java"
public class HelloWorld {
  public HelloWorld();
    Code:
       0: aload_0
       1: invokespecial #1      // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2     // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3     // String Hello, World!
       5: invokevirtual #4     // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

2.字節(jié)碼解釋

(1) 構(gòu)造方法 HelloWorld()

  • aload_0: 加載局部變量表中第一個變量(即this引用)。
  • invokespecial #1: 調(diào)用父類(java/lang/Object)的構(gòu)造方法。
  • return: 從構(gòu)造方法返回。

(2) main方法

  • getstatic #2: 獲取靜態(tài)字段java/lang/System.out,它是一個 PrintStream 對象。
  • ldc #3: 將常量池中索引為3的項(即字符串"Hello, World!")加載到操作數(shù)棧。
  • invokevirtual #4: 調(diào)用 PrintStream 的 println 方法,參數(shù)是棧頂?shù)淖址?/li>
  • return: 從main方法返回。

(3) 關(guān)鍵字節(jié)碼指令解析

  • aload_0: 加載局部變量表中索引為 0的引用類型變量到操作數(shù)棧。
  • invokespecial: 調(diào)用實例初始化方法和私有方法。
  • getstatic: 獲取靜態(tài)字段的值并將其壓入操作數(shù)棧。
  • ldc: 將常量池中的常量加載到操作數(shù)棧。
  • invokevirtual: 調(diào)用對象的實例方法,方法的選擇是基于對象的運行時類型。

通過這個示例,我們可以看到 Java源代碼被編譯成 JVM 字節(jié)碼后是什么樣子。

JVM字節(jié)碼指令集

通過上述查看 JVM字節(jié)碼的示例,我們可以看到很多 JVM內(nèi)部的指令,比如加載、存儲、運算、跳轉(zhuǎn)等。JVM字節(jié)碼指令集(Bytecode Instruction Set)是 JVM用來執(zhí)行 Java 程序的指令集合,每條字節(jié)碼指令由一個字節(jié)的操作碼(opcode)和可選的操作數(shù)組成。

以下是 JVM 字節(jié)碼指令集的一些主要類別和具體指令:

1.加載和存儲指令

加載和存儲指令,全稱 Load and Store Instructions,包含以下幾個指令:

  • aload: 從局部變量表加載引用類型變量到操作數(shù)棧。
  • astore: 將操作數(shù)棧頂?shù)囊妙愋妥兞看鎯Φ骄植孔兞勘怼?/li>
  • iload: 從局部變量表加載整數(shù)類型變量到操作數(shù)棧。
  • istore: 將操作數(shù)棧頂?shù)恼麛?shù)類型變量存儲到局部變量表。
  • dload, fload, lload: 加載雙精度浮點數(shù)、單精度浮點數(shù)和長整數(shù)類型變量。
  • dstore, fstore, lstore: 存儲雙精度浮點數(shù)、單精度浮點數(shù)和長整數(shù)類型變量。

2.算術(shù)運算指令

算術(shù)運算指令,全稱 Arithmetic Instructions,包含以下幾個指令:

  • iadd: 對棧頂?shù)膬蓚€整數(shù)進行加法運算。
  • isub: 對棧頂?shù)膬蓚€整數(shù)進行減法運算。
  • imul: 對棧頂?shù)膬蓚€整數(shù)進行乘法運算。
  • idiv: 對棧頂?shù)膬蓚€整數(shù)進行除法運算。
  • iinc: 對局部變量表中的整數(shù)變量進行自增。
  • dadd, fadd, ladd: 加法運算(雙精度浮點數(shù)、單精度浮點數(shù)、長整數(shù))。
  • dsub, fsub, lsub: 減法運算(雙精度浮點數(shù)、單精度浮點數(shù)、長整數(shù))。

3.類型轉(zhuǎn)換指令

類型轉(zhuǎn)換指令,全稱 Type Conversion Instructions,包含以下幾個指令:

  • i2d: 整數(shù)轉(zhuǎn)雙精度浮點數(shù)。
  • i2f: 整數(shù)轉(zhuǎn)單精度浮點數(shù)。
  • i2l: 整數(shù)轉(zhuǎn)長整數(shù)。
  • d2i, f2i, l2i: 轉(zhuǎn)換為整數(shù)。

4.對象操作指令

對象操作指令,全稱 Object Manipulation Instructions,包含以下幾個指令:

  • new: 創(chuàng)建一個新的對象實例。
  • newarray: 創(chuàng)建一個新的數(shù)組。
  • anewarray: 創(chuàng)建一個新的引用類型數(shù)組。
  • checkcast: 檢查對象是否為某一類型的實例。
  • instanceof: 判斷對象是否是某一類型的實例。

5.方法調(diào)用和返回指令

方法調(diào)用和返回指令,全稱 Method Invocation and Return Instructions,包含以下幾個指令:

  • invokestatic: 調(diào)用靜態(tài)方法。
  • invokevirtual: 調(diào)用實例方法,根據(jù)對象的實際類型進行分派。
  • invokespecial: 調(diào)用實例初始化方法、私有方法和父類方法。
  • invokeinterface: 調(diào)用接口方法。
  • return: 從方法返回(無返回值)。
  • ireturn, dreturn, freturn, lreturn, areturn: 從方法返回(返回值為整數(shù)、雙精度浮點數(shù)、單精度浮點數(shù)、長整數(shù)、引用類型)。

6.控制流指令

控制流指令,全稱 Control Flow Instructions,包含以下幾個指令:

  • goto: 無條件跳轉(zhuǎn)。
  • ifeq: 如果棧頂整數(shù)為0,則跳轉(zhuǎn)。
  • ifne: 如果棧頂整數(shù)不為0,則跳轉(zhuǎn)。
  • iflt, ifge, ifgt, ifle: 比較棧頂整數(shù),并根據(jù)結(jié)果跳轉(zhuǎn)。
  • tableswitch: 用于switch語句的多路分支跳轉(zhuǎn)。
  • lookupswitch: 用于switch語句的查找表跳轉(zhuǎn)。

7.異常處理指令

異常處理指令,全稱 Exception Handling Instructions,包含以下幾個指令:

  • athrow: 拋出異常或錯誤。
  • try-catch塊:通過異常表實現(xiàn),不是具體的字節(jié)碼指令。

8.同步指令

同步指令,全稱 Synchronization Instructions,包含以下幾個指令:

  • monitorenter: 獲取對象的監(jiān)視器鎖。
  • monitorexit: 釋放對象的監(jiān)視器鎖。

9.棧操作指令

棧操作指令,全稱 Stack Operations Instructions,包含以下幾個指令:

  • pop: 彈出棧頂?shù)囊粋€元素。
  • dup: 復制棧頂?shù)囊粋€元素。
  • swap: 交換棧頂?shù)膬蓚€元素。

JVM 如何執(zhí)行字節(jié)碼?

JVM 字節(jié)碼的執(zhí)行過程主要依賴于 Java 虛擬機的解釋器和即時編譯器(Just-In-Time Compiler,簡稱JIT)。JVM會將字節(jié)碼讀取到內(nèi)存中,并逐條解釋執(zhí)行,或者將熱點代碼編譯為機器碼來提高執(zhí)行效率。

為了更好地說明 JVM 字節(jié)碼的執(zhí)行過程,我們還是通過一個具體的示例來進行說明。

1.示例代碼

這里以 a + b 求和為例,代碼如下:

public class Sum {
    public static int add(int a, int b) {
        return a + b;
    }
}

使用 javap -c Sum 命令獲取字節(jié)碼,具體信息如下:

Compiled from "Sum.java"
public class Sum {
  public Sum();
    Code:
       0: aload_0
       1: invokespecial #1     // Method java/lang/Object."<init>":()V
       4: return

  public static int add(int, int);
    Code:
       0: iload_0
       1: iload_1
       2: iadd
       3: ireturn
}

2.字節(jié)碼解釋

(1) 構(gòu)造方法 Sum()

  • aload_0: 加載局部變量表中第一個變量(即this引用)。
  • invokespecial #1: 調(diào)用父類(java/lang/Object)的構(gòu)造方法。
  • return: 從構(gòu)造方法返回。

(2) add()方法

  • iload_0: 加載局部變量表中索引為0的整數(shù)(即參數(shù)a)到操作數(shù)棧。
  • iload_1: 加載局部變量表中索引為1的整數(shù)(即參數(shù)b)到操作數(shù)棧。
  • iadd: 彈出操作數(shù)棧頂?shù)膬蓚€整數(shù),進行加法運算,并將結(jié)果壓入操作數(shù)棧。
  • ireturn: 從方法返回,并將操作數(shù)棧頂?shù)恼麛?shù)作為返回值。

3.執(zhí)行過程

假設(shè)我們在另一個類中調(diào)用Sum.add(2, 3),執(zhí)行過程如下:

  • JVM將參數(shù) 2和 3壓入局部變量表,iload_0指令將參數(shù) 2加載到操作數(shù)棧。
  • iload_1指令將參數(shù) 3加載到操作數(shù)棧。
  • iadd指令彈出操作數(shù)棧頂?shù)膬蓚€值(2和3),進行加法運算,將結(jié)果5壓入操作數(shù)棧。
  • ireturn指令將操作數(shù)棧頂?shù)闹担?)作為返回值返回給調(diào)用者。

總結(jié)

本文,我們分析了什么是JVM字節(jié)碼,如何查看JVM字節(jié)碼以及JVM如何執(zhí)行字節(jié)碼,掌握這些底層不但可以幫助我們更好的理解,為什么 Java可以編譯一次,到處運行,還可以幫助我們更好的了解 Java的運行機制以及理解 Java的編程精髓。

責任編輯:趙寧寧 來源: 猿java
相關(guān)推薦

2024-09-29 09:50:05

2024-08-19 00:25:00

2020-09-11 08:41:50

域名系統(tǒng)DNS網(wǎng)絡(luò)

2024-09-03 10:15:21

2024-09-27 16:33:44

2023-07-03 14:36:07

物聯(lián)網(wǎng)IoT

2025-03-28 10:47:05

開發(fā)注解Java

2021-12-08 09:53:50

騰訊QQ號碼重復

2022-11-22 11:30:53

2024-11-15 16:15:59

2021-08-27 09:00:00

CDC數(shù)據(jù)庫技術(shù)

2025-03-07 08:40:00

WAL數(shù)據(jù)庫分布式系統(tǒng)

2023-07-26 13:29:43

高性能短鏈系統(tǒng)

2022-01-17 14:24:09

共享字節(jié)面試

2020-04-21 12:09:47

JVM消化字節(jié)碼

2023-10-07 08:41:42

JavaJVM

2024-04-08 14:29:45

AI工廠數(shù)據(jù)中心

2020-10-13 12:29:38

Linux包管理器

2024-12-26 17:04:47

2024-06-03 14:03:35

點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 亚洲视频免费观看 | 欧美一区二区三区在线观看 | av黄色在线观看 | 亚洲一区二区三区欧美 | 国产免费一区二区 | 免费中文字幕 | 中文字幕视频在线 | 亚洲国产一区在线 | 一区在线视频 | 国产精品极品美女在线观看免费 | av在线一区二区三区 | 久久精品国产一区 | 欧美日韩国产一区二区三区 | 免费99精品国产自在在线 | 天天草天天操 | 免费黄色在线观看 | 国产精品一区二区在线 | 久婷婷 | 中文字幕一二三区 | 一区视频在线免费观看 | 狠狠操av| 久久中文免费视频 | www国产亚洲精品 | 91九色porny首页最多播放 | 成人国产网站 | 亚洲中午字幕 | av免费观看在线 | 久久激情五月丁香伊人 | 黄色片网此 | 精品欧美黑人一区二区三区 | 二区高清| 欧美一区二区在线视频 | 性高湖久久久久久久久aaaaa | 亚洲精品黄色 | 国产美女一区二区三区 | 中文一级片 | 综合精品久久久 | 日本免费小视频 | 91精品国产91久久久久久吃药 | 久久国产视频播放 | 国产精品3区 |