講講 JVM 的內存結構(附上Demo講解)

講講 JVM 的內存結構

  • 什么是 JVM 內存結構?
    • 線程私有
      • 程序計數器?
      • 虛擬機棧
      • 本地方法棧
    • 線程共享
      • 堆?
      • 方法區?
      • 注意
        • 永久代?
        • 元空間?
        • 運行時常量池?
        • 直接內存?
  • 代碼詳解

什么是 JVM 內存結構?

在這里插入圖片描述

JVM內存結構分為5大區域,程序計數器、虛擬機棧、本地方法棧、堆、方法區。?

HotSpot在JDK1.8之前方法區就是永久代,永久代就是方法區。JDK1.8后刪除了永久代,改為元空間,元空間在本地內存中。方法區就是元空間,元空間就是方法區。?

創建一個線程,JVM就會為其分配一個私有內存空間,其中包括PC、虛擬機棧和本地方法棧?

簡單來說:

  • 堆:存放 new 出來的東西
  • 方法區:被虛擬機加載的類信息、常量、靜態常量等。
  • 棧:存放局部變量
  • 程序計數器:記錄指令
  • 本地方法棧:Native 方法

接著進行詳細的介紹:

線程私有

程序計數器?

線程私有的,作為當前線程的行號指示器,用于記錄當前虛擬機正在執行的線程指令地址。程序計數器主要有兩個作用:?

  • 當前線程所執行的字節碼的行號指示器,通過它實現代碼的流程控制,如:順序執行、選擇、循環、異常處理。?
  • 多線程的情況下,程序計數器用于記錄當前線程執行的位置,當線程被切換回來的時候能夠知道它上次執行的位置。?

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

虛擬機棧

Java 虛擬機棧是由一個個棧幀組成,而每個棧幀中都擁有:局部變量表、操作數棧、動態鏈接、方法出口信息。每一次函數調用都會有一個對應的棧幀被壓入虛擬機棧,每一個函數調用結束后,都會有一個棧幀被彈出。?

局部變量表是用于存放方法參數和方法內的局部變量。?

每個棧幀都包含一個指向運行時常量池中該棧所屬方法的符號引用,在方法調用過程中,會進行動態鏈接,將這個符號引用轉化為直接引用。?

  • 部分符號引用在類加載階段的時候就轉化為直接引用,這種轉化就是靜態鏈接?
  • 部分符號引用在運行期間轉化為直接引用,這種轉化就是動態鏈接?

Java 虛擬機棧也是線程私有的,每個線程都有各自的 Java 虛擬機棧,而且隨著線程的創建而創建,隨著線程的死亡而死亡。

Java 虛擬機棧會出現兩種錯誤:StackOverFlowErrorOutOfMemoryError。?
可以通過 -Xss 參數來指定每個線程的虛擬機棧內存大小:java -Xss2M?

本地方法棧

虛擬機棧為虛擬機執行 Java 方法服務,而本地方法棧則為虛擬機使用到的 Native 方法服務。Native 方法一般是用其它語言(C、C++等)編寫的。?

本地方法被執行的時候,在本地方法棧也會創建一個棧幀,用于存放該本地方法的局部變量表、操作數棧、動態鏈接、出口信息。?

線程共享

堆?

堆用于存放對象實例,是垃圾收集器管理的主要區域,因此也被稱作GC堆。?

堆可以細分為:新生代(Eden空間(伊甸園)、From Survivor、To Survivor空間)和老年代。?

通過 -Xms 設定程序啟動時占用內存大小,通過 -Xmx 設定程序運行期間最大可占用的內存大小。如果程序運行需要占用更多的內存,超出了這個設置值,就會拋出OutOfMemory異常。?

方法區?

方法區與 Java 堆一樣,是各個線程共享的內存區域,它用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。?

對方法區進行垃圾回收的主要目標是對常量池的回收和對類的卸載。?

注意

永久代?

方法區是 JVM 的規范,而永久代PermGen 是方法區的一種實現方式,并且只有 HotSpot 有永久代。對于其他類型的虛擬機,如 JRockit 沒有永久代。由于方法區主要存儲類的相關信息,所以對于動態生成類的場景比較容易出現永久代的內存溢出。?

元空間?

JDK 1.8 的時候,HotSpot的永久代被徹底移除了,使用元空間替代。元空間的本質和永久代類似,都是對JVM規范中方法區的實現。

兩者最大的區別在于:元空間并不在虛擬機中,而是使用本地內存。
?

為什么要將永久代替換為元空間呢??
永久代內存受限于 JVM 可用內存,而元空間使用的是直接內存,受本機可用內存的限制,雖然元空間仍舊可能溢出,但是相比永久代內存溢出的概率更小。?

運行時常量池?

運行時常量池是方法區的一部分,在類加載之后,會將編譯器生成的各種字面量和符號引號放到運行時常量池。在運行期間動態生成的常量,如 String 類的 intern()方法,也會被放入運行時常量池。?

直接內存?

直接內存并不是虛擬機運行時數據區的一部分,也不是虛擬機規范中定義的內存區域,但是這部分內存也被頻繁地使用,而且也可能導致 OutOfMemoryError 錯誤出現。?

