サイトのトップへ戻る

Android Studio ドキュメント 日本語訳

サイト内検索

メモリーモニター

Android モニターにはメモリーモニターが搭載されているので、 より簡単にアプリのパフォーマンスとメモリ使用状況を監視できます。 それにより、未割り当てオブジェクトを見つけ、メモリーリークを検知し、接続された端末が使用しているメモリ量を追跡します。 メモリーモニターはあなたのアプリがどのようにしてメモリを割り当てているかを報告し、アプリが使用しているメモリの可視化を手助けします。 そのおかげで、あなたは以下のことができるようになります:

  • 使用可能なメモリと割り当て済みメモリのグラフを時間経過と共に表示します。
  • ガベージコレクション (GC)イベントを時間経過と共に表示します。
  • ガベージコレクションイベントの開始。
  • 過度なガベージコレクションイベントが原因でアプリの遅延が発生しているかどうかを素早くテストします。
  • メモリ不足が原因でアプリのクラッシュが発生しているのかどうかを素早くテストします。


メモリモニターを使った作業の流れ

メモリの使用をプロファイルして最適化するための典型的な作業の流れは、アプリを実行して以下を行うことです:

  1. メモリーモニターを使ってアプリをプロファイルし、望ましくないパターンのガベージコレクションイベントがパフォーマンス問題を引き起こしていないか調べます。
  2. 短時間に大量のガベージコレクションイベントが表示された場合は、Javaヒープをダンプ出力して、予期せぬもしくは不要な割り当てがされたままのオブジェクトタイプの候補を特定します。
  3. 割り当てトラッキングを開始して、コード上で問題が発生している箇所を特定します。

Java ヒープデータは、アプリケーションが割り当てたオブジェクトのタイプ、数、ヒープ上でのそれらのサイズをリアルタイムで表示します。 ヒープを見ると以下のことで役立ちます:

  • あなたのアプリがメモリの割り当てと解放をどのように行っているのかを理解する。
  • メモリリークを識別する。

割り当てトラッキングでは、アプリのメモリー割り当てを記録し、コールスタック・サイズ・割り当てコードを含むプロファイルサイクルの全ての割り当てを一覧表示します。 これは以下のことで役立ちます:

  • 大量の似たようなオブジェクトタイプが、(大体同じコールスタックから)非常に短時間で割り当てと割り当て解除されている場所を特定します。
  • コード上で非効率なメモリ使用の可能性がある場所を探します。


ガベージコレクションルートと支配ノードのツリー図

Java ヒープをダンプ出力した時、メモリーモニターはAndroid固有のHeap/CPU Profiling (HPROF) ファイルを作成します。 これはHPROF ビューア上で閲覧できます。 HPROF ビューアではガベージコレクションルートは GC Root icon アイコン(と0の深度)を付けて表示し、 支配ノードは Dominator icon アイコンを付けて表示します。

Javaにはいくつかの種類のガベージコレクションルートがあります。:

  • スタック上の参照
  • Java Native Interface (JNI) のネイティブオブジェクトとメモリー
  • static 変数とstatic 関数
  • 参照可能なスレッドとオブジェクト
  • ブートストラップローダーによって読み込まれたクラス
  • ファイナライザーとファイナライズされていないオブジェクト
  • busy monitor objects

HPROF ファイルはルートの一覧を HPROF ビューアへ提供します。

支配ノードのツリーは、アプリによって作成されたオブジェクトへのパスをトレースします。 あるオブジェクトを通って直接的にもしくは間接的に他のオブジェクトへ到達することができる場合、そのオブジェクトは到達先オブジェクトを支配する支配ノードです。 メモリ使用の最適化をするためにアプリによって作成されたオブジェクトやパスを調べる際には、不要になったオブジェクトは削除してみてください。 支配ノードを解放するとその全ての下位ノードを解放できます。例えば以下の図でオブジェクトBを削除した場合、Bが支配しているオブジェクトC, D, E, Fが使用しているメモリーも解放されます。 実際のところは、オブジェクト C, D, E, Fが削除対象としてマークされていてもオブジェクト Bがまだそれらを参照していた場合は、 それが理由でオブジェクト C, D, E, Fが解放されない可能性があります。




