哈哈哈哈哈操欧洲电影,久草网在线,亚洲久久熟女熟妇视频,麻豆精品色,久久福利在线视频,日韩中文字幕的,淫乱毛视频一区,亚洲成人一二三,中文人妻日韩精品电影

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

探討JVM的內(nèi)存布局

Android編程精選 ? 來源:博客園 ? 作者:追風少年瀟歌 ? 2022-09-09 15:57 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

內(nèi)存布局

JVM內(nèi)存布局規(guī)定了Java在運行過程中內(nèi)存申請、分配、管理的策略,保證了JVM的穩(wěn)定高效運行。不同的JVM對于內(nèi)存的劃分方式和管理機制存在部分差異。結(jié)合JVM虛擬機規(guī)范,一起來探討jVM的內(nèi)存布局。如下圖所示:

9777d98a-2424-11ed-ba43-dac502259ad0.png

Heap 堆區(qū)

Heap堆區(qū)是Java發(fā)生OOM(Out Of Memory)故障的地方,堆中存儲著我們平時創(chuàng)建的實例對象,最終這些不再使用的對象會被垃圾收集器回收掉,而且堆是線程共享的。一般情況下,堆所占用的內(nèi)存空間是JVM內(nèi)存區(qū)域中最大的,我們在平時編碼中,創(chuàng)建對象如果不加以克制,內(nèi)存空間也會被耗盡。

堆的內(nèi)存空間是可以自定義大小的,同時也支持在運行時動態(tài)修改,通過 -Xms 、-Xmx 這兩參數(shù)去改變堆的初始值和最大值。-X指的是JVM運行參數(shù),ms 是memory start的簡稱,代表的是最小堆容量,mx是memory max的簡稱,代表的是最大堆容量;如 -Xms256M代表堆的初始值是256M,-Xmx1024M代表堆的最大值是1024M。

由于堆的內(nèi)存空間是可以動態(tài)調(diào)整的,所以在服務器運行的時候,請求流量的不確定性可能會導致我們堆的內(nèi)存空間不斷調(diào)整,會增加服務器的壓力,所以我們一般都會將JVM的Xms和Xmx的值設置成一樣,同樣也為了避免在GC(垃圾回收)之后調(diào)整堆大小時帶來的額外壓力。

堆區(qū)分為兩大區(qū):Young區(qū)和Old區(qū),又稱新生代和老年代。對象剛創(chuàng)建的時候,會被創(chuàng)建在新生代,到一定階段之后會移送至老年代,如果創(chuàng)建了一個新生代無法容納的新對象,那么這個新對象也可以創(chuàng)建到老年代。如上圖所示。

新生代分為1個Eden區(qū)和2個S區(qū),S代表Survivor。大部分的對象會在Eden區(qū)中生成,當Eden區(qū)沒有足夠的空間容納新對象時,會觸發(fā)Young Garbage Collection,即YGC。在Eden區(qū)進行垃圾清除時,它的策略是會把沒有引用的對象直接給回收掉,還有引用的對象會被移送到Survivor區(qū)。

Survivor區(qū)有S0和S1兩個內(nèi)存空間,每次進行YGC的時候,會將存活的對象復制到未使用的那塊內(nèi)存空間,然后將當前正在使用的空間完全清除掉,再交換兩個空間的使用狀況。如果YGC要移送的對象Survivor區(qū)無法容納,那么就會將該對象直接移交給老年代。

上面說了,到一定階段的對象會移送到老年區(qū),這是什么意思呢?每一個對象都有一個計數(shù)器,當每次進行YGC的時候,都會 +1。通過-XX:MAXTenuringThrehold參數(shù)可以配置當計數(shù)器的值到達某個閾值時,對象就會從新生代移送至老年代。

該參數(shù)的默認值為15,也就是說對象在Survivor區(qū)中的S0和S1內(nèi)存空間交換的次數(shù)累加到15次之后,就會移送至老年代。如果參數(shù)配置為1,那么創(chuàng)建的對象就會直接移送至老年代。具體的對象分配即回收流程可觀看下圖所示。

978e5d4a-2424-11ed-ba43-dac502259ad0.png

