為啥會出現OutOfMemoryError
內存中加載的數據量過於龐大,如一次從資料庫取出過多數據; 集合類中有對對象的引用,使用完後未清空,使得JVM不能回收;
代碼中存在死循環或循環產生過多重複的對象實體; 使用的第三方軟體中的BUG; 啟動參數內存值設定的過小;
OutOfMemoryError幾種情況
最常見的有這3種
java.lang.OutOfMemoryError: Java heap spacejava.lang.OutOfMemoryError: PermGen spacejava.lang.OutOfMemoryError: GC overhead limit exceeded
(堆內存溢出)java.lang.OutOfMemoryError: Java heap space
Java heap space,Java應用程式創建的對象存放在這片區域,垃圾回收(Garbage Collection)也發生在這塊區域。通常一些比較「重型」的操作可能會導致該異常,比如:需要創建大量的對象,層次比較深的遞歸操作等。
解決方案有兩種,一是優化應用,找到消耗大量內存的地方,然後優化代碼或者算法。這種方式比較推薦,但是難度比較大,尤其是在產品環境中出現這種問題,開發人員不能很好的重現問題。第二種方案是提升Java heap size,這種方式雖然感覺有點治標不治本,但是可行性非常高,操作簡單。
如果是在tomcat中,出現的這種問題,解決辦法是在{tomcat_dir}/bin/catalina.bat中找到如下幾行:
在後面加上一行(數字根據自己的需要調整):
set CATALINA_OPTS=-Xms512m -Xmx512m(方法區內存溢出)java.lang.OutOfMemoryError: PermGen space
Perm Gen Size(Permanent Generation Size),用來存儲被加載的類的定義(class definition)和元數據(metadata),比如:Class Object和Method Object等。這是內存中的一塊永久保存區域,JVM的垃圾回收不會觸及這塊區域。通常在加載一個非常大的項目的時候才會出現該異常。
如果是在tomcat中出現這個問題,解決辦法是在{tomcat_dir}/bin/catalina.bat中添加如下一行:
set CATALINA_OPTS=-server -Xms256m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512mjava.lang.OutOfMemoryError: GC overhead limit exceeded
這個錯誤會出現在這個場景中:GC佔用了多餘98%(默認值)的CPU時間卻只回收了少於2%(默認值)的堆空間。目的是為了讓應用終止,給開發者機會去診斷問題。一般是應用程式在有限的內存上創建了大量的臨時對象或者弱引用對象,從而導致該異常。雖然加大內存可以暫時解決這個問題,但是還是強烈建議去優化代碼,後者更加有效。
首先,你可以關閉JVM這個默認的策略:
1 java -XX:-UseGCOverheadLimit JavaApp 其次,你也可以嘗試去加大Heap Size:
1 java -Xmx512m JavaApp 注意:在修改Tomcat的catalina.bat(*.sh)中的內容時,網上有很多都是說直接修改JAVA_OPTS,按照Apache官方的說法是:
Note: Do not use JAVA_OPTS to specify memory limits. You do not need much memory for a small process that is used to stop Tomcat. Those settings belong to CATALINA_OPTS.
預防OutOfMemoryError從我做起
導致java.lang.OutOfMemoryError的根本原因是程序不健壯
圈起來,這句話是重點
怎麼做?
1、儘早釋放無用對象的引用2、使用字符串處理,避免使用String,應大量使用StringBuffer,每一個String對象都得獨立佔用內存一塊區域3、儘量少用靜態變量,因為靜態變量存放在永久代(方法區),永久代基本不參與垃圾回收4、避免在循環中創建對象5、開啟大型文件或從資料庫一次拿了太多的數據很容易造成內存溢出,所以在這些地方要大概計算一下數據量的最大值是多少,並且設定所需最小及最大的內存空間值。
windows環境中直接到jdk安裝目錄bin文件夾下雙擊jvisualvm.exe打開,或者在cmd下輸入jvisualvm回車。查看更多信息
更多jvm學習
jvm基礎概念理解
jvm內存模型詳解記錄
jvm中的堆和棧(面試總結)
jvm類加載過程