メモリリークと使用分析

アプリがメモリを効率的に使用して不要になったメモリを解放する場合、パフォーマンスは良くなります。 大きなメモリリークや時間と共に増大するメモリリークを修正することが最も重要です。

メモリ使用量の最適化を行うための方法の一つは、大きな配列型を分析することです。 例えば、配列内の個別要素のサイズを減らしてメモリーを節約することなんてできますか?

もう一つの注目すべき観点は、アプリでもう必要ないのに参照を続けているオブジェクトです。 異なる期間のヒープダンプを収集し、それらを比較してメモリリークが増大しているかどうか(コード上で複数回作成したが破棄していないオブジェクトなど)を判別します。 これらのオブジェクトは、例えば、動的に増える配列やオブジェクトツリーの一部の可能性があります。 この問題を洗い出すには、ヒープダンプを比較して、時間経過と共にインスタンスが増え続ける特定のオブジェクト型がないかを調べます。

ルートオブジェクトや支配ノードオブジェクトを含んだオブジェクトツリーが増大し続けると、下位のオブジェクトがガーベージコレクトされないことがあります。 この問題は、メモリリークやメモリ不足やクラッシュの一般的な原因となります。 アプリでは少数のオブジェクトによって多数の下位オブジェクトが破棄されるのを妨げていることがあり、その場合はすぐにメモリが不足してしまいます。 これらの問題を見つけるには、ヒープダンプを取得して、ルートオブジェクトや支配ノードオブジェクトによって保持されているメモリ量を調査します。 メモリが十分ある場合は、メモリ使用の最適化を開始する良い機会です。

メモリ問題の絞込みを始める際には、割り当てトラッカーも使ってメモリを食っているオブジェクトが割り当てられている場所をさらに把握する必要があります。 割り当てトラッカーは特定のメモリ使用を調べるだけでなく、読み込みやスクロールのような重要なコードパスを分析するのにも役立ちます。 For example, tracking allocations when flinging a list in your app allows you to see all of the allocations that need to be done for that behavior, what thread they are on, and where they came from. この情報は、これらのパスを絞り込んでアプリで必要な作業を減らし、UIの全体的な滑らかさ向上させるために非常に有用です。

不要な割り当てをするアルゴリズムや、同じオブジェクトを再利用せずに何度も作成する割り当てるアルゴリズムを調べるのが有効です。 例えば、あなたは一時的に使うオブジェクトや変数を再帰ループ内で毎回作成していませんか? 作成している場合、ループ内で使うオブジェクトや変数をループ前に作成しておくようにしてみてください。 さもないと、アプリでは再帰回数に応じて多くのオブジェクトと変数に不要な割り当てを行ってしまうかもしれません。

最大数かつ最大サイズのオブジェクトを作成するコード部分では、割り当てテストを行うことが重要です。 そういった場所は最適化する余地が最も多いのです。 ユニットテストに加えて、本物に近いデータを読み込んで(特にこれらデータ駆動型のアルゴリズムで)アプリをテストする必要があります。 また、アプリのキャシュ処理と起動フェイズを考慮するようにしてください。これらは場合によっては遅延を引き起こすからです ;正確な結果を得るには、これらのフェイズの後に割り当て分析を行うのがベストです。

コードを最適化したら、それが動作するかテストするようにしてください。 異なる負荷状況下で、メモリモニターツールは起動せずにテストをする必要があります。 最適化前と後の結果を比較して、パフォーマンスが実際に向上していることを確認してください。



異なる仮想マシンごとのメモリ管理

Android モニターは端末やエミュレーターが使用している仮想マシン (VM) を使います:

  • Android 4.3 (API level 18) 以下では Dalvik VMを使用します。
  • Android 4.4 (API level 19)では、Android RunTime (ART) VM がオプションで Dalvik VMが既定です。
  • Android 5.0 (API level 21) 以上では ART VMを使用します。

