LeakCanary-メモリリーク検出アシスタント

OutOfMemoryErrorでクラッシュするのが好きな人はいない



Square Registerで作業し、ビットマップキャッシュを使用してクライアントの署名を描画します。 このビットマップはデバイスの画面サイズであるため、作成中に多くのOutOfMemoryクラッシュが発生しました。



画像



いくつかのアプローチを試しましたが、どれも問題を解決しませんでした。







私たちは間違った道を歩いた





問題はビットマップのサイズではありませんでした。 メモリがほぼ完全に使用されている場合、OOMはどこでも発生します。 もちろん、ビットマップなどの大きなオブジェクトの割り当て中にこれが発生する可能性は高くなります。 OOMは、メモリリークというより深刻な問題の症状です。



メモリリークとは何ですか?





多くのオブジェクトの寿命は限られています。 ライフタイムが終了すると、ガベージコレクターによって収集されることが期待されます。 リンクのチェーンがメモリ内のオブジェクトを指している場合、オブジェクトのライフタイムの予想される完了後に、これはメモリリークを作成します。 一定量のリークが蓄積すると、プログラムはメモリ不足になり始めます。



たとえば、Activity.onDestroyが呼び出された後、アクティビティ、ビューの階層全体、および関連するビットマップがガベージコレクションに使用できるようになります。 バックグラウンドスレッドが動作中にアクティビティへのリンクを保持している場合、そのスレッドが占有していたメモリは解放できません。 遅かれ早かれ、これはOutOfMemoryErrorをスローします。



リークハント





メモリリークのハンティングは手動プロセスであり、RaizlabsのWrangling Dalvikによる一連の記事で詳しく説明されています。



主な手順は次のとおりです。







OOMの前であってもすべてを実行でき、メモリリークの修正に集中できるライブラリがあった場合はどうでしょうか。



LeakCanaryの紹介





LeakCanaryは、デバッグビルドでメモリリークを検出するためのオープンソースJavaライブラリです。



次の例を見てみましょう。



class Cat { } class Box { Cat hiddenCat; } class Docker { static Box container; } // ... Box box = new Box(); Cat schrodingerCat = new Cat(); box.hiddenCat = schrodingerCat; Docker.container = box;
      
      







次に、RefWatcherオブジェクトを作成し、追跡するオブジェクトを提供します。



 //    schrodingerCat   ( ).   . refWatcher.watch(schrodingerCat);
      
      







リークが検出されると、適切なリークトレースを取得できます。

 * GC ROOT static Docker.container * references Box.hiddenCat * leaks Cat instance
      
      







お客様が常に新しい機能を実行していることがわかっているため、インストールは非常に簡単になりました。 1行のコードで、LeakCanaryはアクティビティリークを自動的に検出します。



 public class ExampleApplication extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); } }
      
      







良好な状態で通知を受け取ります:



画像



おわりに





LeakCanaryの使用を開始した後、アプリケーションで多くのリークを検出して修正しました。 Android SDKにいくつかのリークが見つかりました



結果は驚くべきものです:94%少ないOutOfMemoryErrorクラッシュ!



画像



OOMのクラッシュを取り除きたい場合は、 LeakCanaryをインストールしてください



All Articles