溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

jvm內(nèi)存結(jié)構(gòu)的原理及應(yīng)用

發(fā)布時(shí)間:2021-06-23 13:43:07 來源:億速云 閱讀:158 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要講解了“jvm內(nèi)存結(jié)構(gòu)的原理及應(yīng)用”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“jvm內(nèi)存結(jié)構(gòu)的原理及應(yīng)用”吧!

jvm內(nèi)存結(jié)構(gòu)概述

jvm內(nèi)存結(jié)構(gòu)的原理及應(yīng)用
??jvm內(nèi)存結(jié)構(gòu)主要包括:方法區(qū)、堆、虛擬機(jī)棧、本地方法棧、程序計(jì)數(shù)器等五大部分, 下面我們來具體看一下每一個(gè)部分。

1.1 虛擬機(jī)棧

  • 作用:
    虛擬機(jī)棧描述的是java方法執(zhí)行的動(dòng)態(tài)內(nèi)存模型,通過進(jìn)棧、出棧來實(shí)現(xiàn)方法的調(diào)用結(jié)構(gòu)。

  • 分析:
    ??棧結(jié)構(gòu)的特點(diǎn)是后進(jìn)先出,方法調(diào)用的過程也是后調(diào)用的方法返回結(jié)果后,先調(diào)用的方法再接著執(zhí)行,你是干柴,我是烈火。你是魚兒,我是小河。(此處不知道是蛋孵化了雞,還是雞生出了蛋)

??以methodA調(diào)用methodB為例,來看一下方法棧的執(zhí)行過程 jvm內(nèi)存結(jié)構(gòu)的原理及應(yīng)用
首先是主方法進(jìn)入空棧(圖中免去了這一步),主方法中調(diào)用methodA --》 methodA入棧 --》 methodA調(diào)用methodB --》 methodB入棧 --》 methodB執(zhí)行完畢,出棧并返回返回值 --》 methodA執(zhí)行完畢,出棧并返回返回值 --》主線程執(zhí)行完畢并出棧(圖中免去了這一步)--》程序執(zhí)行完畢。
??那么methodA、methodB中到底包含了哪些內(nèi)容呢?
??我們不如從方法定義的角度來思考一下,編寫程序時(shí),里面經(jīng)常出現(xiàn)的幾個(gè)要素?zé)o外乎:變量、控制結(jié)構(gòu)(循環(huán)、分支)、函數(shù)調(diào)用(也可以叫方法),函數(shù)其實(shí)就是用一定的控制結(jié)構(gòu)來操作變量,中間穿插著其他函數(shù)的調(diào)用,分支結(jié)構(gòu)主要控制的是程序執(zhí)行到哪一行,這個(gè)由我們后面1.5章節(jié)要講到的程序計(jì)數(shù)器來實(shí)現(xiàn),函數(shù)調(diào)用層次如上面所說由虛擬機(jī)棧來支持,而變量以及方法的出口就是methodA、methodB中的主要內(nèi)容。
??methodA、methodB在虛擬機(jī)棧中叫做棧幀,棧幀中包括變量(局部變量表-基本類型、對象引用-對象內(nèi)存地址等)以及返回值地址等信息,可以看出棧幀中包含的內(nèi)容是編譯器就可確定大小的,當(dāng)進(jìn)入一個(gè)方法時(shí),需要分配多大的局部變量空間是完全確定的,在運(yùn)行期中不會(huì)改變局部變量表的大小。

  • 此區(qū)域可能出現(xiàn)的異常:
    棧是有深度的,方法調(diào)用層次超過棧的深度,就會(huì)出現(xiàn)StackoverflowError,一般是遞歸調(diào)用時(shí),基線條件不合理時(shí),容易出現(xiàn)此問題。
    當(dāng)棧的深度增大時(shí),所需要的局部變量表空間也隨之增長,當(dāng)超過一定界限時(shí),會(huì)出現(xiàn)OutOfMemoryError異常。

1.2 本地方法棧

  • 作用:
    本地方法棧與虛擬機(jī)棧的區(qū)別是調(diào)用的是不同類型的方法,本地方法棧用于記錄native方法的調(diào)用,本地方法棧中未對native方法實(shí)現(xiàn)語言、數(shù)據(jù)結(jié)構(gòu)等做強(qiáng)制規(guī)定,主要由虛擬機(jī)自己定義并實(shí)現(xiàn)。

  • 注:
    由于本地方法棧和虛擬機(jī)棧的作用非常相似,因此部分虛擬機(jī)的實(shí)現(xiàn)中,就將這兩塊區(qū)域合并成了一個(gè)區(qū)域,例如比較常用的Hotspot。

  • 此區(qū)域可能出現(xiàn)的異常
    與虛擬機(jī)棧相同,此區(qū)域也有可能出現(xiàn)StackoverflowError或OutOfMemoryError。