NIO 的 Buffer 提供了 DirectBuffer,可以直接訪問系統物理內存,避免堆內內存到堆外內存的數據拷貝操作,提高效率。

DirectBuffer直接分配在物理內存中,并不占用堆空間,其可申請的最大內存受操作系統限制,不受最大堆內存的限制。?

直接內存的讀寫操作比堆內存快,可以提升程序I/O操作的性能。通常在I/O通信過程中,會存在堆內內存到堆外內存的數據拷貝操作,對于需要頻繁進行內存間數據拷貝且生命周期較短的暫存數據,都建議存儲到直接內存。

在這里插入圖片描述

代碼詳解

以下是一個簡單的 Java 類,我們將在注釋中說明各個內存區域的作用:

public class MemoryStructureExample {// 靜態變量,存放在方法區private static int staticVar = 42;public static void main(String[] args) {// 局部變量,存放在虛擬機棧int localVar = 10;// 創建一個對象,存放在堆中MemoryStructureExample obj = new MemoryStructureExample();// 調用方法,創建一個新的棧幀obj.doSomething(localVar);// 創建一個數組,存放在堆中int[] array = new int[5];// 常量,存放在方法區final String constantString = "Hello, world!";// 本地方法調用,使用本地方法棧System.out.println("Static variable: " + staticVar);System.out.println("Constant string: " + constantString);}// 方法,存放在方法區public void doSomething(int value) {// 局部變量,存放在虛擬機棧int result = value * 2;System.out.println("Result: " + result);}
}

在這段代碼中,我們可以看到:

  • staticVar 是一個靜態變量,存放在方法區。
  • localVar 是一個局部變量,存放在虛擬機棧。
  • obj 是一個對象,存放在堆中。
  • array 是一個數組,也存放在堆中。
  • constantString 是一個常量,存放在方法區。
  • doSomething 方法創建了一個新的棧幀,其中的局部變量存放在虛擬機棧。

總之,這些內存區域共同構成了 Java 虛擬機的內存結構,確保 Java 程序的正常運行和優化。如果你還有其他問題,歡迎繼續提問!

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

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

相關文章

C# 泛型

泛型 泛型不是語法糖,而是由框架提供的一種便捷語法,首次出現在.NET 2.0中。 1. 泛型定義 泛型:是一種程序特性,定義時不對類型做出明確的規定,使用時規定且不能改變。一般應用:泛型集合、泛型方法、泛型…

機器學習——LR、?GBDT、?SVM、?CNN、?DNN、?RNN、?Word2Vec等模型的原理和應用

LR(邏輯回歸) 原理: 邏輯回歸模型(Logistic Regression, LR)是一種廣泛應用于分類問題的統計方法,尤其適用于二分類問題。其核心思想是通過Sigmoid函數將線性回歸模型的輸出映射到(0,1)區間,從…

【AI前沿】深度學習:神經網絡基礎

文章目錄 📑引言一、神經元和感知器1.1 神經元的基本概念1.2 感知器模型 二、多層感知器(MLP)2.1 MLP的基本結構2.2 激活函數的重要性2.3 激活函數2.4 激活函數的選擇 三、小結 📑引言 深度學習是現代人工智能的核心技術之一&…

kotlin Flow 學習指南 (三)最終篇

目錄 前言Flow生命周期StateFlow 替代LiveDataSharedFlow其他常見應用場景處理復雜、耗時邏輯存在依賴關系的接口請求組合多個接口的數據 Flow使用注意事項總結 前言 前面兩篇文章,介紹了Flow是什么,如何使用,以及相關的操作符進階&#xff…

如何挑選適合的需求池管理系統?10款優質工具分享

本文將分享10款優質需求池管理工具:PingCode、Worktile、Teambition、Epicor Kinetic、TAPD、SAP IBP、Logility、RELEX Solutions、JIRA、明道云。 在管理項目和產品需求時,正確的工具能夠大幅提高效率與透明度。如何從眾多需求池工具中選擇最適合團隊的…

第一節 SHELL腳本中的常用命令(2)

二,網絡管理命令nmcli 1.查看網卡 # 或者先用ip addr或ip a等查看網卡 ip a s 網卡名 ifconfig 網卡名 nmcil device show 網卡名 nmcil device status nmcil connection show 網卡名2.設置網卡 a)當網卡未被設置過時 設置dncp網絡工作模式 nmcil connection add con-name…

Rust編程-編寫自動化測試

編寫單元測試步驟: 1. 準備所需的數據 2. 調用需要測試的代碼 3. 斷言運行結果與我們所期望的一致 Rust的test元數據: #[cfg(test)]:是一個屬性宏(attribute macro)。用于控制特定的代碼段僅在測試環境中編譯…

自定義類型:聯合體

像結構體一樣,聯合體也是由一個或者多個成員組成,這些成員可以是不同的類型。 聯合體類型的聲明 編譯器只為最?的成員分配?夠的內存空間。聯合體的特點是所有成員共?同?塊內存空間。所以聯合體也叫:共?體。 輸出結果: 聯合體…

