欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JVM內(nèi)存劃分機(jī)制的使用詳解

 更新時(shí)間:2025年05月04日 22:09:42   作者:棕豆兔&  
這篇文章主要介紹了JVM內(nèi)存劃分機(jī)制的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

一、JVM 執(zhí)行流程

程序在執(zhí)行之前先要把 java 代碼轉(zhuǎn)換成字節(jié)碼(class文件),JVM 首先需要把字節(jié)碼通過(guò)一定的方式:類加載器(ClassLoader) 把文件加載到內(nèi)存中運(yùn)行時(shí)數(shù)據(jù)區(qū)(Runtime Data Area),而字節(jié)碼文件是 JVM 的一套指令集規(guī)范,并不能直接交個(gè)底層操作系統(tǒng)去執(zhí)行,因此需要特定的命令解析器 “執(zhí)行引擎(Execution Engine)”將字節(jié)碼翻譯成底層系統(tǒng)指令再交由CPU去執(zhí)行,而這個(gè)過(guò)程中需要調(diào)用其他語(yǔ)言的接口,本地庫(kù)接口(Native Interface) 來(lái)實(shí)現(xiàn)整個(gè)程序的功能,這就是這4個(gè)主要組成部分的職責(zé)與功能。

總結(jié)來(lái)看,JVM 主要通過(guò)分為以下 4 個(gè)部分,來(lái)執(zhí)行 Java 程序的:

  1. 類加載器(ClassLoader)
  2. 運(yùn)行時(shí)數(shù)據(jù)區(qū)(Runtime Data Area)
  3. 執(zhí)行引擎(Execution Engine)
  4. 本地庫(kù)接口(Native Interface)

二、JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)

JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)域也叫內(nèi)存布局,但需要注意的是它和 Java 內(nèi)存模型((Java Memory Model,簡(jiǎn)稱 JMM)完全不同,屬于完全不同的兩個(gè)概念,它由以下 5 大部分組成:

2.1 堆(線程共享)

堆的作用:程序中創(chuàng)建的所有對(duì)象都在保存在堆中。

我們常見的 JVM 參數(shù)設(shè)置 -Xms10m 最小啟動(dòng)內(nèi)存是針對(duì)堆的,-Xmx10m 最大運(yùn)行內(nèi)存也是針對(duì)堆的。

ms 是 memory start 簡(jiǎn)稱,mx 是 memory max 的簡(jiǎn)稱。

堆里面分為兩個(gè)區(qū)域:新生代和老生代,新生代放新建的對(duì)象,當(dāng)經(jīng)過(guò)一定 GC 次數(shù)之后還存活的對(duì)象會(huì)放入老生代。新生代還有 3 個(gè)區(qū)域:一個(gè) Endn + 兩個(gè) Survivor(S0/S1)。

垃圾回收的時(shí)候會(huì)將 Endn 中存活的對(duì)象放到一個(gè)未使用的 Survivor 中,并把當(dāng)前的 Endn 和正在使用的 Survivor 清楚掉。

2.2 Java虛擬機(jī)棧(線程私有)

Java 虛擬機(jī)棧的作用:Java 虛擬機(jī)棧的生命周期和線程相同,Java 虛擬機(jī)棧描述的是 Java 方法執(zhí)行的內(nèi)存模型:每個(gè)方法在執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀(Stack Frame)用于存儲(chǔ)局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息。常說(shuō)的堆內(nèi)存、棧內(nèi)存中,棧內(nèi)存指的就是虛擬機(jī)棧。 Java 虛擬機(jī)棧中包含了以下 4 部分:

  1. 局部變量表: 存放了編譯器可知的各種基本數(shù)據(jù)類型(8大基本數(shù)據(jù)類型)、對(duì)象引用。局部變量表所需的內(nèi)存空間在編譯期間完成分配,當(dāng)進(jìn)入一個(gè)方法時(shí),這個(gè)方法需要在幀中分配多大的局部變量空間是完全確定的,在執(zhí)行期間不會(huì)改變局部變量表大小。簡(jiǎn)單來(lái)說(shuō)就是存放方法參數(shù)和局部變量。
  2. 操作棧:每個(gè)方法會(huì)生成一個(gè)先進(jìn)后出的操作棧。
  3. 動(dòng)態(tài)鏈接:指向運(yùn)行時(shí)常量池的方法引用。
  4. 方法返回地址:PC 寄存器的地址。

什么是線程私有?

由于JVM的多線程是通過(guò)線程輪流切換并分配處理器執(zhí)行時(shí)間的方式來(lái)實(shí)現(xiàn),因此在任何一個(gè)確定的時(shí)刻,一個(gè)處理器(多核處理器則指的是一個(gè)內(nèi)核)都只會(huì)執(zhí)行一條線程中的指令。因此為了切換線程后能恢復(fù)到正確的執(zhí)行位置,每條線程都需要獨(dú)立的程序計(jì)數(shù)器,各條線程之間計(jì)數(shù)器互不影響,獨(dú)立存儲(chǔ)。我們就把類似這類區(qū)域稱之為"線程私有"的內(nèi)存。

2.3 本地方法棧(線程私有)

本地方法棧和虛擬機(jī)棧類似,只不過(guò) Java 虛擬機(jī)棧是給 JVM 使用的,而本地方法棧是給本地方法使用的。

2.4 程序計(jì)數(shù)器(線程私有)

程序計(jì)數(shù)器的作用:用來(lái)記錄當(dāng)前線程執(zhí)行的行號(hào)的。

程序計(jì)數(shù)器是一塊比較小的內(nèi)存空間,可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。 如果當(dāng)前線程正在執(zhí)行的是一個(gè)Java方法,此計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址;如果正在執(zhí)行的是一個(gè)Native方法,這個(gè)計(jì)數(shù)器值為空。

程序計(jì)數(shù)器內(nèi)存區(qū)域是唯一一個(gè)在JVM規(guī)范中沒(méi)有規(guī)定任何OOM情況的區(qū)域!

2.5 方法區(qū)(線程共享)

方法區(qū)的作用:用來(lái)存儲(chǔ)被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)的。

