1. 程式人生 > >java.lang.StackOverflowError 和OutofMemoryError解決方案彙總

java.lang.StackOverflowError 和OutofMemoryError解決方案彙總

 在java虛擬機器規範中,虛擬機器棧和本地方法棧都會出現StackOverflowError和OutofMemoryError,程式計數器是java虛擬機器中唯一一塊不會產生error的記憶體區域,StackOverflowError代表的是,當棧深度超過虛擬機器分配給執行緒的棧大小時就會出現此error,OutofMemoryError代表的是,當再申請新的記憶體時,虛擬機器分配給執行緒的記憶體大小中無法再分配新的記憶體,就會出現此error。

現象:物件互相巢狀設定出現StackOverflowError異常,也就是函式呼叫層級過多導致。比如死遞迴。

看到這個異常的第一反應,就是檢查程式碼中是否有大量的遞迴呼叫,結果發現就是沒有。

然後想到的是JVM預設的棧大小,於是想修改JVM引數,這個引數可以在maven的pom.xml檔案中進行配置其中,

以下片段為修改棧大小:

<jvmArgs>   
    <jvmArg>-Xss2048K</jvmArg>
</jvmArgs>

其實個人來說,不是很感動xml檔案,因為我表示我看不是很懂這個檔案中的資訊,所有不敢改動。

因此我在hope的配置檔案中,稍微改動了一些配置引數:

spark.executor.extraJavaOptions="-Xss3062k"

從原來的-Xss2048k修改為3062,希望這次好用。

還修改了一個引數:

spark.driver.extraJavaOptions="-XX:+UseConcMarkSweepGC  -XX:+UseParNewGC   -XX:+PrintGCDetails  -XX:ThreadStackSize=4m"

將-XX:ThreadStackSize=2m 設定為-XX:ThreadStackSize=4m。

結果:報錯了,隨後改回原來的hope引數,不過報錯不是因為引數設定,是因為我演算法裡面修改了依據程式碼,導致我的演算法輸入資料中有NULL值。

OOM:在scala中,大量使用了將執行結果拉取到driver端的active操作:collect,take,show等,導致OOM

使用collect將資料拉取到driver端,而當資料量超過Driver記憶體時會報錯OOM。所以儘量不要列印太多內容,這樣出的bug讓人淚奔。
Java常見的幾種記憶體溢位及解決方法【情況一】:
java.lang.OutOfMemoryError:Javaheapspace:這種是java堆記憶體不夠,一個原因是真不夠(如遞迴的層數太多等),另一個原因是程式中有死迴圈;
如果是java堆記憶體不夠的話,可以通過調整JVM下面的配置來解決:
-Xms3062m
-Xmx3062m
【情況二】
java.lang.OutOfMemoryError:GCoverheadlimitexceeded
【解釋】:JDK6新增錯誤型別,當GC為釋放很小空間佔用大量時間時丟擲;一般是因為堆太小,導致異常的原因,沒有足夠的記憶體。
【解決方案】:
1、檢視系統是否有使用大記憶體的程式碼或死迴圈;
2、通過新增JVM配置,來限制使用記憶體:
-XX:-UseGCOverheadLimit
【情況三】:
java.lang.OutOfMemoryError:PermGenspace:這種是P區記憶體不夠,可通過調整JVM的配置:
-XX:MaxPermSize=128m
-XXermSize=128m
【注】:
JVM的Perm區主要用於存放Class和Meta資訊的,Class在被Loader時就會被放到PermGenspace,這個區域成為年老代,GC在主程式執行期間不會對年老區進行清理,預設是64M大小,當程式需要載入的物件比較多時,超過64M就會報這部分記憶體溢位了,需要加大記憶體分配,一般128m足夠。
【情況四】:
java.lang.OutOfMemoryError:Directbuffermemory
調整-XX:MaxDirectMemorySize=引數,如新增JVM配置:
-XX:MaxDirectMemorySize=128m
【情況五】:
java.lang.OutOfMemoryError:unabletocreatenewnativethread
【原因】:Stack空間不足以建立額外的執行緒,要麼是建立的執行緒過多,要麼是Stack空間確實小了。
【解決】:由於JVM沒有提供引數設定總的stack空間大小,但可以設定單個執行緒棧的大小;而系統的使用者空間一共是3G,除了Text/Data/BSS/MemoryMapping幾個段之外,Heap和Stack空間的總量有限,是此消彼長的。因此遇到這個錯誤,可以通過兩個途徑解決:1.通過-Xss啟動引數減少單個執行緒棧大小,這樣便能開更多執行緒(當然不能太小,太小會出現StackOverflowError);2.通過-Xms-Xmx兩引數減少Heap大小,將記憶體讓給Stack(前提是保證Heap空間夠用)。
【情況六】:
java.lang.StackOverflowError
【原因】:這也記憶體溢位錯誤的一種,即執行緒棧的溢位,要麼是方法呼叫層次過多(比如存在無限遞迴呼叫),要麼是執行緒棧太小。
【解決】:優化程式設計,減少方法呼叫層次;調整-Xss引數增加執行緒棧大小。

參考連結:

https://zhidao.baidu.com/question/1695734020620443668.html