Android でのメモリ リークとメモリ オーバーフロー

1.メモリリーク

1. メモリリークの現象と本質

メモリ リーク ( Memory Leak) とは、一部のオブジェクトが使用されなくなったが、ガベージ コレクタによって再利用できず、依然としてメモリ空間を占有している現象を指し、これがこのメモリの一部のリークにつながります。

ガベージ コレクターが一部のオブジェクトを再利用できない理由は、これらのオブジェクトがまだ参照されているためです。したがって、メモリ リークの本質は、ライフ サイクルが短いオブジェクトがライフ サイクルが長いオブジェクトによって参照され、ライフ サイクルが短いオブジェクトがガベージ コレクタによって時間内に回収されないことです。

2. メモリ リークの危険性:

少量のメモリ リークは大きな影響を与えません. リークされたメモリが大きくなり、使用可能な空きメモリがどんどん少なくなると、GC (ガベージ コレクション メカニズム) がトリガーされやすくなり、GC が発生すると他のスレッドが停止します.作業中のため、インターフェイスがフリーズするなどの原因となる可能性があります。

メモリ リークの累積では、多数のメモリ リークが累積すると、メモリ オーバーフローが発生する可能性があります。

3. Android に関連するメモリ リーク

Android アプリケーションでは、メモリ リークについて次の点に注意する必要があります。

(1) static の使用を減らす: static キーワードによって変更されたメンバー変数のライフ サイクルは、アプリケーション プログラムのライフ サイクルと同じです.大量に使用すると、メモリ空間を占有し、使用できなくなります.解放されます. 累積すると、継続的なメモリ オーバーヘッドが発生します. ; また、あまりにも多くのリソースを消費するインスタンス (Context など) を参照する static メンバー変数は避ける必要があります. Context を参照する必要がある場合は、Applicaiton の Context を使用します.

(2)外部クラス参照を保持する非静的内部クラス (匿名内部クラス) を避ける:非静的内部クラス (匿名内部クラス) はデフォルトで外部クラスへの参照を保持しますが、静的内部クラスは保持しません。Handler、AsyncTask (AsyncTask の最下層が Handler)、マルチスレッド (Runnable インターフェイスの実装、Thread クラスの継承) のメモリ リークは、この種のメモリ リークに属します. この場合、静的内部クラスのメソッド +弱参照を使用する必要があります。

(3)登録後の時間内に登録解除: BroadcastReceiver、Service、 ContentObserver、EventBus などは、登録後に対応するライフ サイクル メソッドで登録解除する必要があります。

(4)リソース オブジェクトは、使用後に時間内に閉じられます。データベース操作中のカーソル、ファイルの読み取りと書き込み時の IO ストリーム 、およびその他のオブジェクトは閉じられません。

(5) Bitmapオブジェクトが使用されていない場合は、recycle() を呼び出してメモリを解放します。Bitmapは多くのメモリを消費し、Bitmap をさらに使用するとJavaヒープの制限を一度に超える可能性があります。したがって、ビットマップが使い果たされると、時間内にリサイクルする必要がありますrecycle はBitmapのメモリをすぐに解放することはできませんが、ガベージ コレクターの次の作業時にビットマップをリサイクルします。

(6)非アプリケーションコンテキストはシングルトンモードでは参照されません: シングルトンの静的な性質により、そのライフサイクルはアプリケーションのライフサイクルと同じくらい長いため、アクティビティのコンテキストが適切に参照されていない場合、メモリ リークが発生するため、シングルトン モードのコンテキストはアプリケーションのコンテキストを参照する必要があります。

4. メモリ リーク分析ツール:

(1) 静的コード解析ツール lint: メモリ リークを引き起こす可能性のあるコードを検出するために使用できます. 通常、プログラミング時には、lint によって引き起こされるさまざまな黄色の警告に注意してください.

(1) Android Studio に付属の Android Profiler: Android Studio 3.0 以降の Android Profiler は、Android Monitor ツールに取って代わります。

(2) オープンソースのleakcanary:.

二、メモリオーバーフロー

メモリ オーバーフロー ( Out Of Memory: OOM ) は、アプリケーション アプリケーションによって使用されるメモリが、システムによって指定された最大値を超えることを意味します。Android システムには、各アプリケーションが使用できるメモリの上限があり、メモリ アプリケーションがこのしきい値を超えると、OOM クラッシュが発生します。 

1. Android でのメモリ オーバーフロー

(1) ListView の項目の再利用に注意:

初期に使われていたListViewは手動でアイテムを再利用する必要があり、そうしないと素早くスライドすると大量のItemViewが生成され、ガベージコレクターがメモリを回収する時間がなく、OOMが発生する可能性があります(これも主な理由です) ListView が RecyclerView に置き換えられた理由);

(2) 画像の読み込みに注意してください:

a . 複数の画像をロードする場合:複数の画像をロードする場合、通常、3 レベルのキャッシュ (メモリ キャッシュ、ローカル キャッシュ、ネットワーク キャッシュ) を使用して画像をロードします。キャッシュを使用すると、次の読み込みが速くなる可能性があるため、メモリに一定量の画像キャッシュを保持しておくと、次に画像が表示されるときの速度が向上します。しかし、あまりにも多くのビットマップ オブジェクトをメモリに保存することはできません。そのため、通常は LRUCache アルゴリズムを使用して画像をメモリに保存し、その数を一定の範囲内に制御します。

b. 大きな長い画像のロード:画像が非常に大きい場合、プログラムはロードされるとすぐに OOM になり、アプリケーションは第 3 レベルのキャッシュを使用する前にクラッシュします。したがって、大きな画像を表示するには特別な処理が必要です。画像は非常に大きいですが、この画像に表示する必要があるコントロールは非常に小さい場合があります。最初に画像の幅と高さを取得し、次にこの画像を表示する必要があるコントロールの幅と高さを取得し、次に画像とコントロールのズーム率を取得します。最後に、1 つの画像のメモリ使用量を削減するために、画像のサンプリング レートがズーム比に従って設定されます。
    BitmapFactory.Options options = new BitmapFactory.Options();
    //只得到图片的大小,不去加载图片的内容
    options.inJustDecodeBounds = true;
    Bitmap boundBitmap = BitmapFactory.decodeFile(filePath,options);
    int imageWidth = boundBitmap.getWidth();
    int imageHeight = boundBitmap.getHeight();
    //计算 inSampleSize 的值 此时可以根据控件大小和图片大小来得到缩放比例 这里先写成 2
    options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一
    options.inJustDecodeBounds = false;
    Bitmap bitmap = BitmapFactory.decodeFile(filePath,options);

おすすめ

転載: blog.csdn.net/beita08/article/details/127717728