1

私のアプリの単純化されたバージョンには、A と B の 2 つのアクティビティがあります。アクティビティ A は B を開始し、いくつかの作業の後、B は finish() を呼び出します。ほとんどのデバイス (4.2 を実行する Galaxy Nexus、4.0.4 を実行する Droid 4、および 2.3.4 を実行する Droid 2) でメモリ アナライザー ツールを使用しても、アクティビティ B の痕跡は表示されません。

しかし、4.1.1 を実行している Samsung S3 では、次の GC ルートへのパス (弱い/ソフト参照は除外) により、MAT はアクティビティ B オブジェクトを表示します。

Class Name                                                        | Shallow Heap | Retained Heap
-------------------------------------------------------------------------------------------------
com.myCo.myApp.ActivityB  @ 0x42720818                            |          264 |         3,280
|- <Java Local> java.lang.Thread @ 0x4271cf60  Thread-21941 Thread|           80 |        52,264
|- mOuterContext android.app.ContextImpl @ 0x426adf68             |          104 |           784
    |  '- mContext android.media.AudioManager @ 0x428e49a0        |           48 |           152
-------------------------------------------------------------------------------------------------

アクティビティ B を開始および停止するたびに、MAT はアクティビティ B のメモリ フットプリントの別のインスタンスを表示します。また、アクティビティ B を開いたり閉じたりするほど、logcat で報告されるメモリ フットプリントが大きくなります。MAT を使用して GC を強制しても、アクティビティ B メモリへの参照は削除されません。

3 つの質問があります。

  1. デバイスによってメモリ/GC の動作が異なるのはなぜですか?

  2. S3 では、OS は最終的に戻ってきて、取り残されたアクティビティ B オブジェクトを GC します (つまり、Android がクラッシュする前にクリーンアップするので、心配する必要はありません)。

  3. そうでない場合、Thread と AudioManager の参照はどこから来ているのですか?どうすればクリアできますか?

経験豊富な「リークハンター」に感謝します!

4

1 に答える 1

2

更新:アクティビティBによって残された「取り残された」メモリが実際に問題であるかどうかを確認するために、アクティビティAとBの間にループを作成しました。

--- A calls startActivityForResult() on B
--- B calls finish()
--- onActivityResult() in A calls B again, etc...

私はそれを約15,000回の反復で飛行させましたが、プログラムはクラッシュしませんでした。したがって、この電話とOSバージョン(Samsung S3、4.1.1)のJVMは、メモリにクラスBへの参照を残しますが、アクティビティBがfinish()を呼び出した後でも、後で何らかのクリーンアップが行われるようです。 Bクラスへの参照の数は、テスト中に単調に増加しませんでした。

実際、テスト中にいくつかのヒープダンプを生成しましたが、Bクラスのインスタンスが約100を超えることはありませんでした。これは、他にクリーンアップがないかどうかを確認する15kとは対照的です。logcatのGCステートメントは、アクティビティBの呼び出しが多数あるにもかかわらず、メモリ使用量が上下することも示しています。

私の結論は、finish()呼び出し後のヒープダンプにクラスB参照が存在することを心配する必要はないということです。これは、この電話/Androidバージョンで使用されるJVMが何らかの遅延クリーンアップを実行するように見えるためです。

注:これは私が実行したテストに基づく私の推測です。誰かが別のことを知っている場合は共有してください。ありがとう!

于 2013-01-22T14:23:37.830 に答える