JVM 內存、JMM內存與集群機器節點內存的聯系

目錄

1、JVM 內存

1.1、分配機制

1.2、jvm模型位置

1.3、字節碼內存塊

2、JMM內存

?2.1、JMM模型

2.2、工作流程圖

1、工作內存與主內存的交互

2. 多線程下的主內存與堆內存交互

2.3、 主內存與工作內存的同步方案

1、volatile

2、synchronized

3、final

3、內存使用

3.1、集群環境

3.2、容器化環境

3.3、示例場景

4、常見問題與解決方案


前言

? ? ? ? 在日常開發過程中,不知道你是否考慮JVM內存模型、JMM模型、計算機內存模型它們是通過何種機制來進行聯系的。

問題:

? ? ? ? 比如當選擇一臺物理機器節點部署應用的時候,如何選擇規模適度的內存大小?選擇了計算機內存后,如何為程序應用選擇JVM內存大小。

????????在jvm內存大小設定好,JMM模型是如何用jvm交互的呢?本篇將介紹下,它們的聯系及內存分配。


1、JVM 內存

1.1、分配機制

????????JVM運行內存分配時,其最終由?操作系統?管理。

????????JVM 的內存參數(如?-Xms、-Xmx)只是告訴 JVM?它期望使用的內存范圍,但實際使用的內存是?運行 JVM 的物理機器或虛擬機節點的內存

如下圖所示:

根據上面可以看出:

????????JVM內存模型是模仿操作系統內存模型構建的,JVM內存模型和操作系統內存模型是可以一一對應起來的。

1.2、jvm模型位置

關于jvm內存模型,可參考:關于對JVM的知識整理_jvm知識-CSDN博客

?????????JVM就類似于一個操作系統,整個JVM內存模型存儲在操作系統的堆中。

如下圖所示:

1、方法區:

????????而JVM的方法區,也就相當于操作系統/主機的硬盤區,也叫永久區;而操作系統棧(本地方法棧)和JVM的棧也是一致的;

2、堆:

????????JVM堆和操作系統堆在概念上和目標上是一致的,分配內存的方式也是一致的,但JVM堆管理垃圾的方式是GC回收,而操作系統堆則是需要程序員手動釋放;

3、PC寄存器:

????????計算機上的PC寄存器是計算機上的硬件(是CPU內部用來存放“偽指令”或地址數據的一些小型存儲區域)。

????????而對于虛擬機,PC寄存器它表現為一塊內存(一個字長,虛擬機要求字長最小為32位),存放的是將要執行指令的地址。

1.3、字節碼內存塊

關于更多方法區的介紹,可參考:關于對JVM的知識整理_jvm知識-CSDN博客

? ? ? ? ClassLoader這個類加載器存放在堆內存,當一個classLoder啟動的時候,它會去主機硬盤上將A.class加載到jvm的方法區。

如下所示:

????????方法區里面的字節文件會被虛擬機讀取并執行new A字節碼(),然后在堆內存生成了一個A字節碼的對象。

此時方法區里面A字節碼內存文件有兩個引用:

一個指向A的class對象,一個指向加載自己的classLoader引用。

如下圖。

??????????注意:圖里面的字段信息應該是字段的結構信息(方法區),而不是字段的值(堆內存)。

對比字節碼內存塊和類的信息。

代碼示例:

public final class ClassStruct extends Object implements Serializable {// 實例變量的值(存儲在堆內存)// 實例變量的(結構信息存放在方法區)private String name;private int id;// 靜態常量(存儲在方法區)public final int CONST_INT = 0;public final String CONST_STR = "CONST_STR";// 靜態變量(存儲在方法區)public static String static_str = "static_str";// 靜態方法(字節碼存儲在方法區)public static final String getStatic_str() throws Exception {return ClassStruct.static_str;}
}

結論:jvm方法區里面的字節碼內存就是將完整的類信息加載到了內存。

參考類的信息:

ClassStruct
├── 類名: "ClassStruct"
├── 父類: "java.lang.Object"
├── 接口: "java.io.Serializable"
├── 字段:
│   ├── name: private java.lang.String
│   ├── id: private int
│   ├── static_str: public static java.lang.String
│   ├── CONST_INT: public final int
│   └── CONST_STR: public final java.lang.String
├── 方法:
│   └── getStatic_str(): public static final
└── 常量池:├── "static_str"├── "CONST_STR"└── 0

