JVMST109: Insufficient space in Javaheap to satisfy allocation request

zgy13121發表於2008-08-15

JVMST109: Insufficient space in Javaheap to satisfy allocation request錯誤的處理

環境:aix5.3L+weblogic8.1+ibm jdk1.42 6g記憶體,給weblogic的記憶體為1536m.

錯誤:

JVMST109: Insufficient space in Javaheap to satisfy allocation request

java.lang.OutOfMemoryError (簡稱oom)

發生情況: 當一報表結果集8萬行的時候,頁面只取100行的時候報異常,生產庫伺服器停掉了. 為查出原因,找了很多相關資料,其中有談到ibm jdkjdk1.4的垃圾回收機制與sun jdk1.4機制的異同.沒有時間去考察這些異同的真實性.另這類錯誤,既然是大記憶體的分配與釋放,從程式碼本身解決才是最根本的.

下面就我的有關實驗記錄一下.

[@more@]

經實驗證實在p4 雙核3.2g 3.2g的機器上分配一個stringBuffer的物件最大值為210 000 000左右.超過這個值會報oom錯誤.

根據這一結論,我對原錯誤進行猜想,因為取資料庫結果集時指定了每頁行大小,按正常情況,還不會報oom錯誤.

進一步分析原碼:

DataSet dset = erpm1.executeQueryToDataSet(sqlSelect);

rowCount = dset.getRowCount();

DataSet是離線結果集,既然是離線的,他當然會把所有東西包在裡面,當一結果集超大的時候(比如8萬,其實測試時,當結果集大於2萬條時,就頂不住了),不報oom才怪呢?

所以只有把這個地方處理好了,就可以了. 簡單地說,就是首先求總行數,然後依據條件寫出分頁sql,不要一次性裝載所有資料。否則白天伺服器當機,看人家瞧你!

後記:

由這個錯誤,我想起了

離線處理資料庫,好處:即時的在基類程式碼裡處理與資料庫資源的釋放問題,使得程式碼簡潔.用空間換取了時間,贏得了效率.但同時也帶來了潛在的問題,大量的記憶體被消耗了. 雖說java的垃圾回收機制比較先進,而且還在進步,但當遇到這種超大結果集的時候,就暴露出了很大的問題,一下子分配過多,就oom了.

而聯機處理的resultSet就沒有這樣的問題(但是,如果取數過大,會佔用資料庫記憶體從而引發問題(一般在應用端出問題的,肯定先經過資料庫端,應該說資料庫可以執行透過),所以,在取數時,切記用分頁處理,不要一次性全部取出,尤其是大表),他不會將所有的結果全部裝進記憶體,只在你取的時候,從資料庫讀出來,他的缺點是總頭至尾始終佔用資料庫資源.並且在使用完後,一定要手工釋放資源,不能自動回收.這樣使程式碼看起來顯得臃腫.

個人覺得,對於大型專案中基類中的東西,還是用底層的東西較好,儘量避免大記憶體的分配與釋放,提高效率才是解決問題的根本.在後面的應用層,當然還是儘量封裝好的,畢竟不是每個開發員都能寫出優雅的程式碼.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/11419868/viewspace-1009007/,如需轉載,請註明出處,否則將追究法律責任。

相關文章