從容應對問題再發:關於JVM記憶體,你想知道的都在這裡

博為峰網校發表於2022-03-16

 JVM記憶體是我們在系統部署、最佳化、問題排查中的一項重要內容,在最近支援的幾個專案中,多次出現與JVM記憶體相關的問題,因此有必要加強一下實施人員對JVM記憶體的理解,從而更好地應對今後可能再次出現的問題。 加我VX:atstudy-js 回覆“測試”,進入 自動化測試學習交流群~~

關於JVM記憶體相關理論的文章,網上有很多,下面的內容是參照網路文章並結合我們實際工作中的問題做出的一些總結,重點在JVM的記憶體結構上,供大家參考。

公式一

JVM在我們看來,就是一個java程式,無論我們的系統使用的是tomcat、weblogic、還是websphere,系統起來後對應的就是一個java程式。這個java程式的記憶體組成可以粗略的用下面的公式來表示:

JAVA程式記憶體(或者叫作JVM記憶體)=堆記憶體+類儲存記憶體+堆疊記憶體+其它記憶體

堆記憶體:就是heap記憶體,就是透過-Xms和-Xmx設定的那部分記憶體,這部分記憶體主要儲存java物件,例如new生成出來的物件,這部分記憶體可以透過垃圾回收器進行回收。

類儲存記憶體:是專門儲存java類的記憶體,例如系統啟動時裝載的第三方jar包,應用伺服器本身的類,編譯jsp後形成的java類等,都是存在這個區域的,這部分記憶體基本不會被垃圾回收器回收,只有在某些特殊情況下才會被回收。不同廠商對於這部分記憶體的實現不盡相同,例如Sun的jdk中,是透過-XX:PermSize和-XX:MaxPermSize來設定的,而IBM的jdk則沒有這個區域,而是存在堆記憶體中的。

堆疊記憶體:即stack記憶體,主要用於儲存執行緒用到的相關資料,棧中主要存放一些基本型別的變數(int, short, long, byte, float, double, boolean, char)和物件控制程式碼。

執行緒堆疊記憶體:透過-Xss引數來指定,預設值在256KB到756KB不等,假設執行緒堆疊設定為-Xss512k,系統執行期間共有200個執行緒,那麼執行緒堆疊總的佔用記憶體大概就是100M,執行執行緒數量越多,堆疊佔用記憶體也就越大。

其它記憶體:主要包括JIT、JNI、NIO等,這些記憶體比較複雜,這裡不做過多介紹。

公式二

上面介紹的JAVA程式記憶體都是指使用者空間的記憶體,除了使用者空間記憶體,還有一部分核心空間記憶體,核心空間記憶體供作業系統使用,對於應用程式來說是透明的不可訪問的。

對於上面的公式,可以進一步細化為如下公式:

JAVA程式記憶體=使用者空間記憶體(堆記憶體+類儲存記憶體+堆疊記憶體+其它記憶體)+核心空間記憶體

有了這個公式,我們在理解以下問題時就比較清晰了。

問題一:32位jdk和64位jdk的最大記憶體問題。

32位jdk的-Xmx值最大可以設定多大,這個問題是我們在實施過程中經常遇到的。

對於32位系統,單個程式記憶體的最大定址空間為2的32次方,也就是4GB記憶體,其中一部分是使用者空間記憶體,一部分是核心空間記憶體。對於windows系統,核心空間預設是預留2GB,使用者空間最大隻有2GB,使用者空間除了有堆記憶體,還有其它型別的記憶體,所以-Xmx的最大值一定是小於2G,通常最大能設定到1536M。

對於linux系統,核心空間預設是預留1GB,使用者空間最大可以到3GB,所以-Xmx的最大值一定是小於3G,通常至少可以設定到2048M以上。

對於64位系統,單個程式記憶體的最大定址空間為2的64次方,非常大了,基本可以當作沒有限制,所以-Xmx的最大值可以認為是無限大。

注:可以透過java –Xmx****** -version來測試最大可設定的堆記憶體。

問題二:記憶體溢位的分類及應對。

當出現記憶體溢位時,首先要搞清楚是哪部分記憶體溢位,這樣才能採取相應的應對措施。

A.堆記憶體溢位

錯誤日誌:

java.lang.OutOfMemoryError: Java heap space

解決方案:檢查-Xmx設定是否合理;透過工具分析javacore和heapdump定位問題。

B.類儲存記憶體溢位

該類問題通常只出現在sun的jdk中,錯誤日誌大致如下:

java.lang.OutOfMemoryError: PermGen space

解決方案:增加-XX:MaxPermSize的值。

C.堆疊記憶體溢位

錯誤日誌:

java.lang.StackOverflowError

解決方案:通常是程式碼中有死迴圈或迴圈次數太多導致,也可以適當增加-Xss引數值。

D.使用者空間記憶體溢位(也叫本機記憶體溢位)

錯誤日誌:

java.lang.OutOfMemoryError: Failed to fork OS thread

java.lang.OutOfMemoryError:requested 32756 bytes for ChunkPool::allocate.Out of swap space?

The system is out of physical RAM or swap space In 32 bit mode, the process size limit was hit.

解決方案:

1、實體記憶體不足,增加實體記憶體。

2、Jdk的bug,升級或更換jdk。

3、實體記憶體充足的情況下出現本機記憶體溢位,一定是在32位系統中才會出現,最好的解決方案就是換成64位系統,如果無法更換的話只能透過適當調整JAVA使用者空間記憶體中各組成部分的大小來嘗試解決。

例如在32位windows系統中,使用者空間記憶體最大值為2G,堆記憶體-Xmx設定了1536M,這樣其它非堆的記憶體部分只可以使用不到500M的記憶體,如果500M不夠用的話,就會出現本機記憶體溢位,這時可以將-Xmx調小,例如調小到1024M(保證夠用不會出現堆記憶體溢位),這樣非堆的記憶體就增加到了1024M,問題有可能就得到解決。

關於本機記憶體溢位的原因可能會比較複雜,需要根據實際情況具體問題具體分析。

透過以上總結和分析,希望大家再次遇到記憶體溢位問題時能理清思路,對症下藥。目前記憶體價格相對便宜,很多客戶配置的實體記憶體都會超過4G,為了減少記憶體溢位問題的發生,可以建議使用者都採用64位的作業系統,相關的jdk、應用伺服器、資料庫也都採用64位的,這樣也可以使資源得到充分利用。

最後:

可以我的個人V:atstudy-js,可以免費領取一份10G軟體測試工程師面試寶典文件資料。以及相對應的影片學習教程免費分享!,其中包括了有基礎知識、Linux必備、Mysql資料庫、抓包工具、介面測試工具、測試進階-Python程式設計、Web自動化測試、APP自動化測試、介面自動化測試、測試高階持續整合、測試架構開發測試框架、效能測試等。

這些測試資料,對於做【軟體測試】的朋友來說應該是最全面最完整的備戰倉庫,這個倉庫也陪伴我走過了最艱難的路程,希望也能幫助到你!

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31407649/viewspace-2871464/,如需轉載,請註明出處,否則將追究法律責任。

相關文章