???????1.類信息:修飾符(public final)

????????????????????????是類還是接口(class,interface)

????????????????????????類的全限定名(Test/ClassStruct.class)

????????????????????????直接父類的全限定名(java/lang/Object.class)

????????????????????????直接父接口的權限定名數組(java/io/Serializable)

?public final class ClassStruct extends Object implements Serializable這段描述的信息提取

???????2.字段結構信息:修飾符(pirvate)

????????????????????????????字段類型(java/lang/String.class)

????????????????????????????字段名(name)

? ? ? ? private String name;這段描述信息的提取。(實例變量的值存放在堆內存里面)

???????3.方法信息:修飾符(public static final)

??????????????????????????方法返回值(java/lang/String.class)

??????????????????????????方法名(getStatic_str)

??????????????????????????參數需要用到的局部變量的大小還有操作數棧大小(操作數棧)

??????????????????????????方法體的字節碼(就是花括號里的內容)

??????????????????????????異常表(throws Exception)

? ? ? ?public static final String getStatic_str ()throws Exception的字節碼的提取

?????????4.常量池:

? ?????????????????整型直接常量池public final int CONST_INT=0;

???????????????????字符串直接常量池???public final String CONST_STR="CONST_STR";

? ? ? ? ? ? ? ? ? ? 浮點型直接常量池? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

????????方法名、方法描述符、類名、字段名,字段描述符的符號引用

? ? ? 5.類變量:

??????????????????就是靜態字段(?public static String static_str="static_str";)

??????????????????虛擬機在使用某個類之前,必須在方法區為這些類變量分配空間。

??????6.一個到堆內存classLoader的引用:

????????通過this.getClass().getClassLoader()。

??????7.一個到堆內存class A對象的引用:

????????這個對象存儲了所有這個字節碼內存塊的相關信息。

可使用反射:java的反射詳解_java中的反射-CSDN博客

1、類信息,你可以通過this.getClass().getName()取得;

2、所有的方法信息,可以通過this.getClass().getDeclaredMethods()。

3、字段信息可以通過this.getClass().getDeclaredFields()。


2、JMM內存

?2.1、JMM模型

????????Java 內存模型(Java Memory Model, JMM)定義了多線程環境下變量的可見性、原子性和有序性規則。

如下圖所示:

Java 內存模型(JMM)
├── 主內存(所有線程共享)
│   ├── 堆內存(對象實例、數組)
│   ├── 方法區(類元數據信息、常量池、靜態變量、字節碼文件)
│   └── 靜態變量
└── 工作內存(每個線程私有)├── 虛擬機棧(局部變量)└── 本地方法棧(Native 方法使用)

1、堆內存與JMM 主內存的聯系

JVM 堆內存是 Java 內存模型(JMM)中主內存的一部分。

堆內存中的對象屬于主內存

????????所有在堆中創建的對象(如?new object())存儲在 JMM 的主內存中。多線程共享這些對象,線程通過工作內存(如 CPU 緩存)讀寫堆內存中的對象。

JMM 的主內存范圍更廣

主內存?不僅包含堆內存,還包括:

????????方法區(存儲類信息、靜態方法和字段、常量池、字節碼文件等,JDK 8 后移至元空間 Metaspace)。

????????靜態變量(存儲在方法區)。

????????局部變量(存儲在虛擬機棧中,但變量引用的對象存儲在堆中)。

主內存 vs 工作內存

????????主內存:所有線程共享的物理內存(包括堆、方法區等)。

????????工作內存:每個線程私有的本地內存(如 CPU 寄存器、高速緩存),用于臨時存儲變量副本。

注意:堆內存?是主內存中用于存儲對象實例的核心部分。

總結

2.2、工作流程圖

1、工作內存與主內存的交互

2. 多線程下的主內存與堆內存交互

1、變量讀寫流程

線程訪問變量

????????如果變量在主內存(如堆中的對象字段),線程會將變量復制到工作內存。修改后,線程將更新后的值寫回主內存(通過?happens-before規則保證可見性)。