如果Survivor區(qū)無法放下,或者創(chuàng)建了一個超大新對象,Eden和Old區(qū)都無法存放,就會觸發(fā)Full Garbage Collection,即FGG,便再嘗試放在Old區(qū),如果還是容納不了,就會拋出OOM異常。在不同的JVM實現(xiàn)及不同的回收機制中,堆內(nèi)存的劃分方式是不一樣的。

Metaspace 元空間

在JDK8版本中,元空間的前身Pern區(qū)已經(jīng)被淘汰。在JDK7及之前的版本中,Hotspot還有Pern區(qū),翻譯為永久代,在啟動時就已經(jīng)確定了大小,難以進行調(diào)優(yōu),并且只有FGC時會移動類元信息。不同于之前版本的Pern(永久代),JDK8的元空間已經(jīng)在本地內(nèi)存中進行分配,并且,Pern區(qū)中的所有內(nèi)容中字符串常量移至堆內(nèi)存,其他內(nèi)容也包括了類元信息、字段、靜態(tài)屬性、方法、常量等等都移至元空間內(nèi)。

JVM Stacks 虛擬機棧

棧(Stack)是一個先進后出的數(shù)據(jù)結(jié)構(gòu),先進后出怎么理解?類似于我們平時打羽毛球時,裝羽毛球的球筒,第一個先放進去的往往最后一個才能拿出來,最后放進去的一個最先拿出來。

相對于基于寄存器的運行環(huán)境來說,JVM是基于棧結(jié)構(gòu)的運行環(huán)境。因為棧結(jié)構(gòu)移植性更好,可控性更強。JVM的虛擬機棧是描述Java方法執(zhí)行的內(nèi)存區(qū)域,并且是線程私有的。棧中的元素用于支持虛擬機進行方法調(diào)用,每個方法從開始調(diào)用到執(zhí)行完成的過程,就是棧幀從入幀到出幀的過程。

在活動線程中,只有位于棧頂?shù)膸攀怯行У?,稱為當前棧幀。正在執(zhí)行的方法稱為當前方法,棧幀是方法運行的基本結(jié)構(gòu)。在執(zhí)行引擎運行時,所有指令都只能針對當前棧幀進行操作。而StackOverflowError表示請求的棧溢出,導致內(nèi)存耗盡,通常出現(xiàn)在遞歸方法中。如果把JVM當做一個棋盤,虛擬機棧就是棋盤上的將/帥,當前方法的棧幀就是棋子能走的區(qū)域,而操作棧就是每一個棋子。操作棧的壓棧和出棧如下圖所示:

979ecef0-2424-11ed-ba43-dac502259ad0.png

虛擬機棧通過壓棧和出棧的方式,對每個方法對應的活動棧幀進行運算處理,方法正常執(zhí)行結(jié)束,肯定會跳轉(zhuǎn)到另外一個棧幀上。在執(zhí)行的過程中,如果出現(xiàn)異常,會進行異?;厮?,返回地址通過異常處理表確定。棧幀在整個JVM體系中的地位頗高,包括局部變量表、操作棧、動態(tài)連接、方法返回地址等。

下面對棧幀的各個活動棧幀進行簡要的分析

(1)局部變量表

局部變量表是存放方法參數(shù)和局部變量的區(qū)域。我們都知道,類屬性變量一共要經(jīng)歷兩個階段,分為準備階段和初始化階段,而局部變量是沒有準備階段,只有初始化階段,而且必須是顯示的。如果是非靜態(tài)方法,則在index[0]位置上存儲的是方法所屬對象的實例引用,隨后存儲的是參數(shù)和局部變量。字節(jié)碼指令中的STORE指令就是將操作棧中計算完成的局部變量寫回局部變量表的存儲空間內(nèi)。

(2)操作棧

操作棧是一個初始狀態(tài)為空的桶式結(jié)構(gòu)棧。在方法執(zhí)行過程中,會有各種指令往棧中寫入和提取信息。JVM的執(zhí)行引擎是基于棧的執(zhí)行引擎,其中的棧指的就是操作棧。字節(jié)碼指令集的定義都是基于棧類型的,棧的深度在方法元信息的stack屬性中,下面就通過一個例子來說明下操作棧與局部變量表的交互:

