JVM規范之棧幀

JVM規范之棧幀

  • 前言
  • 正文
    • 概述
    • 局部變量表
    • 操作數棧
    • 動態鏈接
  • 總結
  • 參考鏈接

前言

上一篇文章了解了JVM規范中的運行時數據區:
JVM規范之運行時數據區域
其中,棧是JVM線程私有的內存區,棧中存儲的單位是幀(frames),本篇文章通過JVM8規范學習棧幀在JVM運行時的作用。

正文

概述

每個棧幀的內存分配自線程私有的 Java 虛擬機棧(JVM Stack),線程調用方法時壓棧,方法結束時出棧銷毀。

幀的作用是保存方法調用的局部變量、中間結果、執行動態鏈接、方法返回信息、發送異常。一個幀通常包含局部變量表、操作數棧、運行時常量池引用,這些組件都是幀私有的。

創建/銷毀時機:
當方法被調用的時候,棧幀也會被創建,當方法調用完成時,棧幀被銷毀,方法調用的含義包含兩種:

  • 方法正常調用結束,方法運行期間,JVM 沒有拋出或者沒有顯式地使用throw拋出未被捕獲的異常;
  • 方法非正常結束(如拋出未捕獲異常)時,棧幀會提前銷毀,JVM 通過異常棧軌跡(StackTrace)記錄各層棧幀信息,用于調試;

內存分配策略:
局部變量表和操作數棧的大小在編譯時確定,運行時常量池引用的大小本質是一個指針,具體大小可能取決于具體的 JVM 實現,因此棧幀的大小由編譯時確定的局部變量表和操作數棧的理論最大值,結合 JVM 實現的內存布局(如 Slot 字節數、對齊策略)決定。

局部變量表

  • 每個棧幀都有自己的局部變量表,局部變量表的大小是在編譯時確定的,因此在運行時可以一次性從棧上進行分配;
  • 局部變量表通過索引的方式訪問,每個索引的位置可以理解一個變量槽(slot),每個槽可以存儲boolean, byte, char, short, int, float, reference, returnAddress類型的值,一對slot可以存儲longdouble類型的值;
  • longdouble占用兩個連續的變量槽,比如一個long占用了索引nn+1兩個變量槽的位置,但是n+1位置是不可讀取的,可以被寫入,這會導致變量槽n位置的數據失效;
  • JVM 規范沒有限制局部變量表中的數據必須進行字節對齊;
  • 在調用方法時,JVM 使用局部變量表傳遞參數,從索引位置 0 開始,如果調用的方法是一個實例方法,索引 0 位置總是被傳入this;對于靜態方法,局部變量表索引 0 不存儲this,直接從索引 0 開始存儲方法參數。

操作數棧

  • 每個棧幀都包含一個操作數棧,棧的最大深度是編譯時確定的,當棧幀被創建時,操作數棧是空的;
  • 操作數棧符合棧的特點,LIFO,操作數棧中每個entry可以容納一個JVM數據類型,包含longdouble類型;
  • 操作數棧中存儲的數據類型和操作指令必須嚴格匹配,JVM會在進行class文件驗證時,檢查操作數棧的使用是否符合規范;
  • 操作數棧中,long/double作為 64 位值,占用 2 個深度單位,其他類型占 1 個;

動態鏈接

什么是動態鏈接?
在 JVM 中,動態鏈接類加載機制運行時環境的關鍵環節,主要用于將符號引用(Symbolic References)解析為直接引用(Direct References),是實現多態的核心技術。

  • 每個棧幀都包含一個運行時常量池的引用,用于實現方法調用的動態鏈接過程;
  • 字節碼文件中描述了方法調用的符號表引用,但是并沒有實際代碼的內存地址,因此動態鏈接是將符號表引用翻譯為直接引用;
  • 動態鏈接是實現多態的核心機制,通過運行時常量池解析虛方法的符號引用,在運行時根據對象實際類型(如instanceof)找到具體方法的直接引用。例如,子類重寫父類方法時,編譯期符號引用指向父類,運行時動態鏈接到子類實現。

補充:

  • 在編譯階段,字節碼文件中僅保存符號表引用,不會涉及靜態鏈接或者動態鏈接的過程;
  • 靜態鏈接在類加載階段(解析階段)確定方法調用目標,將符號表引用轉化為直接引用,而動態鏈接指JVM在運行時才能確定調用目標的實例類型,在運行時將符號表引用轉化為直接引用。

動態鏈接代碼示例