2、內存可見性問題

  • 默認情況下,線程對變量的修改對其他線程不可見(因為工作內存和主內存的同步延遲)。
  • 解決方案
    • 使用?volatile?關鍵字:強制每次讀寫都直接訪問主內存。
    • 使用?synchronized?或?Lock:通過鎖機制確保內存同步。

代碼示例:

public class JMMExample {private int sharedVariable = 0; // 存儲在堆內存(主內存)public void increment() {int localVariable = this.sharedVariable; // 從主內存讀取到工作內存localVariable++;this.sharedVariable = localVariable; // 將修改后的值寫回主內存}
}
  • 線程 A 執行?increment():
    1. 從主內存(堆)讀取?sharedVariable?到工作內存。
    2. 修改后寫回主內存。
  • 線程 B 讀取?sharedVariable:
    • 如果未使用?volatile?或?synchronized,可能讀取到舊值(工作內存未同步)。

2.3、 主內存與工作內存的同步方案

1、volatile

關于volatile的實現詳細可參考:對于Synchronized和Volatile的深入理解_java sychronized和volatile以及同步代碼塊-CSDN博客

private volatile int sharedVariable = 0;
  • 作用:禁止線程緩存變量副本,每次讀寫直接操作主內存。

2、synchronized

關于synchronized的實現可參考:對于Synchronized和Volatile的深入理解_java sychronized和volatile以及同步代碼塊-CSDN博客

public synchronized void increment() {sharedVariable++;
}
  • 作用:通過鎖確保變量的修改對其他線程可見。

3、final

關于final的具體應用,可參考:對于final、finally和finalize不一樣的理解-CSDN博客

private final int sharedVariable = 0;
  • 作用:final?變量在構造函數結束后對其他線程可見。


3、內存使用

3.1、集群環境

????????在?集群部署(如 Kubernetes、Docker Swarm、物理服務器集群)中,每個 JVM 實例運行在某個?節點(Node)?上。

JVM 的內存分配規則如下:

1、節點物理內存 vs JVM 堆內存

1.JVM 堆內存(Heap Memory)

????????通過?-Xms(初始堆大小)和-Xmx(最大堆大小)參數配置。這些參數控制的是?JVM 堆內存,但它會占用?所在節點的物理內存

????????例如:-Xmx4g?表示 JVM 最多可以使用 4GB 節點內存用于堆。

2.非堆內存(Metaspace、Direct Memory 等)

????????Metaspace(類元數據):默認無上限(需通過?-XX:MaxMetaspaceSize?限制)。

????????直接內存(Direct Memory):通過?-XX:MaxDirectMemorySize?配置,同樣占用節點物理內存。

如下圖所示:

3.2、容器化環境

如Docker/Kubernetes。

1、容器內存限制

????????如果 JVM 運行在容器中(如 Docker 容器),容器的內存限制(如?--memory=4g?或 Kubernetes 的?resources.limits.memory)會?限制 JVM 可使用的總內存

????????JVM 無法突破容器內存限制,否則會被操作系統強制終止(OOMKilled)。

2、JVM 參數與容器限制的關系

????????-Xmx?應小于容器內存限制的?70%-80%,為其他組件(如非堆內存、OS 緩存)預留空間。例如:容器內存限制為 4GB,則?-Xmx?建議設為?3g

3.3、示例場景

1:物理服務器集群

  • 節點配置:8GB 內存。
  • JVM 配置:-Xmx4g
  • 實際內存使用:JVM 最多占用 4GB 節點內存(堆內存),其余內存可用于其他服務(如數據庫、中間件)。

2:Kubernetes 集群

  • Pod 配置:resources.limits.memory=4Gi。
  • JVM 配置:-Xmx3g。
  • 實際內存使用:JVM 最多占用 3GB 容器內存,剩余 1GB 用于非堆內存和容器內其他進程。


4、常見問題與解決方案

1、JVM 報?OOM?但節點內存充足

  • 原因
    • JVM 堆內存未配置,導致堆內存無限制。
    • 非堆內存(如 Metaspace)未限制,導致內存泄漏。
  • 解決方案
    • 顯式設置?-Xmx?和?-XX:MaxMetaspaceSize。
    • 監控 JVM 內存使用(如通過 Prometheus + Grafana)。

