ImageView にセットした Bitmap はどうなるのか(3)

前回は、ImageView に貼り付けられた Bitmap の参照が外されて、Android によって自動的にメモリーが回収されるところまでみた。

では、ImageView で利用する Bitmap は recycle() メソッドを呼ばなくてよいのか。実際にアプリケーションを作っていると、Bitmap を recycle() し忘れるとOutOfMemoryError が出るのだから、recycle() は呼ばなくてはならないはずだ。

Bitmap.recycle() メソッドを呼び出さなければならない理由は、Android の開発ガイド、Managing Bitmap Memoryに記述がある。以下、概略である。

Bitmap のデータはどこに格納されるか

Android 2.3.x 以下の場合、Android はピクセルデータを Bitmap オブジェクトとは隔離された状態で native memory に格納する。Android 3.0以降の場合、ピクセルデータと Bitmap オブジェクトは関連づけられており、Dalvik heap に格納する。
※Dalvik heap は、アプリケーションが動作する Dalvik 仮想マシンのヒープ領域、native memory は、Android の OS が管理するメモリー領域。

簡単に言うと、Android 2.3.x 以下の場合は、アプリケーションから Bitmap オブジェクトのピクセルデータを格納するメモリーを管理できない。Android 3.0 以降は可能になったということになる。

OutOfMemoryError エラーはなぜ起きるか

Android 2.3.x 以下の場合、Bitmap のピクセルデータは native memory に格納する。Bitmap.recycle() メソッドは、Android にピクセルデータが解放可能であることを伝えるが、ピクセルデータが実際にいつ解放されるかは、アプリケーションには分からない。メモリーが足りなくなると、仮想マシンは GC(garbage collection)を実行するが、そのときにメモリーが解放されるとは限らないようだ。

Bitmap 利用後に recycle() メソッドを呼び出しておかないと、Bitmap のピクセルデータが native memory に残ったままになり、GC を実行しても必要なメモリーを確保できずに OutOfMemoryError になる可能性がある。つまり、Bitmap が不要になったら、出来るだけ早く recycle() メソッドを呼び出し、native memory のピクセルデータを解放しておくことが望ましいということになる。

Android 2.2.x 以下の場合、GC はアプリケーションのスレッドを止めて行われ、Bitmap の参照が外されているだけでは、native memory のメモリーは解放されないようだ。Android 2.3.x 以降で、concurrent garbage collection が追加され、Bitmap の参照が外されていれば、recycle() メソッドを呼び出した場合と同じ状態になるという記述がある。

recycle() メソッドを呼び出すべきか

Android 2.3.x 以下を対象とするのであれば、recycle() メソッドは呼び出しておいた方がよいだろう。recycle() メソッドを呼び出せば、可能な限り早く使用している native memory を解放できる。まだ、Android 3.0以降のみ対象(ってことは、現実的には Android 4.0以降になるでしょうね)にするには時期が早いので、ほとんどの場合 recycle() メソッドは忘れずに呼び出さなければならないということになるだろう。

Android 3.0以降のみ対象にするのであれば、recycle() メソッドを呼び出さなくても良さそうなのだが、呼び出さなくてよいという記述がない。メモリーを再利用する方法や、SoftReference が紹介されているだけだ。もっとも、記述しているコードを見る限りでは、recycle() メソッドを呼び出さなくてもよさそうだ。Android 4.0以降のみを対象とするアプリケーションを作る機会があったら、試してレポートしたいと思う。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Time limit is exhausted. Please reload CAPTCHA.