JVM 字節碼是如何存儲信息的?

JVM 字節碼是 Java 虛擬機 (JVM) 執行的指令集,它是一種與平臺無關的二進制格式,在任何支持 JVM 的平臺上都可運行的Java 程序。 字節碼存儲信息的方式,主要通過以下幾個關鍵組成部分和機制來實現:

1. 指令 (Opcodes) 和 操作數 (Operands):

  • 指令 (Opcodes): 字節碼的核心是指令集,每條指令都是一個單字節 (byte) 的數字編碼,稱為 操作碼 (opcode)。 操作碼定義了 JVM 需要執行的具體操作,例如:
    • 算術運算: iadd (整數加法), isub (整數減法), fmul (浮點數乘法) 等。
    • 數據加載和存儲: iload (加載整數到操作數棧), istore (將整數從操作數棧存儲到局部變量表), getfield (獲取對象字段值) 等。
    • 類型轉換: i2f (整數轉浮點數), l2i (長整型轉整型) 等。
    • 方法調用: invokevirtual (調用虛方法), invokestatic (調用靜態方法), invokeinterface (調用接口方法) 等。
    • 控制流: goto (無條件跳轉), ifeq (如果等于 0 則跳轉), return (方法返回) 等。
  • 操作數 (Operands): 有些指令需要額外的操作數 (operands) 來指定指令執行所需的參數或數據。 操作數緊跟在操作碼之后,可以是:
    • 字節 (byte): 例如,用于表示局部變量表的索引、常量池的索引等。
    • 短整型 (short): 例如,用于表示分支指令的偏移量。
    • 整型 (int): 例如,用于表示常量池的索引 (在某些指令中)。
    • 常量池索引 (constant pool index): 指向常量池中特定項的索引,用于引用類名、方法名、字段名、字符串字面量、數值常量等。

案例:

// Java 源代碼
public class Example {public static int add(int a, int b) {return a + b;}
}// 對應的 JVM 字節碼 (簡化表示)
// 方法 add 的字節碼
0: iload_0        // 將局部變量 0 (a) 推入操作數棧
1: iload_1        // 將局部變量 1 (b) 推入操作數棧
2: iadd           // 執行整數加法,棧頂兩個值相加,結果推回棧頂
3: ireturn        // 從方法返回,返回棧頂的整數值

在這個例子中:

  • iload_0, iload_1, iadd, ireturn 都是操作碼 (指令)。
  • iload_0iload_1 的操作數是隱式的 (隱含了局部變量表的索引 0 和 1)。

2. 常量池 (Constant Pool):

  • 關鍵的數據結構: 常量池是 .class 文件中的一個表結構,也是字節碼存儲信息的核心組成部分。 它存儲了類、方法、字段、字符串字面量、數值常量等各種符號引用和字面量常量
  • 動態鏈接的基礎: 常量池為 JVM 的動態鏈接機制提供了基礎。 字節碼中的指令通常通過常量池索引來引用程序中的各種符號和常量,而不是直接使用內存地址。 這使得字節碼具有平臺無關性,因為具體的內存地址在運行時才由 JVM 決定。
  • 存儲類型: 常量池中的每一項 (constant pool entry) 都有一個 tag 標識其類型,常見的類型包括:
    • CONSTANT_Class_info: 類或接口的符號引用 (類名、接口名)。
    • CONSTANT_Fieldref_info: 字段的符號引用 (類名、字段名、字段描述符)。
    • CONSTANT_Methodref_info: 方法的符號引用 (類名、方法名、方法描述符)。
    • CONSTANT_InterfaceMethodref_info: 接口方法的符號引用。
    • CONSTANT_String_info: 字符串字面量。
    • CONSTANT_Integer_info, CONSTANT_Float_info, CONSTANT_Long_info, CONSTANT_Double_info: 數值常量 (整數、浮點數、長整型、雙精度浮點數)。
    • CONSTANT_NameAndType_info: 字段或方法名稱和描述符。
    • CONSTANT_Utf8_info: UTF-8 編碼的字符串 (用于存儲類名、方法名、字段名等字符串)。
    • … (還有其他類型)

