On Jul 20, 2007, at 14:15, Jeremias Maerki wrote:

Another argument: Why did Chris have an OutOfMemoryError in the first
place that the fix for FixedLengthProperty solved?
The OutOfMemoryError doesn't happen anymore because not so many objects
are created to actually be filling the memory.

That was precisely the point, since:
a) specified properties very frequently have recurring values in the same document as well as over different documents. b) default/initial values are generally the same for a given property in all documents c) computed values for inherited properties are frequently identical on parent and child

Even if you render a million documents, there would always be one and only one FixedLength instance corresponding to an absolute computed value of 10pt, no matter if it is used for font-size, line-height, padding...

If the objects in the cache had been releasable, they would have been released
by the GC and Chris wouldn't have run into the OutOfMemoryError.

Depends on how you look at it:
I don't believe the reference to the value object that is held by the Map.Entry object itself is of issue here. However, since that is a strong reference (what the API doc means to say), then if the value would in turn /hold/ (not /be/) a reference to the key object, the references would become circular and the fact that the key is wrapped in a WeakReference does not do anything useful. If key and value are the same objects, there is no circular reference, hence no particular problem. The only strong reference to the key is then ultimately held by the *Map.Entry*, not the value object (which happens to be the key).

Could be I'm incorrect in my interpretation here. If I am, then the solution could still be pretty simple (as I see Adrian has already suggested):
replace put(key, value) with put(key, new WeakReference(value));

That would make sure that, even if the WeakHashMap implementation cannot resolve situations where one of its entries contains the only strong reference to the key --which I doubt to be the meaning of the note, but could be wrong--, the entries are always cleared when no objects outside the Map refer to the key.

Another note:
As to /when precisely/ an entry in a WeakHashMap /does/ get cleared by GC, that is guaranteed nowhere. The only guarantee is that "an entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use". So, it is not because there are no references to the key that the entry will be /immediately/ cleared, only that it becomes eligible for collection in the next GC cycle.

This could make it JVM-dependent, and may perhaps explain why I could not reproduce the bug.... Some JVMs are better at collecting obsolete objects held in static Maps than others. If this is a deciding factor, I'd only expect this to be a problem in older versions (less advanced GC algorithms).

I'm also thinking, maybe the fact that instances corresponding to default/initial values are, in turn, cached by the static PropertyMakers in FOPropertyMapping causes carry-over of instances into other runs.

(check:
 PropertyMaker.make(PropertyList) {
   if (default != null) {
     return default;
   } else {
     ...
     default = p;
   }
)

That would make instances corresponding to an initial value indeed non-collectable once FOP has processed one document. Unless when there are disastrous bugs like the one in FixedLength, nothing alarming, since those instances will be used many times over after that.


FWIW: I agree very much that the caches should probably be made global in another way, either tie them to the FopFactory somehow, or to a specific rendering run, as you suggest. The first would have the benefit of being able to re-use the same NumberProperty instance in different subsequent renderings.

I experimented a bit with a Map of (Class->Map) mappings, where the key in the outer map is the Property-subclass, and the inner Map contains the canonical instances for that type of Property. As I remember this was quite slow (presumably due to the increased number of lookups), so I decided not to employ that particular strategy.

That said, I'm still very open to suggestions.


Cheers

Andreas

Reply via email to