4

問題は、明らかにメモリ リークを引き起こす static final 定数の使用に関するものです。Android アプリでメモリ リークを引き起こさない方法に関する情報を探しています。大きな問題の 1 つは、定数に private static final を使用することです。どうやらそれが定数の定義方法です。ただし、 static final は、回転後にハングアップすることを意味し、アクティビティをクリアできないことを意味します。

明らかに私は何かを誤解しています。変数を Application コンテキストに配置すると、問題を引き起こすことなくぶらぶらすることができることを私は知っています。

メモリ リークに関する一般的な質問: メモリ リークに関する情報はたくさんありますが、すべての情報を明確にまとめたものは見つかりません。すべてが完全に説明されている推奨事項。

4

5 に答える 5

12

この情報は正しくありません。変数を static final にすると、static final とマークされたという理由だけで、いかなる種類のメモリ リークも発生しません。ただし、それによってメモリリークを作成できないと言っているわけではありません。絶対に避けたいことの 1 つは、コンテキスト型 (アクティビティなど) の静的変数を作成することです。コンテキストへの静的参照を作成すると、メモリ リークが発生する可能性があります。静的変数とは、アプリケーション全体およびそのクラスのインスタンス間で、その変数のコピーが 1 つしかないことを意味します。また、明示的にクリアされるか、アプリケーションがシャットダウンされるまで、メモリに残ることも意味します。静的変数はクラス レベルの変数であり、オブジェクトの特定のインスタンスには関連付けられません。たとえば、「public static final string myString = "Hello"」を作成する場合 メモリリークが発生することはありません。この方法で定数を定義すると、'public final string myString = "Hello"' を使用する場合と比較して実際にメモリが節約されます。これは、static を使用しないと、すべてのインスタンスに対して 1 つのコピーを保持するのではなく、このクラスのすべてのインスタンスに対してその文字列を格納するメモリ ロケーションが作成されるためです。使用する。

于 2012-04-04T19:51:47.793 に答える
5

Java では、静的変数はヒープ上に存在し、クラスのロード時に割り当てられます。インスタンス変数のガベージ コレクションの適格性は、そのインスタンスに関連付けられています。

値型 (int、bool、double など) の静的変数を使用しても、クラスのインスタンスはリークしません。非値型の静的変数を許可すると、これらの静的変数によって参照されるものはすべてリークする可能性があります。

簡単なクラスを考える

public class Activity extends Context {
    static int willNotLeakActivity = 0;
    static Context mayLeakActivity = new Context();

    //if you call activityA.leakyMethod(activityA); you will leak activityA
    public void leakyMethod(Context context){
        mayLeakActivity = context;
    }

    //this method won't leak the instance
    public void safeMethod(int arg){
        willNotLeakActivity = arg;
    }
}

Activity オブジェクトへの参照を (参照型が Context であっても) 静的変数に保持すると、Activity オブジェクトがリークします。

Android は実際の JVM ではなく、Dalvik VM で実行されることに注意してください。そのため、理論上は結果が異なる場合がありますが、GC の適格性に関する限り、Dalvik が異なることに非常に驚いています (私は自分で問題に遭遇することはありません)。

編集 - 質問をもう一度見てみると、これで理解が深まるかもしれないと思います。オブジェクトは、GC ルートから参照チェーンをたどって到達できる限り、ガベージ コレクションの対象にはなりません。アクティビティ オブジェクトは、Android プロセスによってインスタンス化され、正常に維持されます (これは、少なくともstatic void main(string[] args).

システムが yourActivityInstance.onDestroy() を呼び出して参照を解放すると、別の参照を介して GC ルートからアクティビティのインスタンスに到達できない限り、そのオブジェクト (およびその後、それが参照するすべてのオブジェクト) を GC する資格があります。この参照が保持されるべきよりも長く保持されている場合 (読み取り: 無期限)、GC はリークされたオブジェクトのリソースを安全に解放できるかどうかを確認できないため、このオブジェクトをリークしています。

この参照がどのように保持されるか (静的または非静的、最終的または非最終的) は問題ではありません。オブジェクトが GC ルート (少なくとも静的メソッドのローカル変数とスコープ内変数、ロードされたクラスの静的フィールド) から到達できる限り、リークが発生します。

于 2012-04-04T21:05:33.467 に答える
2

これは、Android のすべてのメモリ管理に対応し、メモリ リークの検出について詳しく説明している非常に優れたビデオです。あなたが求めているものとはまったく異なりますが、同じスレッドで言及する価値があります.

http://www.youtube.com/watch?v=_CruQY55HOk

于 2012-04-04T19:59:17.937 に答える
0

アクティビティ自体を参照していない場合、定数によってメモリ リークが発生することはありません。アクティビティで (文字列などの) 定数を使用しても問題はありません。

メモリ リークに関するトピックをキャプチャする 2 つの優れたリソースがあります。

  • ここの Android 開発者ブログからの説明
  • メモリ管理に関する Google IO プレゼンテーションはこちら
于 2012-04-04T19:55:50.113 に答える
0

静的定数は必ずしもアクティビティを保持するわけではなく、非常に標準的です。この問題は、アクティビティ (ビューやドローアブルなど) への参照を保持する static があり、そのアクティビティの意図された寿命を超えて存続する場合に発生します。

メモリ分析の適切な出発点は、こちらこちら、およびこちらです。また、ガベージ コレクションが一般的にどのように機能するかを調査するだけでも役に立ちます。

于 2012-04-04T19:56:06.487 に答える