1

次のような AIDL インターフェースを備えたサービスがあります。

interface Bar {

    void doStuff();
    // ...
    void destroySelf();
}

interface Foo {

    // ...
    Bar createBar();
}

サービスの実装では、スタブは作成されたスタブFooのリストを維持し、スタブでが呼び出されると、このインスタンスはリストから削除されます。BarBardestroySelf()

破棄されたBarインスタンスをクライアントから呼び出せないようにしたいのですが、どうすればよいですか?

このクライアント コードは例外をスローしません。

Bar bar = foo.createBar();
bar.destroySelf();
bar.doStuff();  //I want that to go "boom"

Binder実装を調べたところdestroy()、メソッドから呼び出されるネイティブ メソッドがありますfinalize()が、それはガベージ コレクターが起動することを決定したときにのみ呼び出されます。クライアントがインスタンスのメソッドを呼び出したときにインスタンスにアクセスできるようにBinder、インスタンスへの参照が保持されていないかどうかさえわかりません。BarStub

4

1 に答える 1

0

BarStubバインダーのものがインスタンスへの参照を保持し、いつでもそれらにアクセスできると言うとき、あなたは正しいです。事実上、Binderオブジェクトはシステム全体でガベージコレクションされるため、プロセスがそれらにアクセスできない場合にのみ存在しなくなります。

私は2つのオプションを提案します:

  • destroySelf()オブジェクトを実際に破壊するものとは考えないでください。代わりに、オブジェクトを非アクティブな状態にします。次に、他のすべてのメソッド呼び出し(たとえばdoStuff())でオブジェクトの状態を確認し、オブジェクトが非アクティブ状態の場合はエラーを返します。
  • さらに良いこと、Android Binderの設計に反対するのではなく、その設計を使用してください。クロスプロセス参照カウントは、おそらくまさにあなたが望むものです。具体的には、これを行います。
    • 削除するdestroySelf()
    • サービス内で、への参照を保持しないでくださいBar
    • Barが破壊されたことをサービスが本当に知っている場合は、それを呼び出すことができますlinkToDeath。しかし、私はあなたがそれ以外の方法でそれへの参照を保つことができるとは思わない、さもなければそれは決して破壊されないだろう。
于 2013-03-15T08:36:14.433 に答える