1.3 堆

  • 作用:
    堆是jvm是管理的內(nèi)存中最大的一塊,此區(qū)域只有一個(gè)作用就是存放對象實(shí)例。(java是面向?qū)ο笳Z言--》堆用于存放對象實(shí)例 --》堆占用空間最大,嗯,沒毛病鐵子。)

  • 注 :
    由于此區(qū)域占用內(nèi)存空間最大,而且對象的創(chuàng)建與銷毀是比較頻繁的,那內(nèi)存空間不夠用了怎么辦?跟殺豬挑最肥的宰是一個(gè)道理,此區(qū)域是垃圾回收的主要區(qū)域。java為我們省去了代碼層手動(dòng)釋放內(nèi)存的工作,通過垃圾回收器來實(shí)現(xiàn)自動(dòng)化的內(nèi)存回收(《7天精通java》:《21天c++從入門到入土》,知道自動(dòng)垃圾回收的重要性了吧)

  • 此區(qū)域可能出現(xiàn)的異常:
    為對象分配空間時(shí),內(nèi)存不足,會(huì)出現(xiàn)OutOfMemoryError(敲黑板)。
    對應(yīng)的排查策略:配置參數(shù)-XX:+HeapDumpOnOutOfMemoryError,這樣虛擬機(jī)在出現(xiàn)此異常時(shí),會(huì)生成內(nèi)存堆存儲(chǔ)快照,使用工具Eclipse Memory Analyzer或jprofiler,可以分析某些對象占用空間百分比,快速定位到問題,如果代碼存在問題,例如不停的創(chuàng)建某些對象,但并不釋放,那就要通過修改代碼來解決問題,如果代碼不存在問題,就需要通過加大物理內(nèi)存,調(diào)整jvm堆參數(shù)來增加堆大小。(-Xms 堆初始化大小,-Xms 對空間最大大小,實(shí)際配置過程中,一般設(shè)置成一樣的大小,避免出現(xiàn)內(nèi)存抖動(dòng),影響穩(wěn)定性)

1.4 方法區(qū)

  • 作用:
    方法區(qū)主要用于存取類信息、常量、靜態(tài)變量、運(yùn)行時(shí)常量池等。

  • 分析:
    運(yùn)行時(shí)常量池用于存取字面量和符號引用,當(dāng)使用雙引號聲明String變量時(shí),此變量并不是開辟到堆空間當(dāng)中,而是開辟到方法區(qū)中的運(yùn)行時(shí)常量池中的,運(yùn)行時(shí)常量池不僅可以在編譯期產(chǎn)生,也可以在程序運(yùn)行期間,動(dòng)態(tài)產(chǎn)生,例如String中的intern方法,就是在程序運(yùn)行狀態(tài)中將字符串值放到運(yùn)行時(shí)常量池中的。

  • 此區(qū)域可能出現(xiàn)的異常:
    此區(qū)域在內(nèi)存不足時(shí),也會(huì)出現(xiàn)OutOfMemoryError異常。

1.5 程序計(jì)數(shù)器

  • 作用:
    程序計(jì)數(shù)器主要是用于記錄當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器,即當(dāng)前線程執(zhí)行到了哪一行,由于功能比較簡單,所以與其他幾個(gè)區(qū)域相比,內(nèi)存空間占用的非常小。

  • 此區(qū)域可能出現(xiàn)的異常:
    程序計(jì)數(shù)器的作用決定了在此區(qū)域中不會(huì)出現(xiàn)由程序本身導(dǎo)致的異常,如果此處出現(xiàn)異常,是jvm本身的設(shè)計(jì)缺陷。

  • 注:
    如果線程執(zhí)行的是java方法,計(jì)數(shù)器對應(yīng)的是字節(jié)碼指令的地址,但是如果是native方法,底層是非java實(shí)現(xiàn)的,此時(shí)計(jì)數(shù)器對應(yīng)的值是undefined

  • 引申:
    說到了程序計(jì)數(shù)器,在部分編程語言中,是支持goto關(guān)鍵字的,goto可以讓程序直接跳轉(zhuǎn)到指定行,java是不支持goto的,但是把goto作為了保留字,即java不支持此種語法,但是也不讓開發(fā)者去定義為變量,防止后續(xù)java發(fā)展過程中,加入goto關(guān)鍵字后,導(dǎo)致部分程序運(yùn)行異常。

1.6 線程共享區(qū)與線程獨(dú)占區(qū)

??上面五個(gè)區(qū)域中,方法區(qū)和堆是線程共享的區(qū)域,這兩個(gè)區(qū)域中放置的內(nèi)容是與線程無關(guān)的,任意一個(gè)線程都可能會(huì)訪問到這兩塊區(qū)域中的內(nèi)容。
??對于每個(gè)線程來說,它的調(diào)用方法棧應(yīng)該是獨(dú)屬于某個(gè)線程的,如果多個(gè)線程共用一個(gè)方法棧那程序的執(zhí)行順序是無法得到保障的,線程執(zhí)行到哪一行應(yīng)該也是唯一的,因此方法棧、程序計(jì)數(shù)器是線程獨(dú)占的。

感謝各位的閱讀,以上就是“jvm內(nèi)存結(jié)構(gòu)的原理及應(yīng)用”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對jvm內(nèi)存結(jié)構(gòu)的原理及應(yīng)用這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

jvm
AI