LeakCanary:AndroidおよびJava用のメモリリーク検出ライブラリ。
java.lang.<a href="http://javakk.com/tag/outofmemoryerror" title="查看更多关于 OutOfMemoryError 的文章" target="_blank">OutOfMemoryError</a>
at android.graphics.Bitmap.nativeCreate(Bitmap.java:-2)
at android.graphics.Bitmap.createBitmap(Bitmap.java:689)
at com.squareup.ui.SignView.createSignatureBitmap(SignView.java:121)
** OutOfMemoryError **のクラッシュが好きな人はいません
スクエアレジスタでは、ビットマップキャッシュにクライアントの署名を描画します。このビットマップはデバイスの画面のサイズであり、作成時に大量のメモリ不足(OOM)のクラッシュが発生しました。
いくつかの方法を試しましたが、どれも問題を解決しませんでした。
- Bitmap.Config.ALPHA_8を使用します(署名には色は必要ありません)。
- OutOfMemoryErrorをキャッチし、GCをトリガーして、数回再試行します(GCUtilsに触発されています)。
- Javaヒープからビットマップを割り当てることについては考えていません。まだラッキーではありません。
間違えました
ビットマップサイズは問題ではありません。メモリがほぼいっぱいになると、OOMはどこでも発生する可能性があります。この状況は、大きなオブジェクト(ビットマップなど)が作成される場合に発生する可能性が高くなります。OOMは、より深刻な問題の症状です:**メモリリーク**。
メモリリークとは何ですか?
一部のオブジェクトの寿命は限られています。作業が完了すると、ガベージコレクションが行われます。予想される存続期間が終了した後、参照チェーンがオブジェクトをメモリに保存すると、メモリリークが発生します。これらの脆弱性が蓄積すると、アプリケーションのメモリが使い果たされます。
たとえば、Activity.onDestroy()が呼び出されると、そのビュー階層とそれに関連付けられたビットマップはガベージコレクタブルである必要があります。バックグラウンドで実行されているスレッドがアクティビティへの参照を保持している場合、対応するメモリを再利用することはできません。これにより、最終的にOutOfMemoryErrorがクラッシュしました。
メモリリークを特定する
メモリリークの検出は手動のプロセスです。重要な手順は次のとおりです。
- Bugsnag、Crashlytics、または開発者コンソールを介してOutOfMemoryErrorがクラッシュする方法について説明します。
- 問題を再現してみてください。クラッシュした特定のデバイスを購入、借用、または盗む必要がある場合があります。(すべてのデバイスがリークするわけではありません!)また、暴力が原因である可能性のあるリークを引き起こしたナビゲーションシーケンスを把握する必要があります。
- OOMが発生したら、ヒープをダンプします。
- MATまたはYourKitを使用して、ガベージダンプを検索し、ガベージコレクションする必要のあるオブジェクトを見つけます。
- 強い参照から最短経路を計算します。
- パスに存在してはならない参照を見つけて、メモリリークを修正します。
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のインスタンスを作成し、監視するオブジェクトを指定します。
// We expect schrodingerCat to be gone soon (or not), let's watch it.
refWatcher.watch(schrodingerCat);
リークが検出されると、自動的にリークトレースが取得されます。
* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance
あなたが機能を書くのに忙しいことを私たちは知っているので、私たちは簡単にセットアップできます。LeakCanaryは、たった1行のコードで、アクティブなリークを自動的に検出します。
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}
}
箱から出して通知と素敵なディスプレイが表示されます。
結論として
LeakCanaryを有効にした後、アプリケーションで多くのメモリリークを見つけて修正しました。AndroidSDKにもいくつかの脆弱性が見つかりました。
結果は素晴らしいです。現在、OOMエラーによって引き起こされるクラッシュは94%減少しています。
OOMのクラッシュを排除したい場合は、今すぐLeakCanaryをインストールしてください。