メモリリークとは何ですか
メモリ リークとは、プログラム内で動的に割り当てられたヒープ メモリが解放されないか、何らかの理由で解放できないことを意味します。その結果、システム メモリが無駄に消費され、プログラムの実行速度の低下やシステム クラッシュなどの重大な結果につながります。
上記はメモリリークに関する公式声明です。簡単に言うと、解放すべきメモリが正常に解放されなかった場合、メモリリークとなります。プログラムでメモリ リークが発生すると、少なくとも実行速度に影響を与えるか、メモリ オーバーフローによりプログラムがクラッシュする可能性があります。
メモリ不足 (OOM) とは、リサイクルできないメモリの存在、またはアプリケーション システムで使用されるメモリが多すぎることを指し、最終的にプログラムの実行に使用されるメモリが提供可能な最大メモリを超えてしまいます。
したがって、プログラムにメモリ リークの疑いがある場合は、それに注意を払う必要があります。
メモリリークを特定する方法
メモリ リークの危険にさらされているプログラム内のコードを見つけるには、コードを手動でレビューしてメモリ リークを見つけて解決することもできます。また、adb コマンドを使用して関連ステータスを観察することもできます。また、プロファイラーを使用することもできます。 Android Studio が提供するそれらを検出するツール。
アクティビティのメモリ リーク検出の使用法
主に使用されるプロファイラーモジュール:
ページ漏洩事件:
2 つのアクティビティを作成します。1 つはデフォルトのアクティビティ A、もう 1 つはデモのアクティビティ B です。A は B を開始し、Return キーを押して B ページを終了します。B のコードは次のとおりです。
class ProfilerMainActivity : AppCompatActivity() {
companion object {
//定义一个静态变量,引用Activity实例
var refAct: ProfilerMainActivity? = null
}
private lateinit var student: Student
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profiler_main)
//让静态变量一直持有当前实例
refAct = this
student = Student()
student.sayHello()
}
}
次に、最初にプロファイラー ツールのキャプチャ ヒープ ダンプを使用して、メモリ ヒープ データの一部をキャプチャします。
A が B を開始した後:
この時点ではまだ正常です
B出口
ページ B を終了したら、セクションを再クロールします。
アクティビティの ondestroy ライフ サイクルが完了したことがわかります。論理的には、ページは破棄され、オブジェクトはメモリ内に存在し続ける必要はありません。オブジェクトは上記の静的変数によって参照され、GC が実行されました。オブジェクトを解放できません。
問題をシミュレーションする
上記のページで操作を完了します。
class ProfilerMainActivity : AppCompatActivity() {
//省略。。。。
override fun finish() {
super.finish()
refAct = null
}
}
上記の取得手順を繰り返して、メモリ データを再度取得します。
オブジェクトがまだメモリ内に存在していることがわかりますが、誰もそれを参照していないため、次回 GC がガベージ コレクションを行うときにリサイクルされます。ここでは、推測が正しいかどうかを確認するために、GC にガベージ コレクションを直接強制的に実行させています。
クロール
ProfilerMainActivity インスタンスがメモリ内に表示されなくなっていることがわかります。
Java/Kotlin 割り当ての記録の使用
主に、一定期間内のヒープ内のオブジェクトの数と破棄時間を記録します。
上記のコードを引き続き使用して、今度は Student オブジェクトを調べ、操作 A–》B–》A–》B を実行してから、ガベージ コレクションを複数回強制的に実行します。
上の図を見ると、Student が 2 回作成されているため、プロセス全体で 1 と 2 の合計 2 つのオブジェクトが記録されています。これらの違いは、1 の Dealloc Time が空ではないことと、Student であるためインスタンスの詳細がないことです。初めてページを開始します。ページ B を作成して終了した後、GC によってリサイクルされました。全体のアクティブ時間は 1 秒 05 ミリ秒でした。ただし、2 の Dealloc Time は空ではなく、リサイクルされていないことを示しています。スタック情報このオブジェクトの内容はインスタンスの詳細に記録され、ヒープ内でまだアクティブです。全文では、Android 開発でよく遭遇するメモリ リークの問題と、プロファイラー ツールを使用してそれらを検出する方法について説明しています。Android パフォーマンス最適化に関連するその他のテクノロジについては、 「Android パフォーマンス最適化分析」を参照してください。クリックすると、詳細なパフォーマンス最適化セクションが表示されます。
要約する
メモリ リークを簡単に確認できるように、プロファイラー ツールには、どのページがリークしたかをレポートするためのアプリ ヒープの表示カテゴリが用意されています。同時に、シングルトンなどの非ページ クラスが正常にリリースされているかどうかも確認できます。特定の関数を実行した後、手動でシングルトンを空 (「破棄」) に設定し、オブジェクトがまだアクティブかどうかを GC に強制的にチェックさせた後、メモリ データの一部を取得するだけで済みます。