• 検索結果がありません。

OutOfMemoryError 避けが悪影響だけ出している

第 1 章 駄目コードとその対策 6

1.11 OutOfMemoryError 避けが悪影響だけ出している

ServiceCon-nection

のリークに繋がります。この例では

Service

bind/unbind

するタイミングは

on-Start()/onStop()

を使用していますが、

onCreate()/onDestroy()

onPause()/onResume()

など、

Activity

のライフサイクル上で必ず通る組み合わせを使用するとリークを回避すること

ができます。

Eclipse

の場合、このプラグインをインストールすると、

DDMS

パースペクティブの

Dump

HPROF file

ボタンを押すとダンプしたメモリを解析できるようになります。

1.2 Dump HPROF fileボタン

たとえば次のような無駄に大きな

byte

配列をもつ

Activity

の解析をしてみましょう。メン バ変数として

16MB

byte

配列を保持しています。

リスト1.34: LargeBytesActivity.java

public class LargeBytesActivity extends ActionBarActivity { private byte[] mLargeBytes = new byte[16 * 1024 * 1024];

@Override

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

} }

この

16MB

byte

配列をメモリリークの原因ということにして、

MAT

を使って追ってみ ましょう。

まず最初に

Dump HPROF file

ボタンを押します。すると図

1.3

のような画面が表示され ます。この画面ではおおよそメモリを大きく使用しているクラスが何であるのかが円グラフ で表示されます。

1.3 Memory Analyzerの初期表示

今回はメモリを大きく保持しているクラスが何であるかを確認したいので、ヒストグラムを 表示します。ヒストグラムを表示するには図

1.4

のヒストグラムのボタンを押します。

1.4 Create a histogramボタン

すると図

1.5

のように、各クラスのインスタンスの数と、どれだけメモリを占有している かが表示されます。今回の場合では

byte

配列が一番大きくメモリを占有しているのがわかり ます。

1.5 Histogram

次に

byte

配列のインスタンスを個別に見てみましょう。図

1.6

のように右クリックのメ ニューの

List objects

からインスタンスの一覧を表示できます。

1.6 List objects

リストの

Retained Heap

で並べ替えると図

1.7

のように一番大きい、

16MB

byte

配列 を見つけることができました。

1.7 16MBbyte配列

次にこの

byte

配列はどこから参照されているのか、そしてなぜ

GC

によって回収されない のかを調べます。調べるには右クリックのメニューから

Path to GC Roots

を選択すること で解析できます。

1.8 Path to GC Roots

解析結果は図

1.9

のようになります。するとこの

16MB

byte

配列は、

mLargeBytes

と いう変数名で

LargeBytesActivity

というクラスが保持していることまで特定できました。

1.9 リーク原因の特定

OutOfMemoryError

が発生したとき、仮説を立てて修正し、再発するかを確認する方法が

ありますが手間がかかります。

MAT

を使えばどのクラスがどれだけのメモリを専有し、それ が何故

GC

によって回収されないのかを特定することができます。実際にメモリリークが発 生している場合も同じような手順で特定することができます。

駄目なコードでは原因を特定せず、そこら中で使い終わった変数に

null

を代入していたり しますが、結局根本的な解決になっておらず、

null

落ちや可読性の低下に陥っているのを見か けます。仮説を立て修正することも大切ですが、

MAT

のように使えるツールがあるので、ま ず解析を行い原因を特定してから修正をするようにしましょう。