例子 (常量池引用):

// Java 源代碼
public class Example {private String message = "Hello"; // 字符串字面量 "Hello"public void printMessage() {System.out.println(message); // 引用字段 message}
}// 對應的 JVM 字節碼 (簡化表示)
// ... (省略其他字節碼)
// getfield 指令,操作數是常量池索引 #2
4: getfield      #2  // Field Example.message:Ljava/lang/String;// 常量池 #2 項 (簡化表示)
#2 = Fieldref      #4.#5        // 字段引用#4 = Class         #6        // 類名引用#5 = NameAndType   #7:#8      // 名稱和類型引用#6 = Utf8          Example     // 類名字符串 "Example"#7 = Utf8          message     // 字段名字符串 "message"#8 = Utf8          Ljava/lang/String; // 字段類型描述符 "Ljava/lang/String;"

在這個例子中:

  • getfield #2 指令使用常量池索引 #2 來引用要訪問的字段 message
  • 常量池 #2 項是一個 Fieldref 結構,它又通過其他常量池索引引用了類名、字段名和字段描述符等信息。
  • 字符串字面量 "Hello" 也存儲在常量池中 (例如,通過 CONSTANT_String_infoCONSTANT_Utf8_info),并在需要時被引用。

3. 局部變量表 (Local Variable Table):

  • 存儲方法內的局部變量: 局部變量表是每個方法在運行時創建的棧幀 (stack frame) 的一部分。 它用于存儲方法內部的局部變量,包括:
    • 方法的參數 (arguments)。
    • 方法體內部定義的局部變量。
  • 數組結構: 局部變量表本質上是一個數組,每個數組元素可以存儲一個 Java 的基本數據類型值 (int, float, long, double, byte, short, char, boolean) 或對象引用 (reference)。
  • 索引訪問: 字節碼指令使用索引來訪問局部變量表中的變量,例如 iload_0 加載索引為 0 的局部變量,istore_1 將值存儲到索引為 1 的局部變量。

4. 操作數棧 (Operand Stack):

  • 運算和操作的工作區: 操作數棧是每個方法棧幀的另一個重要組成部分。 它是一個后進先出 (LIFO) 的棧,用于:
    • 存儲指令的操作數: 指令執行時,會從操作數棧中彈出操作數。
    • 存儲指令的運算結果: 指令執行完畢后,會將結果壓入操作數棧頂。
  • 指令的執行流程: JVM 的字節碼指令大多是基于棧的指令集。 指令通常會:
    1. 從局部變量表或常量池加載數據到操作數棧。
    2. 從操作數棧中彈出操作數進行運算。
    3. 將運算結果壓入操作數棧。
    4. 將操作數棧頂的值存儲到局部變量表或字段中,或者作為方法返回值返回。

5. 方法區 (Method Area) (元空間/永久代):

  • 存儲類元數據: 方法區 (在 JDK 8 及之后被元空間 Metaspace 取代,JDK 7 及之前為永久代 PermGen) 用于存儲類的信息,包括:
    • 類的結構信息: 例如,類的名稱、父類、實現的接口、字段信息、方法信息、訪問修飾符等。
    • 運行時常量池 (Runtime Constant Pool): 每個類都有一個運行時常量池,它是 .class 文件常量池在運行時的表示形式,用于支持動態鏈接。
    • 靜態變量: 類的靜態變量也存儲在方法區中。
    • JIT 編譯后的代碼: 即時編譯器 (JIT Compiler) 編譯后的本地機器碼通常也存儲在方法區中。

總結:

