OutOfMemoryErrorの対策方法につきまして

3,681 views
Skip to first unread message

Ryo_andorid

unread,
Jan 19, 2011, 1:43:26 AM1/19/11
to 日本Androidの会

初めて投稿させていただきます。Ryoと申します。


画像系アプリケーションを作成しているのですが、
稀にOutOfMemoryErrorが発生し、対応に苦慮しております。

===========

public static boolean mRun = true;

public static TestImageDraw( String [] FilePaths )
{

int i = 0;
String FilePath;

while(mRun)
{
FilePath = FilePaths[i];

// 画像処理(後述)
LoadImage( FilePath );

// 1秒間スリープ
try
{
Thread.sleep(1000); // 1秒間停止
}
catch (InterruptedException e)
{
// 処理なし
}

// カウンタ処理
if( i > 10 )
{
i = 0;
}

}

Log.d("----- TestImageDraw End -----");

}

public static void LoadImage( String FilePath )
{

Bitmap bmImage;
File file;

// ファイル読み込み
file = new File(FilePath);
bmImage = BitmapFactory.decodeFile(file.getPath()); // この処理で
OutOfMemoryが発生する

// 描画処理

// 開放処理
bmImage.recycle();
bmImage = null;

System.gc();

}

===========

※発生時のDDMS/Logcatのエラーメッセージ

ERROR/dalvikvm-heap(14964): 4608000-byte external allocation too large
for this process.
ERROR/GraphicsJNI(14964): VM won't let us allocate 4608000 bytes
DEBUG/skia(14964): --- decoder->decode returned false
WARN/dalvikvm(14964): threadid=8: thread exiting with uncaught
exception (group=0x4001d7e0)
ERROR/AndroidRuntime(14964): FATAL EXCEPTION: Thread-9
ERROR/AndroidRuntime(14964): java.lang.OutOfMemoryError: bitmap size
exceeds VM budget
ERROR/AndroidRuntime(14964): at
android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
ERROR/AndroidRuntime(14964): at
android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:459)
ERROR/AndroidRuntime(14964): at
android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:271)
ERROR/AndroidRuntime(14964): at
android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:296)

おおよその処理内容とエラーは上記の通りになります。

エラーが発生する箇所は「BitmapFactory.decodeFile」の箇所で、
発生時にDDMSからLogCatにて確認すると、Java/DalvikよりHeapMemoryが
確保できなかったとのエラーが発生しています。

発生頻度は不確定で、上記の状態で一晩実行させても
エラーが発生しないこともあれば、3~4回目のループで
発生することもあります。


解決方法や情報などございましたら、お知恵を拝借できませんでしょうか。


以上、宜しくお願いいたします。

飯塚康至

unread,
Jan 19, 2011, 2:31:54 AM1/19/11
to android-g...@googlegroups.com
こんにちは、飯塚です。

手抜きですみません。
http://www.google.co.jp/search?aq=f&sourceid=chrome&ie=UTF-8&q=OutOfMemory%E3%80%80Android

・recycleをつかう
・画像を縮小て読み込む
・ARGB_4444を使う

といったところだと思います。

2011年1月19日15:43 Ryo_andorid <sheena....@gmail.com>:

> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
> このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
> このグループから退会するには、android-group-j...@googlegroups.com にメールを送信してください。
> 詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにアクセスしてください。
>
>

--
以上、宜しくお願いします。

飯塚 康至

Ryo_andorid

unread,
Jan 24, 2011, 8:20:42 PM1/24/11
to 日本Androidの会

Ryoと申します。

遅くなりました。お返事ありがとうございます。


発生条件や状況などを調査していたのですが、
以下の内容がわかりました。

・画像処理のため、それなりに大きいサイズのファイルまたは
 テンポラリメモリ領域を、取得または開放していると発生する。
 (おおよそ2MB以上のファイルを扱ったときに出やすい)

・発生時のjava heapメモリの状態を確認すると、要求サイズ以上の
 空き領域があるように見える。

-----

Runtime r = Runtime.getRuntime();
long max = 0, total = 0, free = 0;
int retry_count = 10;
boolean retry_flg = true;

do
{
try
{
Log.d("Read Bitmap","bmImage");
bmImage = BitmapFactory.decodeFile(file.getPath());
retry_flg = false;
}
catch(OutOfMemoryError e)
{
System.err.println("Catched");

// java情報を取得
max = r.maxMemory(); total = r.totalMemory(); free =
r.freeMemory();
Log.e("OutOfMemoryError " , "max=" + max + "B. " + "total="
+ total + "B. " + "free=" + free + "B. " + "used=" + (total - free) +
"B.");

retry_count--;
e.printStackTrace();

// 50msec sleep
f_effect_sleep(50);

System.gc();

// 50msec sleep
f_effect_sleep(50);

if(retry_count == 0)
{
return null;
}

}

} while(retry_flg);
-----

LogCat出力ログの例:
01-24 06:14:22.671: ERROR/OutOfMemory(XXX): max=25165824B.
total=18816992B. free=9734856B. used=9082136B.

上記のコードでOutOfMemoryをキャッチしたときに、変数freeのサイズが
要求サイズより大きいことが確認できました。

java heapメモリに空きはあるのに、確保できないといった状況です。

このような現象の情報をお持ちの方いらっしゃいませんでしょうか?


以上、宜しくお願いいたします。




On 1月19日, 午後4:31, 飯塚康至 <iiz...@acl-inc.co.jp> wrote:
> こんにちは、飯塚です。
>
> 手抜きですみません。http://www.google.co.jp/search?aq=f&sourceid=chrome&ie=UTF-8&q=OutOfM...
>
> ・recycleをつかう
> ・画像を縮小て読み込む
> ・ARGB_4444を使う
>
> といったところだと思います。
>
> 2011年1月19日15:43 Ryo_andorid <sheena.andr...@gmail.com>:
> 飯塚 康至- 引用テキストを表示しない -
>
> - 引用テキストを表示 -

みせつ

unread,
Jan 25, 2011, 7:29:32 AM1/25/11
to android-g...@googlegroups.com
現象への情報はないですが、
気になるところだけ。

outofMemoryが発生した後では、
メモリが開放済みなのでは?

この関数で取れる値が、
outofMemoryと直接関係しているのか?
(ネイディブヒープは、含むか否か)

わし(H&A-lab)

unread,
Jan 25, 2011, 7:08:51 AM1/25/11
to 日本Androidの会
はじめましてです。わしです。

いつもROMってばかりのはずかしがりやさんです・・・。

上記、OutOfMemoryですが、Dalvikヒープの制限にかかっていると思います。
Androidが監視すべきメモリは、JavaヒープとDalvikヒープがあり、Dalvikヒープは、一つのプロセスに
最大(たしか)24MB(Android標準)の制限がつきます。
なので、Javaヒープに余裕があっても、Dalvikヒープで制限にひっかかったものかと。

的外れなこと書いてたらすいません。
Reply all
Reply to author
Forward
0 new messages