3

解決しようとしている設計上の問題があります。つまり、そのオブジェクトにのみ関係し、そのオブジェクトが存続している間だけ使用できるリソースfinalize()を解放するために使用しても大丈夫ですか?private static詳細は次のとおりです...

まず、制約は次のとおりです。

  1. デコレータパターンを使用して、X記述しなかったタイプ()をカプセル化します。

  2. Xサブクラス化されているfinalので問題外です。

  3. ラッパーにメソッドがあります。たとえばx()、いつでも基になるメソッドを返します。X instance

  4. その理由は、ラッパータイプは、 パラメーターx()を期待する既存のAPIと互換性がある必要があるためです。X

  5. ラッパーには、Xインスタンスをパラメーターとして受け取るコンストラクターがあります。次に、カプセル化Xされたオブジェクトをこのインスタンスに設定します。

問題:

ラッパーにいくつかの機能/データを追加したいのですが、それを保持しています。つまり、ラッパーが「ラップX解除」されると、コード内の他のポイントでラッパーに「再ラップ」される可能性があります。つまり、余分なデータは、基になるデータに含まれていなくても復元されます。X

これまでの私の考え:

キーが一意のIDであり、値が構造内のこの追加データであるラッパークラスで静的マップを作成するXと、メソッド内でそれを取得できますrewrap(X x)

ラッパーまたはオブジェクトをマップのキーとして使用しません。Xこれにより、GCが実行される可能性がなくなるため(マップから明示的に削除されない限り)、代わりに一意のハッシュコードを使用します。

これは原則として問題ないように見えますが、問題は、静的マップからこの余分なデータをいつ削除するかです。この場合、finalize()の実装を許可できますか?

finalize(){
   map.remove(wrapperKey);
}

これが私の正当な理由です...finalize()に依存することは、一般にリソースを解放するのは悪い考えですが、ここでは、問題のリソースはオブジェクトに直接関係しています。外部リソースへの参照がないため、ラッパーオブジェクト自体がGCされるまでこれらの内部リソースが必要です。その時点で、リソースマッピングを削除するだけです。

最悪のシナリオでは、冗長なこれらの静的マッピングを削除する必要はありません。これにより、メモリリークが発生するためです。

この機能を実現し、既存のAPIとの下位互換性を維持する他の方法は考えられません。

public void foo(Wrapper wrapper){
  bar(wrapper.x());
}
public void bar(X instance){...}

それが問題です、代替のアプローチや意見はありますか?

どうもありがとう

編集:さらに調査した後、同様の状況が弱参照 の主要な候補である可能性があるため、この質問を更新すると思いました

4

1 に答える 1

0

Xインスタンスにアクセスする必要があるたびに明示的にWrapper.xを呼び出す場合、Wrapperにクリーンアップメソッドを追加し、Wrapperオブジェクトを削除する前に明示的に呼び出すことはできませんか?

クリーンアップメソッドは、明示的に呼び出されていない場合に確実にクリーンアップされるように、finalizeから呼び出すこともできます。これにより、ラッパーが誤って使用された場合にメモリリークが減少する可能性が高くなるため、2つの世界の最良のものが得られます。

void someRandomMethod() {
    Wrapper someWrapperINeed = new Wrapper(new X(blah, blah blah));
    foo(someWrapperINeed);
    someWrapperINeed.clean();

    // Instead of foo(new Wrapper(new X(blah, blah, blah));
}

// Or foo can call clean if the wrapper will never be needed after its invocation
void foo(Wrapper w) {
    bar(w.x());
    w.clean();
}

編集:コードサンプルを追加しました!

于 2013-01-03T11:04:19.167 に答える