JVM 字節碼通過以下方式存儲信息:

  • 指令集 (Opcodes): 定義了 JVM 要執行的操作,每條指令都是一個單字節編碼。
  • 操作數 (Operands): 為指令提供參數或數據,可以是字節、短整型、整型或常量池索引。
  • 常量池 (Constant Pool): 存儲了類、方法、字段、字符串字面量、數值常量等符號引用和字面量常量,是動態鏈接的基礎。
  • 局部變量表 (Local Variable Table): 存儲方法內部的局部變量,包括參數和方法體內部定義的變量。
  • 操作數棧 (Operand Stack): 作為指令運算和操作的工作區,存儲指令的操作數和運算結果。
  • 方法區 (Method Area) / 元空間 (Metaspace): 存儲類的元數據信息,包括類結構、運行時常量池、靜態變量等。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/75602.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/75602.shtml
英文地址,請注明出處:http://en.pswp.cn/web/75602.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于51單片機語音實時采集系統

基于51單片機語音實時采集 (程序+原理圖+PCB+設計報告) 功能介紹 具體功能: 系統由STC89C52單片機ISD4004錄音芯片LM386功放模塊小喇叭LCD1602按鍵指示燈電源構成 1.可通過按鍵隨時選擇相應的錄音進行播…

關于 Java 預先編譯(AOT)技術的詳細說明,涵蓋 GraalVM 的配置、Spring Boot 3.x 的集成、使用示例及優缺點對比

以下是關于 Java 預先編譯(AOT)技術的詳細說明,涵蓋 GraalVM 的配置、Spring Boot 3.x 的集成、使用示例及優缺點對比: 1. 預先編譯(AOT)技術詳解 1.1 核心概念 AOT(Ahead-of-Time&#xff09…

【ROS2】行為樹:BehaviorTree

1、簡介 與狀態機不同,行為樹強調執行動作,而不是狀態之間的轉換。 行為樹是可組合的。可以重復使用簡單的行為來構建復雜的行為。 在游戲領域,行為樹已經比較流行了。主要用于維護游戲角色的各種動作和狀態。 ROS2的導航框架Navigation2中引入了行為樹來組織機器人的工作流…

Centos7.9 升級內核,安裝RTX5880驅動

系統鏡像下載 https://vault.centos.org/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2009.iso 系統安裝步驟省略 開始安裝顯卡驅動 遠程登錄查看內核 [root192 ~]# uname -a Linux 192.168.119.166 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x8…

多層感知機與全連接神經網絡關系解析

感知機(Perceptron)、多層感知機(MLP,Multilayer Perceptron)和全連接神經網絡(FCNN,Fully Connected Neural Network)是神經網絡發展過程中密切相關的概念,但它們有明確…

解析醫療器械三大文檔:DHF、DMR與DHR

醫療器械的 DHF、DMR 和 DHR 是質量管理體系(QMS)中的核心文件,貫穿產品全生命周期, 確保醫療器械的安全性、有效性和合規性。 一、三大文件的定義與法規依據 縮寫全稱法規依據(以 FDA 為例)核心目的DHF…

netty啟用websocket的壓縮機制

netty啟用websocket的壓縮機制 package com.aerotop.connector.websocket.base;import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.compression.JZlibDec…

可能存在特殊情況,比如控制臺顯示有延遲、緩沖問題等影響了顯示順序。

從控制臺輸出看,正常邏輯應是先執行 System.out.println(" 未處理異常演示 "); 輸出對應文本,再因 arr 為 null 訪問 length 觸發 NullPointerException 輸出異常信息。可能存在特殊情況,比如控制臺顯示有延遲、緩沖問題等影響…

第一節:React 基礎篇-React虛擬DOM原理及Diff算法優化策略

必考點:虛擬DOM樹對比(同級比較、Key的作用、組件類型判斷) 延伸:React 18中并發更新對Diff算法的影響 React虛擬DOM原理及Diff算法優化策略 虛擬DOM核心原理 概念: ? 虛擬DOM(Virtual DOM)…

Java spring mybatis面試題(200道),八股文

Java面試題 通過網盤分享的文件:面試題等2個文件 鏈接: https://pan.baidu.com/s/1Xw0PzkfAmL8uesYBvrW2-A?pwdpebt 提取碼: pebt mybatis相關 1、 什么是Mybatis? … 2 2、 Mybaits 的優點: … 2 3、 MyBatis 框架的缺點: ……

windows使用Python調用7-Zip【按大小分組】壓縮文件夾中所有文件

使用Python調用7-Zip【按大小分組】壓縮文件夾中所有文件 問題描述:方法前提條件任務完整代碼示例代碼如何工作? 問題描述: 我現在想把文件夾下的所有內容上傳到網盤,但是這個文件夾下的素材內容很多,使用分卷壓縮的話…

《Python星球日記》第26天:Matplotlib 可視化

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder😊) 訂閱專欄:《Python星球日記》 目錄 一、Matplotlib 簡介1. 什么是 Matplo…