publicintadd(){
intx=10;
inty=20;
intz=x+y;

returnz;
}

字節(jié)碼操作順序如下:

publicintadd();
Code:
0:bipush10//常量10壓入操作棧
2:istore_1//并保存到局部變量表的slot_1中(第1處)
3:bipush20//常量20壓入操作棧
5:istore_2//并保存到局部變量表的slot_2中
6:iload_1//把局部變量表的slot_1元素(intx)壓入操作棧
7:iload_2//把局部變量表的slot_2元素(inty)壓入操作棧
8:iadd//把上方的兩個數(shù)都取出來,在CPU里加一下,并壓回操作棧的棧頂
9:istore_3//把棧頂?shù)慕Y(jié)果存儲到局部變量表的slot_3中
10:iload_3
11:ireturn//返回棧頂元素值

第 1 處說明:局部變量表就像一個快遞柜,有著很多的柜子,依次編號為1,2,3,...,n,字節(jié)碼指令 istore_1 就代表打開了 1 號柜子,再把棧頂中的值 10 存進去。棧就好如一個桶,任何時候只能對桶口的元素進行操作,所以數(shù)據(jù)只能在棧頂進行存取。部分指令可以直接在柜子里面直接進行,比如 iinc指令,直接對抽屜里的數(shù)值進行 +1操作。我們經(jīng)常遇到的 i++ 和 ++i,通過字節(jié)碼對比起來,答案一下子就一目了然了。如下表格所示:

97af836c-2424-11ed-ba43-dac502259ad0.jpg


左列中,iload_1 從局部變量表的第1號柜子取出一個數(shù),壓入棧頂,下一步直接在柜子里實現(xiàn) + 1的操作,而這個操作時對棧頂元素的值沒有任何影響,所以 istore_2 只是把棧頂元素賦值給 a,而右列,它是先在柜子里面進行 +1的操作,然后再通過 iload_1 把第1號柜子里的數(shù)壓入棧頂,所以istore_2賦給a的值是 +1 之后的值。擴展下,i++ 并非是原子操作。即使通過volatile關(guān)鍵字來修飾,多線程情況下,還是會出現(xiàn)數(shù)據(jù)互相覆蓋的情況。

(3)動態(tài)連接

每個棧幀中包含一個在常量池中對當前方法的引用,目的是支持方法調(diào)用過程的動態(tài)連接。

(4)方法返回地址

方法執(zhí)行時有兩種退出情況:第一,正常退出,即正常執(zhí)行到任何方法的返回字節(jié)碼指令,如 RETURN、IRETURN、ARETURN等;第二,異常退出。無論何種退出情況,都將返回方法當前被調(diào)用的位置。方法退出的過程相當于彈出當前棧幀,而退出可能有三種方式:

返回值壓入上層調(diào)用棧幀。

異常信息拋給能夠處理的棧幀。

PC 計數(shù)器指向方法調(diào)用后的下一條指令。

Native Method Stacks(本地方法棧)

本地方法棧(Native Method Stack)在JVM內(nèi)存布局中,也是線程對象私有的,但是虛擬機?!爸鲀?nèi)”,而本地方法?!爸魍狻?。這個“內(nèi)外”是針對JVM來說的,本地方法棧為Native方法服務。線程開始調(diào)用本地方法時,會進入一個不再受JVM約束的世界。本地方法可以通過JVNI(Java Native Interface)來訪問虛擬機運行時的數(shù)據(jù)區(qū),甚至可以調(diào)用寄存器,具有和JVM相同的能力和權(quán)限。當大量本地方法出現(xiàn)時,勢必會削弱JVM對系統(tǒng)的控制力,因為它的出錯信息都比較黑盒,難以捉摸。對于內(nèi)存不足的情況,本地方法棧還是會拋出 native heap OutOfMemory。

重點說下JNI類本地方法,最常用的本地方法應該是System.currentTimeMills(),JNI使Java深度使用操作系統(tǒng)的特性功能,復用非Java代碼。但是在項目過程中,如果大量使用其他語言來實現(xiàn)JNI,就會喪失跨平臺特性,威脅到程序運行的穩(wěn)定性。假如需要與本地代碼交互,就可以用中間標準框架來進行解耦,這樣即使本地方法崩潰也不至于影響到JVM的穩(wěn)定。