2、容器被 OOMKilled

  • 原因
    • JVM 堆內存 + 非堆內存 + 容器其他進程內存總和超過容器限制。
  • 解決方案
    • 降低?-Xmx,為非堆內存和系統開銷預留空間。
    • 使用容器內存配額(如 Kubernetes 的?resources.limits.memory)。


參考文章:

1、JVM內存是對應到操作系統內存_jvm內存和電腦內存的關系-CSDN博客

2、關于對JVM的知識整理_jvm知識-CSDN博客

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

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

相關文章

學習昇騰開發的第一天--環境配置

1、昇騰社區官網:昇騰社區官網-昇騰萬里 讓智能無所不及 2、產品-->選擇開發者套件-->點擊制卡工具的下載:資源-Atlas 200I DK A2-昇騰社區 3、如果制卡工具不能使用在線制卡,可以下載鏡像到本地使用本地制卡:Linux系統制…

Android WebView 深色模式適配方案總結

Android WebView 深色模式適配方案總結 在 Android WebView 中適配深色模式(Dark Mode)是一個常見的需求,尤其是當加載的網頁沒有原生支持 prefers-color-scheme 時。本文將介紹 3 種主流方案,并分析它們的優缺點,幫助…

項目練習:使用mybatis的foreach標簽,實現union all的拼接語句

文章目錄 一、需求說明二、需求分析三、代碼實現四、報表效果 一、需求說明 在sql查詢數據后,對數據分組統計。并最后進行總計。 二、需求分析 最終,我想用sql來實現這個統計和查詢的功能。 那么,怎么又查詢,又統計了&#xf…

7.7 Extracting and saving responses

Chapter 7-Fine-tuning to follow instructions 7.7 Extracting and saving responses 在本節中,我們保存測試集響應以便在下一節中評分,除此之外保存模型的副本以供將來使用。 ? 首先,讓我們簡單看看finetuned模型生成的響應 torch.manu…

計算機網絡第3章(上):數據鏈路層全解析——組幀、差錯控制與信道效率

目錄 一、數據鏈路層的功能二、組幀2.1 字符計數法(Character Count)2.2 字符填充法(Character Stuffing)2.3 零比特填充法2.4 違規編碼法 三、差錯控制3.1 檢錯編碼(奇偶校驗碼)3.2 循環冗余校驗&#xff…

鑄鐵試驗平臺的重要性及應用前景

鑄鐵作為一種重要的金屬材料,在工業生產中扮演著舉足輕重的角色。為了確保鑄鐵制品的質量和性能,鑄鐵材料的試驗是必不可少的環節。而鑄鐵試驗平臺則是進行鑄鐵試驗的關鍵設備之一,它為鑄鐵材料的研究和開發提供了重要的技術支持。本文將探討…

std::shared_ptr引起內存泄漏的例子

目錄 一、循環引用(最常見場景) 示例代碼 內存泄漏原因 二、共享指針管理的對象包含自身的 shared_ptr 示例代碼 內存泄漏(或雙重釋放)原因 三、解決方案 1. 循環引用:使用 std::weak_ptr 2. 對象獲取自身的 …

AI 知識數據庫搭建方案:從需求分析到落地實施

AI 知識數據庫的搭建需結合業務場景、數據特性與技術架構,形成系統化解決方案。以下是一套完整的搭建框架,涵蓋規劃、設計、實施及優化全流程: 一、前期規劃:需求分析與目標定義 1. 明確業務場景與知識需求 場景導向&#xff1a…

Tensorflow 基礎知識:變量、常量、占位符、Session 詳解

在深度學習領域,TensorFlow 是一個廣泛使用的開源機器學習框架。想要熟練使用 TensorFlow 進行模型開發,掌握變量、常量、占位符和 Session 這些基礎知識是必不可少的。接下來,我們就深入了解一下它們的概念、用處,并通過代碼示例進行演示。 一、常量(Constant) 常量,顧…

linux 常見問題之如何清除大文件的內容

linux 常見問題之如何清除大文件的內容 在 Linux 系統中,我們有時會遇到文件隨著時間增長變得巨大,最常見的就是服務器的日志文件,隨著時間的推移占用大量的磁盤空間,下面介紹如何清楚大文件的內容,當然避免文件內容過…

