Androidアプリケーションでのメモリリークの追跡

実際、この記事はこのトピックの続きです: Androidアプリケーションのメモリ分析 。 この問題を詳細に研究したい人は誰でも歓迎されます。



さあ行こう...



この記事で説明したツールを使用してメモリの状態を分析することは非常に必要かつ有用なことですが、これを行うことが常に便利で適切であるとは限りません。

サードパーティのツールを使用せずにメモリリークを追跡できれば、経験の浅いテスターでもコンピューターにアクセスしなくてもメモリリークを見つけることができれば便利です。



方法



WeakReferenceクラスの機能が役立ちます。

以下は、メモリリークの追跡に役立つクラスの例です。 このクラスはオリジナルのふりをしておらず、おそらく誰かがプロジェクトで似たようなものを使用している可能性もあります。 明らかな理由で、クラスは単純化され、わずかに変更されましたが、その主な機能を実行します。 利便性を高めるために、少なくとも「リーク」オブジェクトの数を結果リストに追加できるとしか言えません。



package com.company.product; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Vector; import android.content.Context; import android.content.Intent; import android.text.TextUtils; public class LeaksManager { private static LeaksManager mThis = null; private final Vector<WeakReference<Object>> mRefs = new Vector<WeakReference<Object>>(); private LeaksManager() { super(); } public static LeaksManager getThis() { if (mThis == null) { mThis = new LeaksManager(); } return mThis; } public <T> T monitorObject(T obj) { if (obj == null) { return obj; } for (WeakReference<Object> ref : mRefs) { if (ref.get() == obj) { return obj; } } mRefs.add(new WeakReference<Object>(obj)); return obj; } public Vector<String> checkLeaks() { System.gc(); Vector<String> names = new Vector<String>(); for (int i = mRefs.size() - 1; i >= 0; i--) { WeakReference<Object> ref = mRefs.elementAt(i); Object obj = ref.get(); if (obj != null) { String className = obj.getClass().getSimpleName(); addUniqueClassName(names, TextUtils.isEmpty(className) ? "Unknown class name" : className); } else { mRefs.remove(i); } } mRefs.trimToSize(); return names; } private void addUniqueClassName(Vector<String> names, String className) { int index = -1; for (int j = 0; j < names.size(); j++) { if (names.elementAt(j).equals(className)) { index = j; break; } } if (index == -1) { names.add(names.getClass().getSimpleName()); } } }
      
      







使い方



まず、 LeaksManager.checkLeaks()



関数によって返される行のリストを取得して表示する簡単なアクティビティを作成する必要があります。 このアクティビティは非常に単純なので、そのコードを引用することにはあまり意味がありません。



次に、追跡する必要がある各オブジェクトを次のようにLeaksManagerに追加します。

Object obj = LeaksManager.getThis().monitorObject(new Object());









さらに、あなたにとって都合の良い場所で、メモリリークのリストを使用してアクティビティコールを行い、リストが空の場合はすべて問題ありませんが、このアクティビティ自体を数回起動した後でも何かが残っている場合、それは考える機会です。



一般に、これが実行される必要があるすべてです。



コメント



作成されたすべてのオブジェクトを追跡することは意味がありません-ほとんどのオブジェクトは状況依存であるため、各アクティビティ、サービス、および場合によってはストリームコンストラクターのonCreate()でmonitorObject()を呼び出すだけで十分です。



このクラスは、 この記事で説明したツールを使用する必要性を排除するものではありませんが、開発者とテスターがメモリリークを簡単に制御できるようにします。 私が参加するプロジェクトでは、各自明なサブミッションの前に、メモリリークに対してこのような「クイック」テストを行うのが一般的です。ほとんど時間はかからず、リリース前に問題を特定することなく、すぐに問題を検出できます。



PS



この記事が誰かに役立つことを願っています。

この記事が興味深い場合は、次の記事でAsyncTaskクラスのトリッキーな機能について説明します



All Articles