jvm堆溢出和棧溢出
一、jvm堆溢出
1、介紹
在jvm運行java程序時,如果程序運行所需要的內存大於系統的堆最大內存(-Xmx),就會出現堆溢出問題。
2、案例
// 介紹:執行該段代碼需要大於10m內存空間 public class HeadOverflow { public static void main(String[] args) { List<Object> listObj = new ArrayList<Object>(); for(int i=0; i<10; i++){ Byte[] bytes = new Byte[1*1024*1024]; listObj.add(bytes); } System.out.println("添加success"); } } // 設置該程序的jvm參數信息 -Xms1m -Xmx10m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError 初始堆內存和最大可以堆內存 Gc詳細日志信息


3、總結
在正式項目部署環境程序默認讀取的是系統的內存,一般設置程序的堆初始內存(-Xms) == 堆最大可用內存(-Xmx)。
二、jvm棧溢出
1、介紹
a、線程請求的棧深度大於虛擬機允許的最大深度 StackOverflowError
b、虛擬機在擴展棧深度時,無法申請到足夠的內存空間 OutOfMemoryError
理解:每次方法調用都會有一個棧幀壓入虛擬機棧,操作系統給JVM分配的內存是有限的,JVM分配給“虛擬機棧”的內存是有限的。如果方法調用過多,導致虛擬機棧滿了就會溢出。這里棧深度就是指棧幀的數量。https://www.cnblogs.com/lovlife/articles/12452502.html
2、案例
// 循環遞歸調用,一直達到jvm的最大深度 public class StackOverflow { private static int count; public static void count(){ try { count++; count(); } catch (Throwable e) { System.out.println("最大深度:"+count); e.printStackTrace(); } } public static void main(String[] args) { count(); } }

調整jvm 棧大小
C:\Users\rocky fang\Documents\mycode>java -Xss2m -cp "C:\Users\rocky fang\Documents\mycode" JavaStackTest
java.lang.StackOverflowError
stack height:23345
C:\Users\rocky fang\Documents\mycode>java -Xss5m -cp "C:\Users\rocky fang\Documents\mycode" JavaStackTest
java.lang.StackOverflowError
stack height:93213
C:\Users\rocky fang\Documents\mycode>java -Xss10m -cp "C:\Users\rocky fang\Documents\mycode" JavaStackTest
java.lang.StackOverflowError
stack height:423618
設置-Xss5m設置最大調用深度后調用

總結:每個計算機都會有一個極限最大調用深度,避免遞歸在代碼中無限循環。
局部變量表內容越多,棧幀越大,棧深度越小。
三、內存溢出和內存泄露
1、區別
內存溢出:申請內存空間,超出最大堆內存空間。
內存泄露:其實包含內存溢出,堆內存空間被無用對象占用沒有及時釋放,導致占用內存,最終導致內存泄露。
情況:靜態static修飾對象。
解決:減少常量的定義(具體看服務器內存情況)
原文鏈接:https://blog.csdn.net/coderyin/article/details/99546338
