7

私はメモリリークを追跡し、Androidのバインダーがどのように実装されているかについて私が真実だと思うことを確認したいと思います。この場合、それぞれ独自のプロセスでサービスとアクティビティがあります。ipcメソッドを介してアクティビティからサービスにコールバックオブジェクトを渡し、要求されたタスクでサービスが完了したときにコールバックを呼び出すことができるAIDLを作成しました。

長い間、私は疑問に思っていました。新しいコールバックオブジェクトをサービスに渡し、アクティビティにコールバックオブジェクトへのポインターを保持しない場合、ガベージコレクターが先に進んでアクティビティにコールバックを収集しないのはなぜですか。処理する?それは起こらないように思われるので、JVMは、アクティビティでコールバックをガベージコレクションするタイミングをどのように知るのでしょうか。

答えは、BinderシステムがActivityプロセスのCallbackへのポインターを保持し、Serviceプロセスの対応するCallbackオブジェクトがfinalize()メソッドを呼び出すまで、ポインターを解放するメッセージをActivityに送信することだと思います。これは正しいです?そうでない場合、それはどのように機能しますか?

私はそうだと信じており、アクティビティのコールバックが非常にメモリを大量に消費するものを指している場合、サービスのコールバックが収集されるまで収集されないという興味深い状況につながります。サービスのメモリが不足していない場合、コールバックが長期間収集されず、アクティビティにOutOfMemoryErrorが発生するまでコールバックがアクティビティに蓄積される可能性があります。

4

2 に答える 2

7

ユーリーはかなり正しいです。

My Serviceは、コールバックを保持するスレッドを開始し、スレッドの作業が完了すると、コールバックを呼び出してスレッドを終了します。コールバックが呼び出されると、アクティビティでわずかな作業が行われ、その時点で、アクティビティプロセスにコールバックへのポインタがない状態に戻る場合があります。

ただし、アクティビティ内のコールバックオブジェクトは、サービス内の対応するコールバックオブジェクトがガベージコレクションされるまで、Androidのバインダーシステムによって引き続きポイントされます。

アクティビティプロセスのコールバックオブジェクトが、大量のメモリを消費する他のオブジェクトを支配している場合、正当な理由もなくアクティビティプロセスのメモリを浪費しており、OutOfMemoryErrorが発生する可能性もあります。解決策は、コールバッククラスに単純なメソッドを作成してdestory()、コールバックのすべてのフィールドをnullにし、コールバックが終了したときにそのメソッドを呼び出すことです。

コールバッククラスが非静的内部クラスである場合は、静的内部クラスに変更してコンストラクターで親クラスを渡すことを検討してください。この方法で、destory()メソッドでもそれをnullにすることができます。

これは興味深い考えをもたらします。非静的内部コールバッククラスの親クラスがActivityであり、コールバックがバインダーを介して送信された後、コールバックされる前に構成の変更(画面の回転など)が発生した場合、コールバックは、実行時に古いActivityオブジェクトを指します。

更新:Binder.java内でこのコードを発見しました。もちろん無効になっていますが、Javadocでこの種のコードについて言及されていれば良かったでしょう。

    if (FIND_POTENTIAL_LEAKS) {
        final Class<? extends Binder> klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                (klass.getModifiers() & Modifier.STATIC) == 0) {
            Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }
于 2012-05-19T19:30:23.440 に答える
1

Binderがどのように機能するかを正しく理解していれば、あなたの場合の問題は次のとおりです。着信呼び出しごとに、Service は個別のスレッドを作成します。オブジェクトをこのスレッドに渡すと、Binder システムはスレッド用のオブジェクトのローカル コピーを作成します。したがって、 Service メソッドが結果を返すまで、オブジェクトのコピーを持つスレッドは引き続き機能します。

これを確認するには、(DDMS で) Service プロセスのスレッドを確認してください。

于 2012-01-26T21:16:01.180 に答える