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

いくつかのアプローチを試しましたが、どれも問題を解決しませんでした。
- Bitmap.Config.ALPHA_8を使用
- ガベージコレクションと呼ばれるOutOfMemoryErrorをキャッチして再試行( GCUtilsでスパイ )
- ビットマップをJavaヒープの外側に配置するオプションは考慮しませんでした。 幸運なことに、 フレスコはまだ存在していませんでした
私たちは間違った道を歩いた
問題はビットマップのサイズではありませんでした。 メモリがほぼ完全に使用されている場合、OOMはどこでも発生します。 もちろん、ビットマップなどの大きなオブジェクトの割り当て中にこれが発生する可能性は高くなります。 OOMは、メモリリークというより深刻な問題の症状です。
メモリリークとは何ですか?
多くのオブジェクトの寿命は限られています。 ライフタイムが終了すると、ガベージコレクターによって収集されることが期待されます。 リンクのチェーンがメモリ内のオブジェクトを指している場合、オブジェクトのライフタイムの予想される完了後に、これはメモリリークを作成します。 一定量のリークが蓄積すると、プログラムはメモリ不足になり始めます。
たとえば、Activity.onDestroyが呼び出された後、アクティビティ、ビューの階層全体、および関連するビットマップがガベージコレクションに使用できるようになります。 バックグラウンドスレッドが動作中にアクティビティへのリンクを保持している場合、そのスレッドが占有していたメモリは解放できません。 遅かれ早かれ、これはOutOfMemoryErrorをスローします。
リークハント
メモリリークのハンティングは手動プロセスであり、RaizlabsのWrangling Dalvikによる一連の記事で詳しく説明されています。
主な手順は次のとおりです。
- Bugsnag 、 Crashlytics、または開発者コンソールを使用して 、OutOfMemoryErrorクラッシュについて学習します
- 問題を再現してみてください。 クラッシュしやすい特定のデバイスを購入、借用、または盗む必要がある場合があります(すべてのリークがすべてのリークを示すわけではありません!)。 また、おそらくは総当たりで、リークにつながる一連のアクションを復元する必要があります。
- OutOfMemoryErrorでメモリをダンプします( ここで方法を確認できます)。
- MATまたはYourKitを使用してメモリダンプを調べ、ガベージコレクターによって収集されるはずだったオブジェクトを見つけます。
- オブジェクトからガベージコレクターのルート(GCルート)までの最短パスを見つけます。
- あるべきではないリンクを見つけて、メモリリークを修正します。
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をインストールしてください !