2012-07-18 30 views
0

我有一個應用程序可以在線下載csv文件,然後將其保存到本地,以便該應用程序即使在離線狀態下也能正常工作。我的問題是,當用戶關閉應用程序,然後立即再次打開它,應用程序掛起解析保存的csv文件並拋出OutOfMemoryError。不過,我注意到,當我幾分鐘後再次打開應用程序時,它工作得很好。 下載,解析和保存是在單獨的線程上完成的。 有什麼可以解決這個問題的?分析csv文件時出現Android OutOfMemoryError

+0

文件有多大?你是否一次將它讀入記憶? – Thilo 2012-07-18 06:50:18

+0

〜6mb。是的,我做... – yojoannn 2012-07-18 06:54:41

回答

1

一種可能性:內存不足錯誤可能更多的是與過度勞累的GC相比,實際內存不足。如果你分配大量的內存,然後釋放它們,然後分配更大的內存塊,那麼你會得到大量可用內存佔用空間但無法使用的點,因爲它們不夠大。 GC正在瘋狂地嘗試移動這些東西並將它們合併爲一個連續的塊,以便進行下一次分配,而不是看起來不好,因爲它耗時太長,只會拋出OutOfMemory異常,即使理論上有90%的內存可用(如果你可以給它一分鐘,將可用)。

在你的情況,我懷疑ArrayList。它保存一系列引用。添加條目時,它會添加到數組中。當它運行結束時,它會分配一個新的,更大的,一個釋放舊的。如果你保持繁忙,這些丟棄物堆積起來。散列表有類似的問題。 LinkedList和TreeMap不會,因爲它們可以處理少量的內存。

我對Android沒有太多瞭解,但我猜測應用程序並沒有真正關閉,因此當您重新啓動它時,它與以前的內存碎片執行方式相同。如果你等一會兒,這可能是一個新的執行。即使不是這樣,GC已經有時間清理乾淨了,你很好。

您想要的解決方案可能是每次「啓動」系統時強制進行垃圾回收(System.gc())。它讓GC有機會在爲您分配空間之前整理所有內容,而且不會花費很長時間。從某種意義上說,你讓GC有權鎖定你的程序半秒鐘,這是它自己不能做的。 (如果是這樣,它會選擇一個尷尬的時間來做到這一點 - 而用戶的輸入文字說)

通過使用鏈接集避免大型數組是另一種解決方案,但陣列速度快,當你可以備用用戶時間的半秒鐘沒有理由切換。

希望這會有所幫助。如果這次不是問題,那可能是下一次。

此外:不幸的是,System.gc()只是一個「建議」。它可能沒有做我們希望它會做的工作。或者你打電話後可能會遇到麻煩。我之前應該提到的另一個重大修復將是在ArrayList上設置初始大小非常大,如果這是您正在使用的。使其達到需要的尺寸的兩倍或三倍,可能會在運行時節省十倍的內存量,並節省時間。這適用於任何基於數組的結構(散列表和普通數組)。除此之外,如果你能克服它們的缺點,像LinkedList這樣基於指針的結構將不會有這個問題。

+0

嗨@RalphChapin,你的建議強制垃圾收集有點幫助。我看到一些改進,所以我會接受答案,但它並沒有完全解決問題......我想我錯過了一些東西。會再次檢查我的代碼。謝謝! – yojoannn 2012-07-22 13:53:31

+0

@simplymoody:我稍微擴展了我的答案。我的原創有點理論上的問題,但希望能讓你意識到可能發生的GC問題,不管這是否與你相違背。 (如果System.gc()有幫助,那很可能是)。我添加了另一個實用修補程序和一個不太實際的修補程序。 (儘管我確實使用LinkedLists爲_lot_,因此列表大小變化很大,從微秒到微秒。) – RalphChapin 2012-07-23 15:06:15

相關問題