JVM相關:Java內存區域

Java 虛擬機(JVM)在執行 Java 程序的過程中會把它管理的內存劃分成若干個不同的數據區域。
Java運行時數據區域是指Java虛擬機(JVM)在執行Java程序時,為了管理內存而劃分的幾個不同作用域。這些區域各自承擔特定的任務,并且有著不同的生命周期。根據Java虛擬機規范,主要可以分為線程共享區域和線程私有區域兩大類:
在這里插入圖片描述

1.程序計數器

程序計數器主要有兩個作用:

  • 字節碼解釋器通過改變程序計數器來依次讀取指令,從而實現代碼的流程控制,如:順序執行、選擇、循環、異常處理。
  • 在多線程的情況下,程序計數器用于記錄當前線程執行的位置,從而當線程被切換回來的時候能夠知道該線程上次運行到哪兒了。

注意:程序計數器是唯一一個不會出現 OutOfMemoryError 的內存區域,它的生命周期隨著線程的創建而創建,隨著線程的結束而死亡。

2.Java 虛擬機棧(簡稱棧)

棧絕對算的上是 JVM 運行時數據區域的一個核心,除了一些 Native 方法調用是通過本地方法棧實現的(后面會提到),其他所有的 Java 方法調用都是通過棧來實現的

(方法調用-壓入對應棧幀,調用結束,彈出棧幀)
方法調用的數據需要通過棧進行傳遞,每一次方法調用都會有一個對應的棧幀被壓入棧中,每一個方法調用結束后,都會有一個棧幀被彈出。
棧由一個個棧幀組成,而每個棧幀中都擁有:局部變量表、操作數棧、動態鏈接、方法返回地址。和數據結構上的棧類似,兩者都是先進后出的數據結構,只支持出棧和入棧兩種操作。
棧幀隨著方法調用而創建,隨著方法結束而銷毀。無論方法正常完成還是異常完成都算作方法結束。

棧幀構成

在這里插入圖片描述
動態鏈接 主要服務一個方法需要調用其他方法的場景
當一個方法要調用其他方法,需要將常量池中指向方法的符號引用轉化為其在內存地址中的直接引用。
動態鏈接的作用就是為了將符號引用轉換為調用方法的直接引用,這個過程也被稱為 動態連接

當線程請求棧的深度超過當前 Java 虛擬機棧的最大深度的時候,就拋出 StackOverFlowError 錯誤
棧還可能會出現OutOfMemoryError錯誤,這是因為如果棧的內存大小可以動態擴展, 如果虛擬機在動態擴展棧時無法申請到足夠的內存空間,則拋出OutOfMemoryError異常
在這里插入圖片描述

3. 本地方法棧

虛擬機棧為虛擬機執行 Java 方法 (也就是字節碼)服務,而本地方法棧則為虛擬機使用到的 Native 方法服務

4. 堆

Java 虛擬機所管理的內存中最大的一塊,Java 堆是所有線程共享的一塊內存區域,在虛擬機啟動時創建。此內存區域的唯一目的就是存放對象實例,幾乎所有的對象實例以及數組都在這里分配內存。
Java 世界中“幾乎”所有的對象都在堆中分配
(從 JDK 1.7 開始已經默認開啟逃逸分析,如果某些方法中的對象引用沒有被返回或者未被外面使用(也就是未逃逸出去),那么對象可以直接在棧上分配內存)
Java 堆是垃圾收集器管理的主要區域,因此也被稱作 GC 堆(Garbage Collected Heap)

在 JDK 7 版本及 JDK 7 版本之前,堆內存被通常分為下面三部分:新生代內存(Young Generation)老生代(Old Generation)永久代(Permanent Generation)

JDK 8 版本之后 PermGen(永久代) 已被 Metaspace(元空間) 取代,元空間使用的是本地內存。

