2012-02-17 12 views
3

私は仕事をするためにメモリ集中型のプログラムを手に入れようとしていて、メモリエラーに陥っていました。私は他のスレッドを読んだことがあります。それらはすべてメモリリークについて語りますが、私はそれがここに当てはまるとは思わないのです。Android OutOfMemoryでもメモリをスペアにする

1メガバイトの領域を割り当て、メモリ使用量をメガバイト(maxmem、totalmem、freemem)で表示するボタンを作成しました。最初は(40,5,2)、ボタン(40,6,2)を押します。私はボタンを押し続け、(40、7、2)、(40、8、2)、(40,9,2)、そしてOutOfMemoryを得る。私は(40、10、2)を期待して、OutOfMemoryを私が(40,40、0)のヒットまで得るべきではないでしょうか?

int[][] hi = new int[100][]; 
int i = 0; 

public void save(View view) { 
    hi[i] = new int[256*1024]; 
    i++; 
    TextView tv1 = (TextView) findViewById(R.id.seekBar1Text); 
    System.gc(); 
    tv1.setText("Memory is max " + Runtime.getRuntime().maxMemory()/1024/1024 + " total " + Runtime.getRuntime().totalMemory()/1024/1024 + " free " + Runtime.getRuntime().freeMemory()/1024/1024); 
} 
+1

CommonsWareは、Androidのメモリ測定で正しいかもしれません。私のアプリにこのボタンが表示される直前に、ビットマップARGBフォーマットに写真を読み込みます。これは約20MBのメモリを必要としますが、このメモリは「総メモリ」よりも大きいです。ビットマップは数えられませんでしたが、まだスペースを取っていたと思います。この写真を読み込まないと、40MBのうち約38MBまで、さらに多くのメモリを割り当てることができました。 –

答えて

3

私はDianne Hackborn's definitive answer on Android memory measurementRuntimeメソッドを使用していないことに注意してください。したがって、私はそれらを信頼するかどうかわかりません。まずは、40MBのヒープサイズのAndroid搭載端末がないことが分かりました。

また、OutOfMemoryErrorは、完全にメモリ不足であることを意味しているようです。 OutOfMemoryErrorは、割り当てが試行されなかった場合に発生します。それはあなたが求めるサイズの単一のフリーブロックが存在しないためである可能性があります。これは、Dalvik VMのGCルーチンの性質のため、他のオペレーティングシステムと比べてAndroid上で発生する可能性が高くなります。

1

JVMでは、大きな構造体をテナントスペースに直接配置します。可能であれば、このスペース(またはその断片化されたもの)のサイズを変更すると、十分な空き領域があるにもかかわらず、これらの構造の空き容量が足りなくなります。場合によっては、VMのチューニングが役立つことがあります。

2

興味深い問題です。私はこれをさまざまなAndroidバージョン(エミュレートされた)で遊んでいて、自分のマシンで試してみました。 Android 3.1では期待していた動作(メモリがいっぱいになってからクラッシュする)を見ることができますが、2.2ではその動作を示しています。

@CommonsWareは、あなたが要求する膨大なメモリブロックと関係している可能性が高いと言います。私のマシンでも、4 * 256 * 1024要素の配列を割り当てることはできません(この配列はインデックス可能なので、何とか連続しています)。

最も良い解決策は、少ないメモリを割り当てるのではなく、同じ時間ではなく割り当てることです。 Android 2.2では、16 * 1024のブロックを使って問題なくメモリをいっぱいにすることができます。

正確な解決方法は、アプリケーションの仕様によって異なります。たとえば、

  • 受信データを処理している場合は、メモリ内のデータ量を少なくし、ストリーム処理を使用することができます。
  • 本当にデータが必要な場合は、異なる構造(連続ブロックを必要としない構造)を検討することができます。
  • その他すべてが失敗した場合は、連続したメモリブロックの印象を与えるヘルパークラスを作成し、実際に小さな部分にチャンクすることができます。私のエミュレータ上で
0

(API 10に設定されている)私はこれを使用:

Runtime rt = Runtime.getRuntime(); 

rt.gc(); // cause garbage collection for better accuracy 

int[][] i = new int[4024][2014]; // a blob from hell to cause OOM crash and Force Close 

long max = rt.maxMemory(); // max that can be allocated (more than max gets you OOM crash) 

long total = rt.totalMemory(); // this is total in use, not total possible 

long free = rt.freeMemory();  

long used = (total - free); 

s = "RAM:" + String.format("%.0fKB, %.0fU, %.0fF", 
          max/1024.0, used/1024.0, free/1024.0); 

ブロブ+アプリは、エミュレータの24メガバイトの上限よりもわずかに大きかったので、私は、クラッシュを得ました。 私はまだ完全にメモリの問題を取得しません。 Android/Javaの世界は、メモリの面でLinux/Cの世界より複雑だと思われます。

関連する問題