size_t 數據類型的好處

什么是size_t size_t 類型在不同的平臺上對應不同的底層整數類型,具體取決于平臺的指針大小。size_t 主要用于表示大小和長度,如數組的元素數量、緩沖區的大小等,它的設計目的是為了匹配指針的大小,以避免類型不匹配引起的錯誤。…

代碼隨想錄算法訓練營DAY58|101.孤島的總面積、102.沉沒孤島、103. 水流問題、104.建造最大島嶼

忙。。。寫了好久。。。。慢慢補吧。 101.孤島的總面積 先把周邊的島嶼變成水dfs def dfs(x, y, graph, s):if x<0 or x>len(graph) or y<0 or y>len(graph[0]) or graph[x][y]0:return sgraph[x][y]0s1s dfs(x1, y, graph, s)s dfs(x-1, y, graph, s)s dfs(…

【爬蟲入門知識講解:xpath】

3.3、xpath xpath在Python的爬蟲學習中&#xff0c;起著舉足輕重的地位&#xff0c;對比正則表達式 re兩者可以完成同樣的工作&#xff0c;實現的功能也差不多&#xff0c;但xpath明顯比re具有優勢&#xff0c;在網頁分析上使re退居二線。 xpath 全稱為XML Path Language 一種…

軟考高級第四版備考--第16天(規劃溝通管理)Plan Communication Management

定義&#xff1a;基于每個干系人或干系人群體的信息需求、可用的組織資產以及具體的項目的需求&#xff0c;為項目溝通活動制定恰當的方法和計劃的過程。 作用&#xff1a; 及時向干系人提供相關信息&#xff1b;引導干系人有效參與項目&#xff1b;編制書面溝通計劃&#xf…

【基于R語言群體遺傳學】-16-中性檢驗Tajima‘s D及連鎖不平衡 linkage disequilibrium (LD)

Tajimas D Test 已經開發了幾種中性檢驗&#xff0c;用于識別模型假設的潛在偏差。在這里&#xff0c;我們將說明一種有影響力的中性檢驗&#xff0c;即Tajimas D&#xff08;Tajima 1989&#xff09;。Tajimas D通過比較數據集中的兩個&#x1d703; 4N&#x1d707;估計值來…

vue項目中常見的一些preset及其關系

Babel的作用 Babel主要用途是用來做js代碼轉換的&#xff0c;將最新的js語法或者api轉換成低版本瀏覽器可兼容執行的代碼。 語法兼容是指一些瀏覽器新特性增加的js寫法&#xff0c;例如箭頭函數 ()>{}&#xff1b;低版本的瀏覽器無法識別這些&#xff0c;會導致一些語法解…

spark shuffle寫操作——UnsafeShuffleWriter

PackedRecordPointer 使用long類型packedRecordPointer存儲數據。 數據結構為&#xff1a;[24 bit partition number][13 bit memory page number][27 bit offset in page] LongArray LongArray不同于java中long數組。LongArray可以使用堆內內存也可以使用堆外內存。 Memor…

秋招突擊——7/9——字節面經

文章目錄 引言正文八股MySQL熟悉嗎&#xff1f;講一下MySQL索引的結構&#xff1f;追問&#xff1a;MySQL為什么要使用B樹&#xff1f;在使用MySQL的時候&#xff0c;如何避免索引失效&#xff1f;講一下MySQL的事物有哪幾種特征&#xff1f;MySQL的原子性可以實現什么效果&…

GESP C++ 三級真題(2023年9月)T2 進制判斷

進制判斷 問題描述 N進制數指的是逢N進一的計數制。例如&#xff0c;人們日常生活中大多使用十進制計數&#xff0c; 而計算機底層則一般使用二進制。除此之外&#xff0c;八進制和十六進制在一些場合也是 常用的計數制(十六進制中&#xff0c;一般使用字母A至F表示十至十五…

【區塊鏈+跨境服務】粵澳健康碼跨境互認系統 | FISCO BCOS應用案例

2020 年突如其來的新冠肺炎疫情&#xff0c;讓社會治理體系面臨前所未見的考驗&#xff0c;如何兼顧疫情防控與復工復產成為社會 各界共同努力的目標。區塊鏈技術作為傳遞信任的新一代信息基礎設施&#xff0c;善于在多方協同的場景中發揮所長&#xff0c;從 而為粵澳兩地的疫情…

uniapp上傳文件并獲取上傳進度

1. 上傳普通文件 uni.chooseMessageFile({count: 1,success: (res) > {console.log(res)console.log("res123456", res.tempFiles[0].path)const uploadTask uni.uploadFile({url: http://localhost:8000/demo,filePath: res.tempFiles[0].path,name: file,form…

CSS關于居中的問題

文章目錄 1. 行內和塊級元素自身相對父控件居中1.1. 塊級元素相對父控件居中1.2. 行內元素相對于父控件居中 2. 實現單行文字垂直居中3. 子絕父相實現子元素的水平垂直居中3.1. 方案一3.1.1. 示例 3.2. 方案二3.2.1. 示例 3.3. 方案三(推薦)3.3.1. 示例 3.4. 方案四(了解一下) …