薛定諤的貓思想實驗如何推演到量子計算

前言 這是我的選修課作業,但是我并不喜歡小論文方式的寫法,死板又老套。先在這打一份底稿。 薛定諤的貓 可能一說到量子這個關鍵詞,大家第一時間都會想到的是“薛定諤的貓”。 實驗介紹 薛定諤的貓是一個著名的思想實驗,由奧…

嵌入式開發中fmacro-prefix-map選項解析

在嵌入式開發中,-fmacro-prefix-map 是 GCC 和 Clang 等編譯器提供的一個路徑映射選項,主要用于在預處理階段重寫宏定義中出現的絕對路徑。它的核心目的是解決以下問題: 核心作用 構建可重現性 消除編譯輸出(如 .o、.d 文件&…

Javaweb學習——day3(Servlet 中處理表單數據)

文章目錄 一、概念學習1. GET vs POST 請求方式的區別2. HttpServletRequest 獲取表單數據 二、代碼講解與練習第 1 步:在 webapp 下創建 login.html第 2 步:在 com.example 包下創建 LoginServlet第 3 步:修改 web.xml 注冊 LoginServlet第 …

在 iOS 開發中單獨解析域名為 IP

1 為什么要自己解析? 典型場景說明劫持/污染檢測比較 系統解析 與 自建 DNS 的差異QoS / CDN 選路對每個候選 IP 做 RT/丟包測速系統 API(NSURLSession / Network.framework)在「真正建立連接之前」不會把解析結果暴露出來,因此需要主動解析一步。 2 API 選型概覽 API是否過…

YOLOv1 技術詳解:正負樣本劃分與置信度設計

🔍 YOLOv1 技術詳解:正負樣本劃分與置信度設計 一、前言 YOLOv1 是目標檢測領域中具有劃時代意義的算法之一,它將檢測任務統一為一個回歸問題,實現了“You Only Look Once”的端到端實時檢測。其中,正負樣本的劃分機…

為 Nginx 配置 HTTPS(以 n8n 為例)完整教程【CentOS 7】

在部署如 n8n 這類自動化平臺時,為了保障數據傳輸安全,我們通常會使用 HTTPS 訪問。本文將以 n8n.example.com 為例,介紹如何在 CentOS 7 系統中通過 Nginx 為本地運行在端口 5678 的 n8n 服務配置免費 SSL 證書(Let’s Encrypt&a…

Elasticsearch從安裝到實戰、kibana安裝以及自定義IK分詞器/集成整合SpringBoot詳細的教程ES(四)查詢、排序、分頁、高亮

基礎代碼 package com.test.xulk;import com.alibaba.fastjson.JSON; import com.test.xulk.es.esdoc.HotelDoc; import com.test.xulk.es.service.IHotelService; import org.apache.http.HttpHost; import org.elasticsearch.action.search.SearchRequest; import org.elast…

一個數組樣式上要分成兩個

如圖所示&#xff0c;要有一個區分來顯示&#xff0c;如果一開始就是這樣還可以有很多種處理方式&#xff0c;但是這個后期一直在調整所以不好重做因為開發已經完成&#xff0c;加上很多地方聯動改的地方太多&#xff0c;所以采用了一個比較笨的方法 <ul class"classif…

NLP進化史:從規則模板到思維鏈推理,七次范式革命全解析

“語言不是神的創造物&#xff0c;而是平凡人類的產物。”——諾姆喬姆斯基 自然語言處理&#xff08;NLP&#xff09;的發展史&#xff0c;就是人類試圖教會機器理解語言本質的探索史。本文將帶您穿越70年技術長河&#xff0c;揭示NLP領域關鍵的范式轉換里程碑。 一、規則驅動…

Yarn與NPM緩存存儲目錄遷移

Yarn與NPM緩存存儲目錄遷移 背景與需求 解釋Yarn和NPM緩存機制的作用及默認存儲路徑遷移緩存目錄的常見原因&#xff08;如磁盤空間不足、系統盤性能優化、多項目協作需求&#xff09; Yarn緩存目錄遷移方法 查看當前Yarn緩存目錄的命令&#xff1a;yarn cache dir修改Yarn…