您好,登錄后才能下訂單哦!
這篇文章主要講解了“jvm內存結構的原理及應用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“jvm內存結構的原理及應用”吧!
??jvm內存結構主要包括:方法區、堆、虛擬機棧、本地方法棧、程序計數器等五大部分, 下面我們來具體看一下每一個部分。
作用:
虛擬機棧描述的是java方法執行的動態內存模型,通過進棧、出棧來實現方法的調用結構。
分析:
??棧結構的特點是后進先出,方法調用的過程也是后調用的方法返回結果后,先調用的方法再接著執行,你是干柴,我是烈火。你是魚兒,我是小河。(此處不知道是蛋孵化了雞,還是雞生出了蛋)
??以methodA調用methodB為例,來看一下方法棧的執行過程
首先是主方法進入空棧(圖中免去了這一步),主方法中調用methodA --》 methodA入棧 --》 methodA調用methodB --》 methodB入棧 --》 methodB執行完畢,出棧并返回返回值 --》 methodA執行完畢,出棧并返回返回值 --》主線程執行完畢并出棧(圖中免去了這一步)--》程序執行完畢。
??那么methodA、methodB中到底包含了哪些內容呢?
??我們不如從方法定義的角度來思考一下,編寫程序時,里面經常出現的幾個要素無外乎:變量、控制結構(循環、分支)、函數調用(也可以叫方法),函數其實就是用一定的控制結構來操作變量,中間穿插著其他函數的調用,分支結構主要控制的是程序執行到哪一行,這個由我們后面1.5章節要講到的程序計數器來實現,函數調用層次如上面所說由虛擬機棧來支持,而變量以及方法的出口就是methodA、methodB中的主要內容。
??methodA、methodB在虛擬機棧中叫做棧幀,棧幀中包括變量(局部變量表-基本類型、對象引用-對象內存地址等)以及返回值地址等信息,可以看出棧幀中包含的內容是編譯器就可確定大小的,當進入一個方法時,需要分配多大的局部變量空間是完全確定的,在運行期中不會改變局部變量表的大小。
此區域可能出現的異常:
棧是有深度的,方法調用層次超過棧的深度,就會出現StackoverflowError,一般是遞歸調用時,基線條件不合理時,容易出現此問題。
當棧的深度增大時,所需要的局部變量表空間也隨之增長,當超過一定界限時,會出現OutOfMemoryError異常。
作用:
本地方法棧與虛擬機棧的區別是調用的是不同類型的方法,本地方法棧用于記錄native方法的調用,本地方法棧中未對native方法實現語言、數據結構等做強制規定,主要由虛擬機自己定義并實現。
注:
由于本地方法棧和虛擬機棧的作用非常相似,因此部分虛擬機的實現中,就將這兩塊區域合并成了一個區域,例如比較常用的Hotspot。
此區域可能出現的異常
與虛擬機棧相同,此區域也有可能出現StackoverflowError或OutOfMemoryError。
作用:
堆是jvm是管理的內存中最大的一塊,此區域只有一個作用就是存放對象實例。(java是面向對象語言--》堆用于存放對象實例 --》堆占用空間最大,嗯,沒毛病鐵子。)
注 :
由于此區域占用內存空間最大,而且對象的創建與銷毀是比較頻繁的,那內存空間不夠用了怎么辦?跟殺豬挑最肥的宰是一個道理,此區域是垃圾回收的主要區域。java為我們省去了代碼層手動釋放內存的工作,通過垃圾回收器來實現自動化的內存回收(《7天精通java》:《21天c++從入門到入土》,知道自動垃圾回收的重要性了吧)
此區域可能出現的異常:
為對象分配空間時,內存不足,會出現OutOfMemoryError(敲黑板)。
對應的排查策略:配置參數-XX:+HeapDumpOnOutOfMemoryError,這樣虛擬機在出現此異常時,會生成內存堆存儲快照,使用工具Eclipse Memory Analyzer或jprofiler,可以分析某些對象占用空間百分比,快速定位到問題,如果代碼存在問題,例如不停的創建某些對象,但并不釋放,那就要通過修改代碼來解決問題,如果代碼不存在問題,就需要通過加大物理內存,調整jvm堆參數來增加堆大小。(-Xms 堆初始化大小,-Xms 對空間最大大小,實際配置過程中,一般設置成一樣的大小,避免出現內存抖動,影響穩定性)
作用:
方法區主要用于存取類信息、常量、靜態變量、運行時常量池等。
分析:
運行時常量池用于存取字面量和符號引用,當使用雙引號聲明String變量時,此變量并不是開辟到堆空間當中,而是開辟到方法區中的運行時常量池中的,運行時常量池不僅可以在編譯期產生,也可以在程序運行期間,動態產生,例如String中的intern方法,就是在程序運行狀態中將字符串值放到運行時常量池中的。
此區域可能出現的異常:
此區域在內存不足時,也會出現OutOfMemoryError異常。
作用:
程序計數器主要是用于記錄當前線程所執行的字節碼的行號指示器,即當前線程執行到了哪一行,由于功能比較簡單,所以與其他幾個區域相比,內存空間占用的非常小。
此區域可能出現的異常:
程序計數器的作用決定了在此區域中不會出現由程序本身導致的異常,如果此處出現異常,是jvm本身的設計缺陷。
注:
如果線程執行的是java方法,計數器對應的是字節碼指令的地址,但是如果是native方法,底層是非java實現的,此時計數器對應的值是undefined
引申:
說到了程序計數器,在部分編程語言中,是支持goto關鍵字的,goto可以讓程序直接跳轉到指定行,java是不支持goto的,但是把goto作為了保留字,即java不支持此種語法,但是也不讓開發者去定義為變量,防止后續java發展過程中,加入goto關鍵字后,導致部分程序運行異常。
??上面五個區域中,方法區和堆是線程共享的區域,這兩個區域中放置的內容是與線程無關的,任意一個線程都可能會訪問到這兩塊區域中的內容。
??對于每個線程來說,它的調用方法棧應該是獨屬于某個線程的,如果多個線程共用一個方法棧那程序的執行順序是無法得到保障的,線程執行到哪一行應該也是唯一的,因此方法棧、程序計數器是線程獨占的。
感謝各位的閱讀,以上就是“jvm內存結構的原理及應用”的內容了,經過本文的學習后,相信大家對jvm內存結構的原理及應用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。