在《Java虛擬機(jī)規(guī)范中》把此區(qū)域稱之為“方法區(qū)”,而在 HotSpot 虛擬機(jī)的實(shí)現(xiàn)中,在 JDK 7 時(shí)此區(qū)域叫做永久代(PermGen),JDK 8 中叫做元空間(Metaspace)。

JDK 1.8 元空間的變化:

  • 對(duì)于 HotSpot 來(lái)說(shuō),JDK 8 元空間的內(nèi)存屬于本地內(nèi)存,這樣元空間的大小就不在受 JVM 最大內(nèi)存的參數(shù)影響了,而是與本地內(nèi)存的大小有關(guān)。
  • JDK 8 中將字符串常量池移動(dòng)到了堆中。

2.6 運(yùn)行時(shí)常量池

運(yùn)行時(shí)常量池是方法區(qū)的一部分,存放字面量與符號(hào)引用。

  • 字面量 : 字符串(JDK 8 移動(dòng)到堆中) 、final常量、基本數(shù)據(jù)類型的值。
  • 符號(hào)引用 : 類和結(jié)構(gòu)的完全限定名、字段的名稱和描述符、方法的名稱和描述符。

三、內(nèi)存布局中的異常問(wèn)題

3.1 Java堆溢出

Java堆用于存儲(chǔ)對(duì)象實(shí)例,只要不斷的創(chuàng)建對(duì)象,并且保證GC Roots到對(duì)象之間有可達(dá)路徑來(lái)避免來(lái) GC 清除這些對(duì)象,那么在對(duì)象數(shù)量達(dá)到最大堆容量后就會(huì)產(chǎn)生內(nèi)存溢出異常。

Java堆內(nèi)存的OOM異常是實(shí)際應(yīng)用中最常見的內(nèi)存溢出情況。當(dāng)出現(xiàn)Java堆內(nèi)存溢出時(shí),異常堆棧信息"java.lang.OutOfMemoryError"會(huì)進(jìn)一步提示"Java heap space"。當(dāng)出現(xiàn)"Java heap space"則很明確的告知我們,OOM發(fā)生在堆上。