Program Counter Register (程序計數(shù)寄存器)

在程序計數(shù)寄存器(Program Counter Register,PC)中,Register的命名源于CPU的寄存器,CPU只有把數(shù)據(jù)裝載到寄存器才能夠運行。寄存器存儲指令相關(guān)的現(xiàn)場信息,由于CPU時間片輪限制,眾多線程在并發(fā)執(zhí)行過程中,任何一個確定的時刻,一個處理器或者多核處理器中的一個內(nèi)核,只會執(zhí)行某個線程中的一個指令。

這樣必然會導致經(jīng)常中斷或恢復,如何才能保證分毫無差呢?每個線程在創(chuàng)建之后,都會產(chǎn)生自己的程序計數(shù)器和棧幀,程序計數(shù)器用來存放執(zhí)行指令的偏移量和行號指示器等,線程執(zhí)行或恢復都要依賴程序計數(shù)器。程序計數(shù)器在各個線程之間互不影響,此區(qū)域也不會發(fā)生內(nèi)存溢出異常。

小結(jié)

最后,從線程的角度來看,堆和元空間是所有線程共享的,而虛擬機棧、本地方法棧、程序計數(shù)器是線程內(nèi)部私有的,我們以線程的角度再來看看Java的內(nèi)存結(jié)構(gòu)圖:

97bb8fae-2424-11ed-ba43-dac502259ad0.png





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 計數(shù)器
    +關(guān)注

    關(guān)注

    32

    文章

    2320

    瀏覽量

    98504
  • JVM
    JVM
    +關(guān)注

    關(guān)注

    0

    文章

    161

    瀏覽量

    13084
  • 虛擬機
    +關(guān)注

    關(guān)注

    1

    文章

    973

    瀏覽量

    30683