VM はガベージコレクションを制御しています。Dalvik VM はガベージコレクションにマーク・アンド・スイープ方式を使用します。 ART VM は、世代別ガベージコレクションとマーク・アンド・スイープを組み合わせて使用し、メモリの断片化がひどくなった時などメモリが必要な場合により大きなガベージコレクションを行います。 logcat モニターは、発生したガベージコレクションの種類とその理由を示すいくつかのメッセージを表示します。

メモリーモニターの結果は、VMごとに異なる場合があります。 結果として、あなたが両方のVMをサポートしている場合は両方でテストを行うと良いでしょう。 さらに、異なるAPI levelで使用できるVMは、API levelごとに異なる動作をする場合があります。 例えば、 Android 2.3 (API level 10)以下でのDalvik VMは外部に割り当てられたメモリを使用し、Android 2.4以上ではDalvikヒープ内のみで割り当てをします。

Dalvik VMと ART VMを再設定してパフォーマンスを調整することはできません。 その代わりに、アプリのコードを調べてその処理をどのように改善させるかを決める必要があります(例えば、非常に大きな配列のサイズを減らす、など)。

ベストプラクティスではありませんが、VMがガベージコレクションを実行するタイミングをプログラム上から操作する方法もあります。 これらの技術はVM固有のものです。詳細については ガベージ コレクション(GC)の問題への対応RAM使用状況を調査するを参照してください。

ART VM では、Dalvik VMに比べてパフォーマンス・開発・デバッグにおける改善点がいくつか追加されています。 詳細については ART と Dalvikを参照してください。



実行しているアプリをメモリーモニターに表示する

特定の端末やエミュレーター上で動作しているアプリをメモリーモニターに表示するには:

  1. 前提条件と依存関係の準備を完了させます。
  2. アプリプロジェクトを開きます。
  3. ハードウェア端末やエミュレータ上でアプリを実行します
  4. Android モニターを表示します
  5. Monitors タブをクリックして、 メモリーモニタを表示します
  6. Pause Pause iconをクリックしてメモリモニターを有効にし、それの選択を解除します。
  7. グラフにて、y軸は空きRAMと割り当て済みRAMをメガバイト単位で表示しています。 x軸は時間の経過を示しています。; 最初は○秒で始まり、その後○分○秒と進んで行くといった具合です。 空きメモリの量(メガバイト単位で計測)は明るい色で表示され、割り当て済みメモリは暗い色になります。 割り当て済みメモリの数値が一気に下がったタイミングは、ガベージコレクションイベントが発生したことを示しています。

    ガベージコレクションを強制実行するには、 Initiate GC Initiate GC iconをクリックします。

    以下の図では、VM が最初のガベージコレクションを開始し、開発者が二つ目のガベージコレクションを強制的に実行しています。

  8. アプリを操作して、その操作がメモリ使用量にどのような影響を与えるかをメモリーモニターで見てください。 アプリのガベージコレクションのパターンを把握し、それらが健全なものかどうか、あなたが想定した通りのものかを判断することができます。
  9. このグラフを使えば潜在的な問題を把握できます:

    • 過度なガベージコレクションイベントはアプリを遅延させます。
    • アプリのメモリが不足し、クラッシュの原因となる。
    • 潜在的なメモリーリーク。

    例えば、以下のような問題の兆候が表示されることがあります:

    • アプリを操作していないのに、モニター上には割り当て済みメモリーが表示される。
    • モニター上にはメモリ割り当ての乱高下が表示されているが、そのような動作を引き起こすアプリロジックを実装した覚えがない。
  10. メモリーモニターを停止するには、 Pause Pause icon を再度クリックしてそれを選びます。


ガベージコレクションイベントを強制実行する

ガベージコレクションは負荷が高いため、通常 VMは絶対に必要な時のみにガベージコレクションを実行します。 しかし、特定の状況ではガベージコレクションを強制的に実行できると便利です。 例えばメモリリークを検出する際、大きいオブジェクトの解放が正常に完了したかどうかを判別したい場合、いつもより多くガベージコレクションを実行することができます。

ガベージコレクションイベントを強制実行するには:



Java ヒープとメモリ割り当てのスナップショットを取得する

メモリモニターが動作したり停止したりしている間、スナップショットを取得することができます。 :