1

csvファイルをオンラインでダウンロードしてローカルに保存するアプリがあるので、オフラインでもアプリは機能します。私の問題は、ユーザーがアプリを閉じてすぐに再度開くと、保存されたcsvファイルの解析中にアプリがハングし、OutOfMemoryErrorがスローされることです。ただし、数分後にアプリを再度開くと、問題なく動作することに気付きました。ダウンロード、解析、保存は別々のスレッドで行われます。これに対する解決策は何でしょうか?

4

1 に答える 1

2

1つの可能性:メモリ不足エラーは、実際のメモリ不足よりも、GCの過負荷に関係している可能性があります。大きなメモリを割り当ててから解放し、さらに大きなメモリを割り当てると、大量の空きメモリがスペースを占有しますが、十分な大きさではないため使用できなくなります。GCは必死に物事を動かし、次の割り当てのためにこれらの部分を1つの連続したブロックにマージしようとしますが、時間がかかりすぎるために見栄えが悪くなるのではなく、メモリの90%が理論的に使用可能であっても、OutOfMemory例外をスローします。 (そして、あなたがそれに少し与えることができれば利用可能になります)。

あなたの場合、ArrayListが疑われます。参照の配列を保持します。エントリを追加すると、配列に追加されます。それが終わりを超えて実行されるとき、それは新しい、より大きなものを割り当てて、古いものを解放します。忙しくしていると、これらの廃棄物は山積みになります。ハッシュテーブルにも同様の問題があります。LinkedListとTreeMapは、少量のメモリで動作するため、機能しません。

Androidについてはあまり詳しくありませんが、アプリを短時間閉じても実際には閉じないので、再起動すると以前と同じ空きメモリ断片化実行になります。しばらく待つと、新しい実行になる可能性があります。そうでない場合でも、GCには問題を解決する時間があり、問題はありません。

必要な解決策は、システムを「起動」するたびにガベージコレクション(System.gc())を強制することです。それはあなたのためにスペースを割り当てる前にGCにすべてを整理する機会を与えます、そしてそれは長くはかからないでしょう。ある意味で、プログラムを0.5秒間ロックする許可をGCに与えているのですが、それだけでは実行できません。(もしそうなら、それはそれをするのに厄介な時間を選ぶでしょう-ユーザーがテキストを入力している間、例えば。)

リンクされたコレクションを使用して大きな配列を回避することも別の解決策ですが、配列は高速であり、ユーザーの時間の0.5秒を節約できる場合は、切り替える理由はありません。

お役に立てれば。今回は問題なければ、次回も問題ないかもしれません。

追加: 残念ながら、System.gc()は単なる「提案」です。それは私たちが望んでいた仕事をしていないかもしれません。または、電話の後で問題が発生している可能性があります。前に述べたはずのもう1つの大きな修正は、ArrayListの初期サイズを非常に大きく設定することです(それが使用している場合)。必要なサイズの2〜3倍にすると、1回の実行でその10倍のメモリを節約でき、時間も節約できます。これは、任意の配列ベースの構造(ハッシュテーブルとプレーン配列)で機能します。それを超えて、LinkedListのようなポインタベースの構造は、それらの欠点を回避できれば、この問題は発生しません。

于 2012-07-18T15:23:24.773 に答える