原文標題:圖文并茂:JVM 內(nèi)存布局詳解

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    LuatOS的內(nèi)存分配機制

    不同 LuatOS 硬件平臺在內(nèi)存布局上存在差異,Lua 運行內(nèi)存、系統(tǒng)內(nèi)存與 PSRAM 擴展內(nèi)存的分配方式各有區(qū)別。部分型號將系統(tǒng)與腳本
    的頭像 發(fā)表于 04-16 12:37 ?53次閱讀
    LuatOS的<b class='flag-5'>內(nèi)存</b>分配機制

    DDR5內(nèi)存斷崖式下跌或引發(fā)踩踏式拋貨?

    內(nèi)存
    芯廣場
    發(fā)布于 :2026年03月30日 15:35:23

    MangoTree Halo Ultra「全新PXI」,標配自動糾錯內(nèi)存#

    內(nèi)存
    芒果樹數(shù)字
    發(fā)布于 :2026年03月06日 15:59:34

    深入探討PCB布局布線的專業(yè)設計要點與常見挑戰(zhàn)

    本文深入探討PCB布局布線的專業(yè)設計要點與常見挑戰(zhàn),并介紹上海創(chuàng)馨科技如何憑借資深團隊與豐富經(jīng)驗,為客戶提供從精密布局、優(yōu)化布線到生產(chǎn)制造的一站式高可靠性PCB解決方案。
    的頭像 發(fā)表于 01-04 15:29 ?389次閱讀

    rk基于linux/android內(nèi)存管理

    。內(nèi)存整體使用布局如下,以 ARM64 為例(常規(guī)情況): ? ? 上表中的 Start Addr Offset 一欄表示基于 DDR base 的地址偏移; Fastboot 地址和大小由
    的頭像 發(fā)表于 12-15 10:42 ?278次閱讀
    rk基于linux/android<b class='flag-5'>內(nèi)存</b>管理

    華邦電子重新定義AI內(nèi)存:為新一代運算打造高帶寬、低延遲解決方案

    本文將探討內(nèi)存技術(shù)的最新突破、AI 應用日益增長的影響力,以及華邦如何透過策略性布局響應市場不斷變化的需求。
    的頭像 發(fā)表于 08-28 11:17 ?4669次閱讀
    華邦電子重新定義AI<b class='flag-5'>內(nèi)存</b>:為新一代運算打造高帶寬、低延遲解決方案

    圖解環(huán)路設計及控制技術(shù)探討

    由于之前缺乏控制理論方面的知識在剛接觸反饋環(huán)路的時候?qū)ζ渲械暮芏嗝~不是很明白,這次準備采用圖解的方法逐一的搞清楚這些名詞并且試圖找出一種便捷的設置零、極點的方法。最后準備再探討一下關(guān)于控制技術(shù)
    發(fā)表于 08-22 17:39

    網(wǎng)格布局介紹

    概述 網(wǎng)格布局是由“行”和“列”分割的單元格所組成,通過指定“項目”所在的單元格做出各種各樣的布局。網(wǎng)格布局具有較強的頁面均分能力,子組件占比控制能力,是一種重要自適應布局,其使用場
    發(fā)表于 06-25 06:27

    HarmonyOS NEXT應用元服務布局合理使用布局組件

    選擇合適的布局組件 在布局時,子組件會根據(jù)父組件的布局算法得到相應的排列規(guī)則,然后按照規(guī)則進行子組件位置的擺放。不同的布局容器使用的布局算法
    發(fā)表于 06-20 15:48

    奧托立夫深度探討汽車行業(yè)全球化戰(zhàn)略布局

    供應鏈副總裁劉永杰、及華懋科技董事長吳黎明等行業(yè)專家,進行了 “從本土到全球,端到端的韌性布局” 主題的圓桌論壇,本次論壇由軒轅同學校長 世界新汽車技術(shù)合作生態(tài)協(xié)會理事長賈可博士主持,現(xiàn)場嘉賓就中國汽車產(chǎn)業(yè)全球化布局、供應鏈韌性構(gòu)建及供應鏈合作伙伴協(xié)同模式展開深度
    的頭像 發(fā)表于 05-06 10:47 ?975次閱讀

    基于 IAR Embedded Workbench 的自研 MCU 芯片軟件函數(shù)與變量內(nèi)存布局優(yōu)化精控方法

    在嵌入式軟件開發(fā)領域,MCU芯片軟件的架構(gòu)設計與內(nèi)存布局的精細規(guī)劃對系統(tǒng)性能和穩(wěn)定性起著關(guān)鍵作用。本文檔聚焦于IAR Embedded Workbench環(huán)境下,為自研MCU芯片軟件提供了一套詳盡
    的頭像 發(fā)表于 04-30 16:38 ?857次閱讀
    基于 IAR Embedded Workbench 的自研 MCU 芯片軟件函數(shù)與變量<b class='flag-5'>內(nèi)存</b><b class='flag-5'>布局</b>優(yōu)化精控方法

    模擬地和數(shù)字地混合PCB布局探討

    這是我的產(chǎn)品目前的電路拓撲,有一些疑問想跟大佬們共同探討一下。 圖1,模擬地和數(shù)字地分開,在電源入口處相連,紅色是模擬地的連接示意,綠色為數(shù)字電流的返回路徑。此方案感覺不妥當?shù)氖菙?shù)字電流的返回
    發(fā)表于 04-29 22:35

    電機繞組滾動烘干爐防爆安全技術(shù)探討

    電機繞組滾動烘干工藝在電機行業(yè)中逐步推廣應用,但該防爆滾動烘干設備的制造卻仍沒有統(tǒng)一的標準,這就為設備的制造、使用、維修、保養(yǎng)埋下了隱患。文章主要探討了防爆滾動烘干爐的防爆技術(shù),以期引起同行對防爆
    發(fā)表于 04-27 19:28
    天门市| 宝山区| 东辽县| 克山县| 枣强县| 蒲城县| 苍溪县| 都昌县| 抚顺县| 商洛市| 龙门县| 土默特左旗| 河池市| 肥西县| 读书| 岳阳市| 通辽市| 定日县| 高青县| 涿鹿县| 隆回县| 巍山| 内黄县| 曲沃县| 罗定市| 汉沽区| 崇阳县| 神木县| 盐城市| 揭东县| 彰化县| 义乌市| 武宣县| 阿拉尔市| 茌平县| 姚安县| 林西县| 莆田市| 甘洛县| 道真| 鸡西市|