jvm中主要分為方法區、堆、棧、本地方法棧、程序計數器這幾部分,其中程序計數器是唯一不會出現OOM的
1. java堆溢出(heap)
Java堆內存主要用來存放運行過程中所有的對象,該區域OOM異常一般會有如下錯誤信息:
java.lang.OutofMemoryError:Java heap space
可以通過dump的內存快照就能分析,到底是由於程序原因導致的內存泄露,還是由於沒有估計好JVM內存的大小而導致的內存溢出。
2. 棧溢出(stack)
棧用來存儲線程的局部變量表、操作數棧、動態鏈接、方法出口等信息。如果請求棧的深度不足時拋出的錯誤會包含類似下面的信息: java.lang.StackOverflowError。
由於每個線程占的內存大概為1M,因此線程的創建也需要內存空間。如果申請創建的線程比較多超過剩余內存的時候,也會拋出如下類似錯誤:java.lang.OutofMemoryError: unable to create new native thread
與棧相關的JVM參數有:
1、 -Xss: 每個線程的堆棧大小,JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K.
2、 在相同物理內存下,減小這個值能生成更多的線程.但是操作系統對1個進程內的線程數還是有限制的,不能無限生成。
出現棧溢出可能原因:
遞歸:遞歸里用到的局部變量存儲在堆棧中,堆棧的訪問效率高,速度快,但空間有限,遞歸太多變量需要一直入棧而不出棧,導致需要的內存空間大於堆棧的空間,棧空間是2M,堆空間內存空間。
運行時常量溢出(constant)
運行時常量保存在方法區,存放的主要是編譯器生成的各種字面量和符號引用,但是運行期間也可能將新的常量放入池中,比如String類的intern方法。如果該區域OOM,錯誤結果會包含類似下面的信息:
1 java.lang.OutofMemoryError: PermGen space
相關的JVM參數有:
1、 -XX:PermSize:設置持久代(perm gen)初始值,默認值為物理內存的1/64
2、 -XX:MaxPermSize:設置持久代最大值,默認為物理內存的1/4
方法區溢出
方法區主要存儲被虛擬機加載的類信息,如類名、訪問修飾符、常量池、字段描述、方法描述等。理論上在JVM啟動后該區域大小應該比較穩定,但是目前很多框架,比如Spring和Hibernate等在運行過程中都會動態生成類,因此也存在OOM的風險。如果該區域OOM,錯誤結果會包含類似下面的信息:
java.lang.OutofMemoryError: PermGen space
相關的JVM參數有:
1 -XX:PermSize:設置持久代(perm gen)初始值,默認值為物理內存的1/64
2 -XX:MaxPermSize:設置持久代最大值,默認為物理內存的1/4
https://www.bilibili.com/read/cv9971526/