在上一節中Java虛擬機內存分布 說了Java虛擬機中分為五個區域,而且也知道了在Java程序計數器區域不會出現OOM(OutOfMemeryError),那么以下就對除了程序計數器以外的四個區域出現OOM的原理以及解決方案進行解說。
1.Java虛擬機棧與本地方法棧
棧的大小控制參數時 -Xss。
Java虛擬機在棧中定義了兩種異常,StrackOverFlowError和OutOfMemeryError。當請求棧的深度大於java虛擬機所同意的最大深度則拋出StrackOverFlowError;假設Java虛擬機在棧擴展時。沒有申請到足夠的空間時,則拋出OutOfMemeryError。
StrackOverFlowError:Java虛擬機在執行中,調用方法時,都要創建棧幀,當棧的空間不夠時就會產生StrackOverFlowError。那么相應的解決方法就僅僅能是調節-Xss參數,或者降低方法的調用,減小棧幀的大小兩種方式。
OutOfMemeryError:在棧上出現OOM通常是多線程的情形。
首先咋們解析一下棧使用的空間能夠有多大,拿32位操作系統來舉例。 最大內存2G - Xmx(最大堆容量)- MaxPermSize(最慷慨法區容量)- 虛擬機本身耗費的內存和程序計數器使用的內存。
剩下的內存就是棧能夠使用的空間,當Xss配置的參數一定時,那么在不斷的創建線程過程中。遇到不能申請到棧空間的時候就會拋出OOM。那么相應的解決方案就是,調節-Xss參數減少棧大小,或者調節-Xmx以及MaxPermSize的大小擴大留給棧的空間。
2.方法區內存溢出
方法區的大小通過-PermSize和-MaxPermSize控制。
由於類常量和執行時常量也存儲在方法區中,所以執行時常量過多也可導致方法區的OOM,可是沒有直接控制常量池大小的參數,僅僅能通過-PermSize和-MaxPermSize來間接控制。
在Spring以及Hibernate。Mybatis中都會使用GeneratedConstructorAccessor、動態代理以及CGLib字節碼增強技術的等動態生成類,那么就須要強大的方法區來支撐。
3.堆內存的溢出
堆內存的溢出比較復雜,須要調節GC等多種參數,我們在后面的章節中會進行解說。