此時(shí)要對(duì)Dump出來(lái)的文件進(jìn)行分析,以MAT為例。分析問(wèn)題的產(chǎn)生到底是出現(xiàn)了內(nèi)存泄漏(Memory Leak)還是內(nèi)存溢出(Memory Overflow)

  • 內(nèi)存泄漏 : 泄漏對(duì)象無(wú)法被GC。
  • 內(nèi)存溢出 : 內(nèi)存對(duì)象確實(shí)還應(yīng)該存活。此時(shí)要根據(jù)JVM堆參數(shù)與物理內(nèi)存相比較檢查是否還應(yīng)該把JVM 堆內(nèi)存調(diào)大;或者檢查對(duì)象的生命周期是否過(guò)長(zhǎng)。

3.2 虛擬機(jī)棧和本地方法棧溢出

由于HotSpot虛擬機(jī)將虛擬機(jī)棧與本地方法棧合二為一,因此對(duì)于HotSpot來(lái)說(shuō),棧容量只需要由-Xss參數(shù)來(lái)設(shè)置。

關(guān)于虛擬機(jī)棧會(huì)產(chǎn)生的兩種異常:

  • 如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的最大深度,會(huì)拋出StackOverFlow異常。
  • 如果虛擬機(jī)在拓展棧時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存空間,則會(huì)拋出OOM異常。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 一文搞懂Java并發(fā)AQS的共享鎖模式

    一文搞懂Java并發(fā)AQS的共享鎖模式

    這篇文章主要為大家闡述AQS另外一個(gè)重要模式,共享鎖模式。共享鎖可以由多個(gè)線程同時(shí)獲取,?比較典型的就是讀鎖,感興趣的小伙伴可以了解一下
    2022-10-10
  • 使用maven打包/跳過(guò)某個(gè)modules

    使用maven打包/跳過(guò)某個(gè)modules

    本文總結(jié)了在Maven項(xiàng)目中跳過(guò)或單獨(dú)構(gòu)建模塊的方法,包括使用`-pl`、`-am`和`-amd`參數(shù)來(lái)選擇性地執(zhí)行模塊構(gòu)建,以及通過(guò)`-Dmaven.test.skip`跳過(guò)測(cè)試,以提高構(gòu)建效率
    2024-12-12
  • Required?request?body?is?missing的問(wèn)題及解決

    Required?request?body?is?missing的問(wèn)題及解決

    這篇文章主要介紹了Required?request?body?is?missing的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 緩存工具類ACache使用方法詳解

    緩存工具類ACache使用方法詳解

    這篇文章主要為大家詳細(xì)介紹了緩存工具類ACache的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • maven配置阿里倉(cāng)庫(kù)的方法步驟

    maven配置阿里倉(cāng)庫(kù)的方法步驟

    這篇文章主要介紹了maven配置阿里倉(cāng)庫(kù)的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • spring Mvc配置xml使ResponseBody返回Json的方法示例

    spring Mvc配置xml使ResponseBody返回Json的方法示例

    這篇文章主要給大家介紹了關(guān)于spring Mvc配置xml使ResponseBody返回Json的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-04-04
  • 詳解使用IntelliJ IDEA新建Java Web后端resfulAPI模板

    詳解使用IntelliJ IDEA新建Java Web后端resfulAPI模板

    這篇文章主要介紹了詳解使用IntelliJ IDEA新建Java Web后端resfulAPI模板,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Java調(diào)用Oss JDk實(shí)現(xiàn)刪除指定目錄下的所有文件

    Java調(diào)用Oss JDk實(shí)現(xiàn)刪除指定目錄下的所有文件

    這篇文章主要為大家詳細(xì)介紹了Java如何調(diào)用Oss JDk實(shí)現(xiàn)刪除指定目錄下的所有文件功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2025-03-03
  • Java 停止線程需要注意的地方

    Java 停止線程需要注意的地方

    這篇文章主要介紹了Java 停止線程需要注意的地方,幫助大家更好的理解和學(xué)習(xí)Java線程的相關(guān)資料,感興趣的朋友可以了解下
    2020-09-09
  • Mybatis不支持batchInsertOrUpdate返顯id問(wèn)題

    Mybatis不支持batchInsertOrUpdate返顯id問(wèn)題

    這篇文章主要介紹了Mybatis不支持batchInsertOrUpdate返顯id問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05

最新評(píng)論