5. 方法區(一個邏輯概念,由metaspace實現方法區

方法區屬于是 JVM 運行時數據區域的一塊邏輯區域,是各個線程共享的內存區域。
方法區會存儲已被虛擬機加載的 類信息、字段信息、方法信息、常量、靜態變量、即時編譯器編譯后的代碼緩存等數據。

在這里插入圖片描述

為什么要將永久代 (PermGen) 替換為元空間 (MetaSpace) 呢?

1.整個永久代有一個 JVM 本身設置的固定大小上限,無法進行調整(也就是受到 JVM 內存的限制),而元空間使用的是本地內存,受本機可用內存的限制,雖然元空間仍舊可能溢出,但是比原來出現的幾率會更小。
2.元空間里面存放的是類的元數據,這樣加載多少類的元數據就不由 MaxPermSize 控制了, 而由系統的實際可用空間來控制,這樣能加載的類就更多了
3、在 JDK8,合并 HotSpot 和 JRockit 的代碼時, JRockit 從來沒有一個叫永久代的東西, 合并之后就沒有必要額外的設置這么一個永久代的地方了。
4、永久代會為 GC 帶來不必要的復雜度,并且回收效率偏低。

運行時常量池

Class 文件中除了有類的版本、字段、方法、接口等描述信息外,
還有用于存放編譯期生成的各種字面量(Literal)和符號引用(Symbolic Reference)的 常量池表(Constant Pool Table)

字面量(Literal)

字面量是源代碼中的固定值的表示法,即通過字面我們就能知道其值的含義。字面量包括整數、浮點數和字符串字面量。常見的符號引用包括類符號引用、字段符號引用、方法符號引用、接口方法符號。

運行時常量池是方法區的一部分,自然受到方法區內存的限制,當常量池無法再申請到內存時會拋出 OutOfMemoryError 錯誤

字符串常量池

為了提升性能和減少內存消耗針對字符串(String 類)專門開辟的一塊區域,主要目的是為了避免字符串的重復創建
JDK1.7 字符串常量池和靜態變量從永久代移動了 Java 堆中。

為什么要將字符串常量池移動到堆中?

主要是因為永久代(方法區實現)的 GC 回收效率太低,只有在整堆收集 (Full GC)的時候才會被執行 GC。Java 程序中通常會有大量的被創建的字符串等待回收,將字符串常量池放到堆中,能夠更高效及時地回收字符串內存。
在這里插入圖片描述

重點概念理清

運行時常量池、方法區、字符串常量池這些都是不隨虛擬機實現而改變的邏輯概念,是公共且抽象的,Metaspace、Heap 是與具體某種虛擬機實現相關的物理概念,是私有且具體的。

Java 堆是垃圾收集器管理的主要區域,因此也被稱作 GC 堆(Garbage Collected Heap)
在 JDK 7 版本及 JDK 7 版本之前,堆內存被通常分為下面三部分:新生代內存(Young Generation)老生代(Old Generation)永久代(Permanent Generation)
JDK 8 版本之后 PermGen(永久代) 已被 Metaspace(元空間) 取代,元空間使用的是本地內存。

直接內存
直接內存是一種特殊的內存緩沖區,并不在 Java 堆或方法區中分配的,而是通過 JNI 的方式在本地內存上分配的。
(JNI–java native interface
在這里插入圖片描述

虛擬機在 Java 堆中對象創建過程

Step1:類加載檢查

虛擬機遇到一條 new 指令時,首先將去檢查這個指令的參數是否能在常量池中定位到這個類的符號引用,并且檢查這個符號引用代表的類是否已被加載過、解析和初始化過。如果沒有,那必須先執行相應的類加載過程

Step2:分配內存。

對象所需的內存大小在類加載完成后便可確定,為對象分配空間的任務等同于把一塊確定大小的內存從 Java 堆中劃分出來。分配方式有 “指針碰撞” 和 “空閑列表” 兩種,選擇哪種分配方式由 Java 堆是否規整決定,而 Java 堆是否規整又由所采用的垃圾收集器是否帶有壓縮整理功能決定。
在這里插入圖片描述
在實際開發過程中,創建對象是很頻繁的事情,作為虛擬機來說,必須要保證線程是安全的,通常來講,虛擬機采用兩種方式來保證線程安全:
CAS+失敗重試: CAS(compare and swap) 是樂觀鎖的一種實現方式。所謂樂觀鎖就是,每次不加鎖而是假設沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。虛擬機采用 CAS 配上失敗重試的方式保證更新操作的原子性。
在這里插入圖片描述
TLAB: 為每一個線程預先在 Eden 區分配一塊兒內存,JVM 在給線程中的對象分配內存時,首先在 TLAB 分配,當對象大于 TLAB 中的剩余內存或 TLAB 的內存已用盡時,再采用上述的 CAS 進行內存分配

Step3:初始化零值

內存分配完成后,虛擬機需要將分配到的內存空間都初始化為零值(不包括對象頭),這一步操作保證了對象的實例字段在 Java 代碼中可以不賦初始值就直接使用,程序能訪問到這些字段的數據類型所對應的零值。

Step4:設置對象頭

虛擬機要對對象進行必要的設置,例如這個對象是哪個類的實例、如何才能找到類的元數據信息、對象的哈希碼、對象的 GC 分代年齡等信息。 這些信息存放在對象頭中。

Step5:執行 init 方法

從虛擬機的視角來看,一個新的對象已經產生了,但從 Java 程序的視角來看,對象創建才剛開始, 方法還沒有執行,所有的字段都還為零。所以一般來說,執行 new 指令之后會接著執行 方法,把對象按照程序員的意愿進行初始化,這樣一個真正可用的對象才算完全產生出來

對象的內存布局

虛擬機中,對象在內存中的布局可以分為 3 塊區域:對象頭(Header)、實例數據(Instance Data)和對齊填充(Padding)
在這里插入圖片描述

對象的訪問方式

建立對象就是為了使用對象,我們的 Java 程序通過棧上的 reference 數據來操作堆上的具體對象。對象的訪問方式由虛擬機實現而定,目前主流的訪問方式有:使用句柄、直接指針。

使用句柄

在這里插入圖片描述

直接指針

在這里插入圖片描述
使用句柄來訪問的最大好處是 reference 中存儲的是穩定的句柄地址,在對象被移動時只會改變句柄中的實例數據指針,而 reference 本身不需要修改。使用直接指針訪問方式最大的好處就是速度快,它節省了一次指針定位的時間開銷

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

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

相關文章

Day23 自定義對話框服務

?本章節實現了,自定義對話框服務的功能 當現有的對話框服務無法滿足特定需求時,我們可以采用自定義對話框的解決方案,以更好地滿足一些特殊需求。 一.自定義對話框主機服務步驟 在Models 文件夾中,再建立一個 IDialogHostService 接口類,繼承自 IDialogService 對話框服…

計算兩個LocalDateTime的相差時長

在Java中,你可以使用java.time.Duration類來計算兩個LocalDateTime對象之間的時間差。以下是一個示例代碼,展示了如何計算兩個LocalDateTime實例之間相差的時長: import java.time.Duration; import java.time.LocalDateTime;public class D…

絕對實用Linux命令行下的文件夾逐層創建術,從小白到大神的必學技能

哈嘍,大家好,我是木頭左! 基礎篇:初識Linux文件系統 在深入了解如何在Linux中逐層創建文件夾之前,需要對Linux的文件系統有一個基本的認識。Linux文件系統以其樹狀結構而著稱,其中/(根目錄&…

實用的供應商管理系統推薦:提升效率的合適選擇

隨著全球化和供應鏈的復雜性增加,供應商管理系統已經成為企業提高運營效率和競爭力的重要工具。一個優秀的供應商管理系統不僅能幫助企業優化采購流程,還能有效地管理供應商關系、降低成本、提高產品質量和服務水平。 供應商管理系統,供應商管理系統推薦…

SIMBA方法解讀

目錄 預處理scRNA-seqscATAC-seq 圖構建(5種場景)scRNA-seq分析scATAC-seq分析多模態分析批次整合多模態整合 圖學習SIMBA空間中查詢實體識別TF-target genes 預處理 scRNA-seq 過濾掉在少于三個細胞中表達的基因。原始計數按文庫大小標準化&#xff0…

DDS自動化測試落地方案 | 懌星科技攜最新技術亮相是德科技年度盛會

5月28日,懌星科技作為是德科技的重要合作伙伴亮相Keysight World Tech Day 2024。在此次科技盛會上,懌星科技不僅展示了領先的DDS自動化測試解決方案等前沿技術,還分享了在“周期短、任務重”的情況下,如何做好軟件開發和測試驗證…

前端開發之性能優化

本文章 對各大學習技術論壇知識點,進行總結、歸納自用學習,共勉🙏 文章目錄 1. [CDN](https://www.bootcdn.cn/)2.懶加載3.緩存4.圖片壓縮5.圖片分割6.sprite7.Code Splitting8.gzip9.GPU加速10.Ajax11.Tree Shaking12.Resource Hints 1. CD…

YOLO系列模型 pt文件轉化為ONNX導出

文章目錄 啥是onnx怎么導出導出之后 啥是onnx Microsoft 和合作伙伴社區創建了 ONNX 作為表示機器學習模型的開放標準。許多框架(包括 TensorFlow、PyTorch、scikit-learn、Keras、Chainer、MXNet 和 MATLAB)的模型都可以導出或轉換為標準 ONNX 格式。 在…

C++筆試強訓day40

目錄 1.游游的字母串 2.體育課測驗(二) 3.合唱隊形 1.游游的字母串 鏈接https://ac.nowcoder.com/acm/problem/255195 英文字母一共就26個&#xff0c;因此可以直接暴力枚舉以每個字母作為最后的轉變字母。最后去最小值即可 #include <iostream> #include <cmath&…

趕緊收藏!2024 年最常見 20道 Kafka面試題(十)

上一篇地址&#xff1a;趕緊收藏&#xff01;2024 年最常見 20道 Kafka面試題&#xff08;九&#xff09;-CSDN博客 十九、在分布式情況下&#xff0c;Kafka 如何保證消息的順序消費&#xff1f; 在分布式系統中&#xff0c;Kafka保證消息順序消費主要依賴于其分區機制和消費…

項目實戰系列——WebSocket——websock簡介

最近項目中需要用到mes和本地客戶端進行實時通訊&#xff0c;本來想用webapi進行交互的&#xff0c;但是考慮到高效和實時性&#xff0c;就采用這一項技術。 以往采用的方式——長輪詢 客戶端主動向服務器發送一個請求&#xff0c;如果服務器沒有更新的數據&#xff0c;客戶端…

Jtti:docker部署數據庫有哪些優缺點?

在Docker中部署數據庫有其獨特的優缺點。以下是一些主要的優點和缺點&#xff1a; 優點 環境一致性&#xff1a;Docker容器提供了一致的運行環境&#xff0c;從開發到生產環境&#xff0c;確保數據庫運行環境的一致性&#xff0c;減少因環境差異導致的問題。 快速部署和遷移&am…

內置類型知多少?

內置類型&#xff08;也稱為基本類型或原生類型&#xff09;是C/C本身定義的數據類型&#xff0c;它們直接由編譯器支持&#xff0c;不需要用戶自定義。 內置類型主要包括以下幾類&#xff1a; 1&#xff0e;算術類型&#xff1a; (1)整型&#xff1a;int、short、long、lon…

【ARM Cache 系列文章 1.1 -- Cache size 讀取詳細介紹及代碼實現】

請閱讀【ARM Cache 及 MMU/MPU 系列文章專欄導讀】 及【嵌入式開發學習必備專欄】 文章目錄 ARMv8/v9 CPU Cache SizeCache Size 的計算方法Cache Size 讀取代碼實現ARMv8/v9 CPU Cache Size ARM架構通過一系列的系統寄存器來提供CPU和系統的詳細信息,包括緩存的大小和配置。…

五.應用層協議——HTTP協議

HTTP協議 在上一節中&#xff0c;我們提到了協議的本質&#xff0c;其實是雙方約定好的某種格式的數據&#xff0c;常見的就是用結構體或者類來進行表達 而上層的業務邏輯決定了我們協議的定制&#xff0c;有了協議&#xff0c;雙方就可以按照同樣的角度&#xff0c;去解讀數據…

【硬件工程師面試寶典】常見面試題其二

17. 單片機上電后沒有運轉&#xff0c;首先要檢查什么 當單片機上電后沒有運轉時&#xff0c;首先要檢查以下幾方面&#xff1a; 電源電壓&#xff1a;確保電源電壓穩定且符合單片機要求。時鐘信號&#xff1a;檢查時鐘電路是否正常工作&#xff0c;晶振是否振蕩。復位電路&a…

集合體學習01

集合體系結構 Collection 單列集合 Map 雙列集合 Collection 1.List 1.ArrayList 2.LinkedList 3.Vector 2.Set 1.HashSet 1.LinkedHashSet 2.TreeSet 其中Collection&#xff0c;List&#xff0c;Set 為接口&#xff0c;其余為實現類。 List系列集合&#xff1a;添加的元素…

一篇文章帶你入門XXE

1.什么是XXE&#xff1f; XML External Entity&#xff08;XXE&#xff09;攻擊是一種利用 XML 處理器的漏洞&#xff0c;通過引入惡意的外部實體來攻擊應用程序的安全性。這種攻擊通常發生在對用戶提供的 XML 數據進行解析時&#xff0c;攻擊者利用了 XML 規范允許引用外部實體…

kafka-集群搭建(在docker中搭建)

文章目錄 1、kafka集群搭建1.1、下載鏡像文件1.2、創建zookeeper容器并運行1.3、創建3個kafka容器并運行1.3.1、9095端口1.3.2、9096端口1.3.3、9097端口 1.4、重啟kafka-eagle1.5、查看 efak1.5.1、查看 brokers1.5.2、查看 zookeeper 1、kafka集群搭建 1.1、下載鏡像文件 d…

實時監控電腦屏幕軟件有哪些?(珍藏篇)

在當今的數字化工作環境中&#xff0c;實時監控電腦屏幕軟件是企業管理、遠程協助、教育監控等領域不可或缺的工具。 這些軟件能夠幫助管理者了解員工的工作狀態、提升團隊協作效率、確保數據安全&#xff0c;同時在家庭教育和遠程技術支持中也有廣泛應用。 以下是精選的幾款實…