JVM 常见异常及内存诊断
棧內(nèi)存溢出
棧內(nèi)存大小設置:-Xss size 默認除了window以外的所有操作系統(tǒng)默認情況大小為 1MB,window 的默認大小依賴于虛擬機內(nèi)存。
棧幀過多導致棧內(nèi)存溢出
下述示例代碼,由于遞歸深度沒有限制且沒有設置出口,每次方法的調(diào)用都會產(chǎn)生一個棧幀導致了創(chuàng)建的棧幀過多,而導致內(nèi)存溢出(StackOverflowError)。
示例代碼:
運行結(jié)果:
棧幀過大導致棧內(nèi)存溢出
示例代碼:
運行結(jié)果:
如下所示部門依賴員工集合,員工依賴于部門,如此一來,由于循環(huán)引用使得棧幀過大從而導致棧內(nèi)存的溢出。
因此我們的解決思路是:打破循環(huán)引用來解決,如下所示(當然這只是針對當前實例場景的解決方式,其主要目的是提供一種解決問題的思路)
堆內(nèi)存溢出
堆內(nèi)存大小設置參數(shù):-Xmx
雖然“堆”是垃圾回收的主要管理區(qū)域,但垃圾回收主要是針對已經(jīng)無用的對象的,如果被引用的對象而且不斷的產(chǎn)生新對象而且一直被使用時,垃圾回收器是不會處理被使用的對象的。如果不斷產(chǎn)生新對象最終超出了堆的內(nèi)存大小,則會導致堆內(nèi)存的溢出。
示例代碼:
默認情況下下述代碼一般不會出現(xiàn)堆內(nèi)存溢出情況
把jvm的堆內(nèi)存上限大小設置成8MB,然后再運行程序
運行結(jié)果:
說明:一般出現(xiàn)該情況我們是可以解決的,一方面是確實是因為內(nèi)存不夠的,我們適當?shù)恼{(diào)整內(nèi)存大小,另一方面就是程序邏輯本身有問題,如下圖邏輯,這是一個死循環(huán),字符串通過不斷的添加,沒有終止的時候,不管設置多大的內(nèi)存都會最終撐爆最大的內(nèi)存限定,從而導致了內(nèi)存的溢出,以異常退出程序收場。
?
?
堆內(nèi)存診斷:
jps: 查看當前系統(tǒng)中有那些java進程
.....\demos\jvmbase>jps
28036
15180 Jps
6140 Demo1
jmap 工具: 查看堆內(nèi)存占用情況(瞬時的)
jmap? -heap 進程id
下述是該命令呈現(xiàn)的部分內(nèi)容,下述是堆內(nèi)存某個瞬間的使用情況 如下:
?
jconsole 工具: 圖形界面的,內(nèi)存java性能分析器,多功能的監(jiān)測工具,可以連續(xù)監(jiān)測
方法區(qū)內(nèi)存溢出
代碼示例(基于jdk1.8):
上述代碼運行,在沒有限定元空間大小的時候一般很難出現(xiàn)方法區(qū)內(nèi)存溢出。
下面通過限定元空間的大小為8M,然后重新運行程序
通過限定元空間的大小,這時候會發(fā)現(xiàn)程序會拋出方法區(qū)的內(nèi)存溢出(也就是元空間導致的內(nèi)存溢出)
?
代碼示例(基于jdk1.6): 程序邏輯整體與上述jdk1.8一致,修改jdk版本為1.6:
默認情況下不設置方法區(qū)的內(nèi)存大小一般也不會輕易出現(xiàn)問題,下面我們同意通過修改內(nèi)存大小進行試驗
下面通過限定方法區(qū)(永久代)的大小為8M,然后重新運行程序
通過限定方法區(qū)(永久代)的大小,這時候會發(fā)現(xiàn)程序會拋出方法區(qū)的內(nèi)存溢出(也就是永久代導致的內(nèi)存溢出)
?
總結(jié)
以上是生活随笔為你收集整理的JVM 常见异常及内存诊断的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022-2028年中国汽轮发电机行业市
- 下一篇: 2022-2028年中国汽车制动器行业投