I have a design issue I am trying to resolve. In short, is it ok to use finalize() to release private static resources that pertain only to that object, and are only of use for as long as that object lives? Details follow…
First here are the constraints:
-
I am using the decorator pattern to encapsulate a type (
X) that I
didn’t write -
Xisfinalso subclassing it is out of the question. -
I have a method in the wrapper, say
x(), that at any time will
return the underlyingX instance -
The reason for
x()is that the wrapper type needs to be
interchangeably compatible with existing API’s that expect anX
parameter -
The wrapper has a constructor that takes an
Xinstance as a
parameter. It then sets its encapsulatedXobject to be this
instance.
The problem:
I want to add some functionality/data in the wrapper, BUT have it preserved. By this I mean, when the wrapper is ‘unwrapped’ to X, it can then be ‘rewrapped’ to the wrapper at some other point in the code, and hey presto, the extra data is restored even though it is not carried in the underlying X.
My thoughts so far:
If I create a static map in the wrapper class where the key is a unique X id, and the value is this extra data in some structure, then I can retrieve it inside the rewrap(X x) method let’s say.
I won’t use the wrapper or X object as the key in the map as this will stop it ever possibly being GC’d (unless explicitly removed from the map), so instead we’ll use unique hashcodes.
Whilst this seems OK in principle, the issue is when to delete this extra data from the static map. In this case can we permit an implementation of finalize():
finalize(){
map.remove(wrapperKey);
}
Here’s my justification… We all know relying on finalize() is a bad idea to release resources in general, but here the resources in question pertain directly to the object. There is no reference to external resources, and so we need these internal resources until the wrapper object itself is GC’d, at which point we just delete the resources mapping.
The worst case scenario would be not worry about deleting these static mappings that are redundant, as this results in memory leaks.
I can’t think of any other way to achieve this functionality and preserve the backwards compatibility with existing APIs:
public void foo(Wrapper wrapper){
bar(wrapper.x());
}
public void bar(X instance){...}
So that’s the problem, any alternative approaches or opinions?
Many thanks
EDIT:
After further research I thought I would update this question as similar situations may be prime candidates for weak references
If you explicitly call Wrapper.x every time you need access to the X instance, couldn’t you add a cleanup method to Wrapper and explicitly call that before getting rid of the Wrapper object?
The cleanup method could be called from finalize too, to ensure that it gets cleaned up if it hasn’t been called explicitly. This would give you the best of two worlds, as it would give you a greater chance of reducing memory leaks if the Wrapper is used incorrectly.
Edit: Added code sample!