天天看點

記憶體溢出的産生原因及解決方法 - canacezhang

記憶體溢出的産生原因及解決方法

一、産生記憶體溢出的

1、java.lang.OutofMemoryError:Java heap space
2、java.lang.OutofMemoryError:PermGen space
3、java.lang.OutofMemoryError:unable to create new native thread
4、java.lang.OutofMemoryError:GC overhead limit exceeded      

1、Java堆空間不夠,當應用程式申請更多的記憶體,而Java堆記憶體已經無法滿足應用程式對記憶體的需要,将抛出這種異常。

2、Java永久代空間不夠,永久代中包含類的位元組碼和長常量池,類的位元組碼加載後的資訊,這和存放對象執行個體的堆區是不同的,大多數JVM的實作都不會對永久帶進行垃圾回收,是以,隻要類加載的過多就會出現這個問題。一般的應用程式都不會産生這個錯誤,然而,對于Web伺服器來講,會産生有大量的JSP,JSP在運作時被動态的編譯成Java Servlet類,然後加載到方法區,是以,太多的JSP的Web工程可能産生這個異常。

3、本質原因是建立了太多的線程,而能建立的線程數是有限制的,導緻了這種異常的發生。

4、是在并行或者并發回收器在GC回收時間過長、超過98%的時間用來做GC并且回收了不到2%的堆記憶體,然後抛出這種異常進行提前預警,用來避免記憶體過小造成應用不能正常工作。

下面兩個異常與OOM有關系,但是,又沒有絕對關系。

  1. java.lang.StackOverflowError …
  2. java.net.SocketException: Too many open files

1、是JVM的線程由于遞歸或者方法調用層次太多,占滿了線程堆棧而導緻的,線程堆棧預設大小為1M。

2、是由于系統對檔案句柄的使用是有限制的,而某個應用程式使用的檔案句柄超過了這個限制,就會導緻這個問題。

二、産生原因及解決辦法

【情況一】: 

  java.lang.OutOfMemoryError: Java heap space:這種是java堆記憶體不夠,一個原因是真不夠,另一個原因是程式中有死循環; 

  如果是java堆記憶體不夠的話,可以通過調整JVM下面的配置來解決: 

  < jvm-arg>-Xms3062m < / jvm-arg> 

  < jvm-arg>-Xmx3062m < / jvm-arg> 

   

【情況二】 

  java.lang.OutOfMemoryError: GC overhead limit exceeded 

  【解釋】:JDK6新增錯誤類型,當GC為釋放很小空間占用大量時間時抛出;一般是因為堆太小,導緻異常的原因,沒有足夠的記憶體。 

  【解決方案】: 

  1、檢視系統是否有使用大記憶體的代碼或死循環; 

  2、通過添加JVM配置,來限制使用記憶體: 

  < jvm-arg>-XX:-UseGCOverheadLimit< /jvm-arg> 

   

【情況三】: 

  java.lang.OutOfMemoryError: PermGen space:這種是P區記憶體不夠,可通過調整JVM的配置: 

  < jvm-arg>-XX:MaxPermSize=128m< /jvm-arg> 

  < jvm-arg>-XXermSize=128m< /jvm-arg> 

  【注】: 

  JVM的Perm區主要用于存放Class和Meta資訊的,Class在被Loader時就會被放到PermGen space,這個區域成為年老代,GC在主程式運作期間不會對年老區進行清理,預設是64M大小,當程式需要加載的對象比較多時,超過64M就會報這部分記憶體溢出了,需要加大記憶體配置設定,一般128m足夠。 

   

【情況四】: 

  java.lang.OutOfMemoryError: Direct buffer memory 

  調整-XX:MaxDirectMemorySize= 參數,如添加JVM配置: 

  < jvm-arg>-XX:MaxDirectMemorySize=128m< /jvm-arg> 

   

【情況五】: 

  java.lang.OutOfMemoryError: unable to create new native thread 

  【原因】:Stack空間不足以建立額外的線程,要麼是建立的線程過多,要麼是Stack空間确實小了。 

  【解決】:由于JVM沒有提供參數設定總的stack空間大小,但可以設定單個線程棧的大小;而系統的使用者空間一共是3G,除了Text/Data/BSS /MemoryMapping幾個段之外,Heap和Stack空間的總量有限,是此消彼長的。是以遇到這個錯誤,可以通過兩個途徑解決: 

  1.通過 -Xss啟動參數減少單個線程棧大小,這樣便能開更多線程(當然不能太小,太小會出現StackOverflowError); 

  2.通過-Xms -Xmx 兩參數減少Heap大小,将記憶體讓給Stack(前提是保證Heap空間夠用)。 

   

【情況六】: 

  java.lang.StackOverflowError 

  【原因】:這也記憶體溢出錯誤的一種,即線程棧的溢出,要麼是方法調用層次過多(比如存在無限遞歸調用),要麼是線程棧太小。 

  【解決】:優化程式設計,減少方法調用層次;調整-Xss參數增加線程棧大小

posted on

2018-08-23 21:37 

canacezhang 

閱讀(4473) 

評論(0) 

編輯 

收藏 

舉報

記憶體溢出的産生原因及解決方法 - canacezhang