第1章 對大型語言模型的介紹

人類正處在一個關鍵轉折點。自2012年起,基于深度神經網絡的人工智能系統研發進入快速通道,將這一技術推向了新高度:至2019年底,首個能夠撰寫與人類文章真假難辨的軟件系統問世,這個名為GPT-2(生成型預訓練變…

dcsdsds

我將為您在頁面頂部添加歡迎內容&#xff0c;同時保持整體風格的一致性。以下是修改后的代碼&#xff0c;主要修改了模板部分和對應的樣式&#xff1a; vue 復制 <template><div class"main-wrapper"><!-- 新增歡迎部分 --><div class"…

學習MySQL的第八天

海到無邊天作岸 山登絕頂我為峰 一、數據庫的創建、修改與刪除 1.1 引言 在經過前面七天對于MySQL基本知識的學習之后&#xff0c;現在我們從基本的語句命令開始進入綜合性的語句的編寫來實現特定的需求&#xff0c;從這里開始需要我們有一個宏觀的思想&…

Linux-內核驅動-中斷-key

DEV_NAME&#xff1a;設備名稱。 wg&#xff1a;等待隊列頭&#xff0c;用于同步。 condition&#xff1a;條件變量&#xff0c;用于等待和喚醒。 中斷處理函數 irq_handler&#xff1a;處理中斷請求&#xff0c;設置條件變量并喚醒等待隊列中的進程。 文件操作函數 open…

asm匯編源代碼之按鍵處理相關函數

提供5個子程序: 1. 發送按鍵 sendkey 2. 檢測是否有按鍵 testkey 3. 讀取按鍵 getkey 4. 判斷鍵盤緩沖區是否為空 bufempty 5. 判斷鍵盤緩沖區是否已滿 buffull 具體功能及參數描述如下 sendkey proc  far ; axcharcode testkey proc  far ; out: ;   zf1 buff empt…

Java Collections 類中常用方法使用

一、Collections類 java.util.Collections 類是 Java 集合框架中的一個工具類&#xff0c;提供了一系列靜態方法來操作和處理各種類型的集合。這些方法簡化了對集合進行排序、查找、同步控制、創建只讀集合等常見操作的過程。 二、常用方法 方法類別??方法簽名??功能??需…

Linux網絡編程——數據鏈路層詳解,以太網、MAC地址、MTU、ARP、DNS、NAT、代理服務器......

目錄 一、前言 二、以太網 二、以太網幀格式 三、 MAC地址 四、MTU 1、數據鏈路層的數據分片 2、MTU對UDP協議的影響 3、MTU對TCP協議的影響 五、ARP協議 1、什么是ARP 2、ARP的作用 3、ARP協議的工作流程 4、ARP緩存表 5、ARP請求報文 6、中間人 六、DNS&…

輕量級開源文件共享系統PicoShare本地部署并實現公網環境文件共享

&#xfeff;## 前言 本篇文章介紹&#xff0c;如何在 Linux 系統本地部署輕量級文件共享系統 PicoShare&#xff0c;并結合 Cpolar 內網穿透實現公網環境遠程傳輸文件至本地局域網內文件共享系統。 PicoShare 是一個由 Go 開發的輕量級開源共享文件系統&#xff0c;它沒有文…