java.lang.OutOfMemoryError Java heap space? 怎麼解?

文章推薦指數: 80 %
投票人數:10人

... 器噴出一個OutOfMemoryError: Java heap space 的錯誤就開始尋錯之旅了… ... 體試試看,如果加了好幾XXG 上去依舊不能用就開始要分析出錯的原因了. Home Archives Categories Tags 2020-02-24 Java 10分鐘閱讀文(大約1471個字) 觀看次數 java.lang.OutOfMemoryErrorJavaheapspace?怎麼解? 前言因為工作關係,其實不只會碰到node.js有時候還會協助其他專案,而有的專案就是用java寫的很久之前在伺服器噴出一個OutOfMemoryError:Javaheapspace的錯誤就開始尋錯之旅了… 但這裡不會真實把工作上的專案的bug記錄在這裡XD只會以簡單的程式去表達當時除錯的流程基本上發摟這方法,應該能夠鎖定問題點不行的話…您看看就好XD 還原案發現場先上一段程式來模擬可以噴出OutOfMemoryError此程式是無限迴圈地往Map裡面塞東西12345678910111213141516importjava.util.HashMap;importjava.util.Map;importjava.util.Random;publicclassTest{publicstaticvoidmain(Stringargs[])throwsException{Mapmap=newHashMap();Randomr=newRandom();while(true){map.put(r.nextInt(),"value");}}} 透過javacTest.java編譯成功後再透過java-Xmx12mTest去執行指令這裡的-Xmx12m是一個關鍵,這裡指定了這個java程式能使用的heapmemory的上限為12M此時執行完指令的時候會噴出以下錯誤12345Exceptioninthread"main"java.lang.OutOfMemoryError:Javaheapspaceatjava.util.HashMap.resize(HashMap.java:703)atjava.util.HashMap.putVal(HashMap.java:662)atjava.util.HashMap.put(HashMap.java:611)atTest.main(Test.java:13) 這樣可以看到噴出此錯誤訊息這代表說假設你電腦本身記憶體空間8G但你分配給java應用程式的記憶體只有12MB的時候它不會跨過這個12MB限制,即使電腦還有將近8G的記憶體空間,它是不會超過12MB總歸一句話,使用的記憶體超出了我們設定給他的限制會導致OOM(OutofMemory) 這裡可以注意到叫做『HeapSpace』也就是程式運行時JVM可調配讓程式使用的記憶體空間Class實例化的Instance也是被放在這個區域除了Heap之外,還有PermGen的設定PermGen指的是Memory永久保存區是存放Class,MetaInfo的地方如果太小可能就會在precompile的階段把PermGen弄爆 解決方法通常記憶體不夠,就是給他開大加下去!但萬一你的程式剛好是無窮迴圈地往某一個地方塞東西這樣加大記憶體就沒有任何意義了因為這屬於程式上的Bug,要解決的不是記憶體而是寫出這程式的人解決程式邏輯的Bug才對 但如果是本身記憶體真的不夠用那就是加上記憶體試試看,如果加了好幾XXG上去依舊不能用就開始要分析出錯的原因了 至於要如何分析,雖然log會噴出Exception的訊息但總不會一直蹲在log前面看Exception哪天噴出來就算log以雲端方式保存,Exception能分析的程度還是有限 所以可以加上以下指令把當時噴出OOM的詳細狀況dump出來-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/tmp會把在OOM的時候,把整個heap等等當下執行詳細的狀況儲存變成一個檔案以上述的範例來說,使用的完整指令為java-Xmx12m-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/tmpTest這樣出現OOM的時候,就會往/tmp底下放入一個副檔名為.hprof可分析檔案12345678910java-Xmx12m-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/tmpTestjava.lang.OutOfMemoryError:JavaheapspaceDumpingheapto/tmp/java_pid57606.hprof...Heapdumpfilecreated[19050199bytesin0.163secs]Exceptioninthread"main"java.lang.OutOfMemoryError:Javaheapspaceatjava.util.HashMap.resize(HashMap.java:703)atjava.util.HashMap.putVal(HashMap.java:662)atjava.util.HashMap.put(HashMap.java:611)atTest.main(Test.java:13) 不過要注意的是當應用程式越龐大的時候,產生出來的hprof就會越大高達GB等級以上也是很常見的所以伺服器保留適當的空間就很重要 這時再透過java內建的一個分析程式jvisualvm去分析這個檔案就可以找到出現OOM的地方通常jvisualvm是位在javahome裡面bin底下的位置,以Mac來說是在這個路徑底下/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/bin/jvisualvmWidnwos則是會在C:\ProgramFiles\Java\jdk1.8.0_65 這前提是你沒有自行更改安裝的位置有更改安裝位置的話,那你自己應該就知道在哪了XD 打開後長這樣,然後開啟剛剛dump出來的hprof檔案 在裡面會看到一個『TheadcasuingOutOfMemoryErrorexception:main』 點選main後就可以看到錯誤的地方 點上面class可以獲得比較詳細的資訊,包含使用記憶體多少的量都能夠知道 以上是簡單介紹針對OOM除錯的一個心得和介紹 Tomcat設定方法在tomcat預設的資料夾底下,進入到bin的資料夾linux用戶新增一行程式新增一個setenv.sh的檔案exportJAVA_OPTS="-Xmx12m-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/tmp" windows用戶則是新增一個setenv.bat的檔案JAVA_OPTS="-Xmx12m-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/tmp" 後記實際上並沒有一個銀彈可以順利地解決OOM的方法必須找到是程式的邏輯Bug導致OOM又或是本身程式就是需要比較大的記憶體又或是第三方的Library寫不好又或是流量太大開太多Thread原因有很多種,只能透過分析的方式找到引起的主因否則,單純加大記憶體不會解決根本原因不然只持推遲爆炸的時間點而已(汗… 不管哪種語言排除OOM的流程都是大同小異這邊就先記錄以Java的方式(畢竟剛好工作上碰到 # java,w3HexSchool 從SSL到SSLPinning看完你就懂! CI/CD實現-bitbucket&Jenkins篇 Yourbrowserisout-of-date! Updateyourbrowsertoviewthiswebsitecorrectly.Update mybrowsernow ×



請為這篇文章評分?