public class Animal {public void sound() {System.out.println("Animal"); } // 虛方法
}
public class Dog extends Animal {@Overridepublic void sound() {System.out.println("Woof");} // 動態鏈接目標
}
// 調用時通過運行時常量池解析為Dog.sound()
Animal animal = new Dog();
animal.sound(); // invokevirtual指令觸發動態鏈接

總結

本篇文章根據JVM 8規范了解了棧幀的數據結構:

  • 棧幀是在JVM線程進行方法調用時創建,每調用一個方法就會創建一個棧幀,每當方法調用結束或者異常結束,棧幀會被出棧;
  • 每個棧幀通常包含局部變量表、操作數棧、運行時常量池引用,棧幀的內存占用大小僅取決于JVM的實現,其中,局部變量表類似一個數組,JVM線程通過索引的方式讀取局部變量表的內容;操作數棧用于保存中間結果和方法保存結果,要求操作數棧中的數據類型和指令必須匹配;運行時常量池引用是JVM實現動態鏈接的關鍵,當然也用來支持類字段引用和其它常量的訪問;

JVM 規范僅定義棧幀的邏輯結構(如局部變量表、操作數棧),具體實現(如 Slot 是否對齊、指針壓縮)由廠商決定。例如,HotSpot 中 Slot 通常為 32 位,long/double占 2 個 Slot,無需 64 位對齊。

參考鏈接

jvm8s

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

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

相關文章

SGMD辛幾何模態分解

SGMD辛幾何模態分解 運行包含頻譜圖相關系數圖 Matlab語言 算法近幾年剛提出,知網還沒幾個人用,你先用,你就是創新! 算法新穎小眾,用的人很少,包含分解圖、頻譜圖、相關系數圖,效果如圖所示&a…

計算機網絡總結(物理層,鏈路層)

目錄 第一章 概述 1.基本概念 2.- C/S模式,B/S模式,P2P模式 3.- LAN,WAN,MAN,PAN的劃分 4.電路交換與分組交換,數據報交換和虛電路交換 第二章 物理層 1.信號編碼:不歸零編碼,曼切斯特編碼 2.幾種復用技術的特…

臺系廠商SSD主控之爭:Phison對決SMI

近日,臺系SSD主控廠商Phison和Silicon Motion之間圍繞主控性能的爭論引發關注,焦點集中在Gen5 SSD的功耗和速度等關鍵指標上。 Phison的E28 Gen5 SSD控制器已推出一段時間,是市場上一些最快存儲設備的“心臟”。其主要競爭對手Silicon Motion…

醫學影像科研概述與研究倫理

關鍵要點 醫學影像科研通過開發和優化影像技術(如X射線、CT、MRI等)推動疾病診斷和治療進步。研究需遵循核心倫理原則:受益(為患者和社會帶來益處)、無害(避免傷害)、自主(尊重患者選擇權)和公正(公平對待參與者)。醫學影像科研的特殊倫理問題包括知情同意、隱私保護…

使用 kafka-console-consumer.sh 指定時間或偏移量消費

1、問題來源 在工作中需要觀察上游生產的數據順序和自己寫的任務處理數據的順序是否一致,嘗嘗需要將kafka中的指定時間或者偏移量開始的數據導出來分析,如果每次都導數據都是從頭開消費導全量,往往少則幾個G多則幾十G的數據,導出…

構建Harbor私有鏡像庫

軟硬件環境清單 環境搭建 部署Euler22.0系統,連接xshell: 關閉防火墻和selinux,設置主機名: systemctl stop firewalld systemctl disable firewalld vi /etc/selinux/config hostnamectl set-hostname harbor reboot 修改靜態…

分布式緩存:緩存設計中的 7 大經典問題_緩存失效、緩存穿透、緩存雪崩

文章目錄 緩存全景圖Pre緩存設計中的 7 大經典問題一、緩存失效1. 問題描述2. 原因分析3. 業務場景4. 解決方案 二、緩存穿透1. 問題描述2. 原因分析3. 業務場景4. 解決方案緩存空結果BloomFilter 過濾BloomFilter 原理簡述 三、緩存雪崩1. 問題描述2. 原因分析3. 業務場景4. 解…

Mysql差異備份與恢復

1.練習差異備份 差異備份:備份完全備份后,新產生的數據。 在192.168.88.50主機完成差異備份 步驟一:練習差異備份//周一完全備份 mysql> select * from test.one; --------------------- | name | age | sex | ------------------…

【Fargo】razor框架調用mediasoup的發送和接收能力

