3

我有一个正在尝试解决的设计问题。简而言之,是否可以使用finalize()释放private static仅与该对象相关的资源,并且仅在该对象存在时才使用?详情如下...

首先是约束:

  1. 我正在使用装饰器模式来封装X我没有编写的类型()

  2. X如此final子类化它是不可能的。

  3. 我在包装器中有一个方法,比如说x(),它随时都会返回底层X instance

  4. 原因x()是包装器类型需要与期望X 参数的现有 API 互换兼容

  5. 包装器有一个将X实例作为参数的构造函数。然后它将其封装的X对象设置为此实例。

问题:

我想在包装器中添加一些功能/数据,保留它。我的意思是,当包装器“解包”到 时X,它可以在代码中的其他位置被“重新包装”到包装器,嘿,即使它没有在底层中携带,额外的数据也会被恢复X.

到目前为止我的想法:

如果我在包装类中创建一个静态映射,其中键是唯一的Xid,值是某种结构中的额外数据,那么我可以在rewrap(X x)方法中检索它,比如说。

我不会使用包装器或X对象作为映射中的键,因为这将阻止它被 GC 处理(除非从映射中明确删除),因此我们将使用唯一的哈希码。

虽然这在原则上似乎没问题,但问题是何时从静态地图中删除这些额外数据。在这种情况下,我们可以允许 finalize() 的实现:

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

这是我的理由......我们都知道依赖 finalize() 来释放资源通常是一个坏主意,但这里所讨论的资源直接与对象相关。没有对外部资源的引用,因此我们需要这些内部资源,直到包装对象本身被 GC'd,此时我们只需删除资源映射。

最坏的情况是不用担心删除这些冗余的静态映射,因为这会导致内存泄漏。

我想不出任何其他方法来实现此功能并保持与现有 API 的向后兼容性:

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

所以这就是问题所在,还有其他方法或意见吗?

非常感谢

编辑: 经过进一步研究,我想我会更新这个问题,因为类似的情况可能是弱参考的主要候选者

4

1 回答 1

0

如果您每次需要访问 X 实例时都显式调用 Wrapper.x,难道您不能在 Wrapper 中添加一个清理方法并在删除 Wrapper 对象之前显式调用它吗?

也可以从finalize调用 cleanup 方法,以确保在未显式调用时将其清理。这将为您提供两全其美的效果,因为如果 Wrapper 使用不当,您将有更大的机会减少内存泄漏。

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 回答