功能進行拆分,創建獨立的發送和接收線程,并實現跨線程的數據傳遞。創建一個簡化的主函數,展示如何使用這些新的接口線程隔離是通過包隊列實現的,實際上可以用webrtc的post 跨線程機制? 需求 主要有兩個需求:啟動接收線程接收數據的接口 啟動發送線程,但是數據來自于sim_…

C++——volatile

Cvolatile關鍵字 volatile是C中的一個關鍵字,用于修飾變量,表示該變量的值可能會在程序的控制之外被改變。它主要告訴編譯器不要對這個變量進行優化,確保每次訪問變量時都從實際存儲位置讀取最新值,而不是依賴寄存器中的緩存值。…

搭建自己的語音對話系統:開源 S2S 流水線深度解析與實戰

網羅開發 (小紅書、快手、視頻號同名) 大家好,我是 展菲,目前在上市企業從事人工智能項目研發管理工作,平時熱衷于分享各種編程領域的軟硬技能知識以及前沿技術,包括iOS、前端、Harmony OS、Java、Python等…

qt瀏覽文件支持慣性

#include <QApplication> #include <QListWidget> #include <QScroller> #include <QScrollerProperties>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 創建列表控件并添加示例項QListWidget listWidget;for (int i 0; i <…

路徑規劃算法BFS/Astar/HybridAstar簡單實現

借鑒本文所述代碼簡單實現一下BFS&#xff0c;Astar和HybridAstar路徑規劃算法&#xff0c;用于輔助理解算法原理。 代碼在這里&#xff0c;畫圖用到了matplotlibcpp庫&#xff0c;需要先裝一下&#xff0c;然后直接在文件目錄下執行如下代碼即可運行&#xff1a; mkdir build…

get_the_category() 和 get_the_terms() 的區別

get_the_category() 和 get_the_terms() 是WordPress中用于獲取文章分類的兩個函數&#xff0c;但它們之間存在一些關鍵差異&#xff1a; get_the_category() 特定于分類&#xff1a;get_the_category() 函數專門用于獲取文章的分類(category)。它返回一個包含所有分類對象的…

RocketMq的消息類型及代碼案例

RocketMQ 提供了多種消息類型&#xff0c;以滿足不同業務場景對 順序性、事務性、時效性 的要求。其核心設計思想是通過解耦 “消息傳遞模式” 與 “業務邏輯”&#xff0c;實現高性能、高可靠的分布式通信。 一、主要類型包括 普通消息&#xff08;基礎類型&#xff09;順序…

maxkey單點登錄系統

github地址 https://github.com/MaxKeyTop/MaxKey/blob/master/README_zh.md 1、官方鏡像 https://hub.docker.com/u/maxkeytop 2、MaxKey:Docker快速部署 參考地址&#xff1a; Docker部署 | MaxKey單點登錄認證系統 拉取docker腳本MaxKey: Dromara &#x1f5dd;?MaxK…

基于AI生成測試用例的處理過程

基于AI生成測試用例的處理過程是一個結合機器學習、自然語言處理&#xff08;NLP&#xff09;和領域知識的系統性流程。以下是其核心步驟和關鍵技術細節&#xff0c;以幫助理解如何利用AI自動化生成高效、覆蓋全面的測試用例。 1. 輸入分析與需求建模 目標 將用戶需求、系統文…

《Java vs Go vs C++ vs C:四門編程語言的深度對比》

引言?? 從底層硬件操作到云端分布式系統&#xff0c;Java、Go、C 和 C 四門語言各自占據不同生態位。本文從??設計哲學??、??語法范式??、??性能特性??、??應用場景??等維度進行對比&#xff0c;為開發者提供技術選型參考。 一、??設計哲學與歷史定位??…

無損提速黑科技:YOLOv8+OREPA卷積優化方案解析(原理推導/代碼實現/調參技巧三合一)

文章目錄 一、OREPA核心思想與創新突破1.1 傳統重參數化的局限性1.2 OREPA的核心創新二、OREPA實現原理與數學推導2.1 卷積核分解策略2.2 動態融合公式三、YOLOv8集成實戰(完整代碼實現)3.1 OREPA卷積模塊定義3.2 YOLOv8模型集成3.3 訓練與推理配置四、性能對比與實驗分析4.1…

RestTemplate 發送的字段第二個大寫字母變成小寫的問題探究

在使用RestTemplate 發送http 請求的時候&#xff0c;發現nDecisonVar 轉換成了ndecisonVar ,但是打印日志用fastjson 打印的沒有問題&#xff0c;換成jackson 打印就有問題。因為RestTemplate 默認使用的jackson 作為json 序列化方式&#xff0c;導致的問題&#xff0c;但是為…