Perhaps I'm being a bit dim, but ... Why store the Property as a key and a value both? Just store "" as the value. You can still get a list of all the cached Property objects by calling keySet(). The entries in the Set returned may be WeakReference objects, but that's easily dealt with.
Just my 2 cents. -- Mark C. Allman, PMP -- Allman Professional Consulting, Inc. -- 617-947-4263 -- www.allmanpc.com On Fri, 2007-07-20 at 14:53 +0100, Adrian Cumiskey wrote: > Taking a look at the code and reading the spec :- > > public class PropertyCache { > > private Map propCache = Collections.synchronizedMap(new WeakHashMap()); > > > /** > * Checks if the given property is present in the cache - if so, > returns > * a reference to the cached value. Otherwise the given object is > added > * to the cache and returned. > * @param obj > * @return the cached instance > */ > public Property fetch(Property prop) { > > Property cacheEntry = (Property) propCache.get(prop); > if (cacheEntry != null) { > return cacheEntry; > } else { > propCache.put(prop, prop); > return prop; > } > } > } > > "Implementation note: The value objects in a WeakHashMap are held by > ordinary strong references. Thus care should be taken to ensure that > value objects do not strongly refer to their own keys, either directly > or indirectly, since that will prevent the keys from being discarded. > Note that a value object may refer indirectly to its key via the > WeakHashMap itself; that is, a value object may strongly refer to some > other key object whose associated value object, in turn, strongly refers > to the key of the first value object. One way to deal with this is to > wrap values themselves within WeakReferences before inserting, as in: > m.put(key, new WeakReference(value)), and then unwrapping upon each get." > > I have to agree with Jeremias, the value does need to be wrapped in a > WeakReference object when it is put() in the PropertyCache as the value > reference will be held as a strong reference as it directly holds the > same reference value as its key. > > This patch should single line patch should fix it. > > -- snip -- > Index: src/java/org/apache/fop/fo/properties/PropertyCache.java > =================================================================== > --- src/java/org/apache/fop/fo/properties/PropertyCache.java > (revision 555659) > +++ src/java/org/apache/fop/fo/properties/PropertyCache.java (working > copy) > @@ -19,6 +19,7 @@ > > package org.apache.fop.fo.properties; > > +import java.lang.ref.WeakReference; > import java.util.Collections; > import java.util.Map; > import java.util.WeakHashMap; > @@ -48,7 +49,7 @@ > if (cacheEntry != null) { > return cacheEntry; > } else { > - propCache.put(prop, prop); > + propCache.put(prop, new WeakReference(prop)); > return prop; > } > } > -- snip -- > > > Adrian. > > Chris Bowditch wrote: > > Jeremias Maerki wrote: > > > >> On 20.07.2007 12:51:33 Chris Bowditch wrote: > >> > >>> Jeremias Maerki wrote: > >>> > >>> > >>>> On 20.07.2007 11:52:15 Andreas L Delmelle wrote: > >>> > >>> <snip/> > >>> > >>>>>> In addition to that there was a bug in FixedLength.equals() that made > >>>>>> the caching effect-less: > >>>>>> http://svn.apache.org/viewvc?view=rev&rev=557934 > >>>>> > >>>>> That was the most likely cause. The equals() method returning > >>>>> false because of this, would keep on creating separate instances. > >>>>> How they would be leaked into a subsequent run is not quite clear > >>>>> to me, though... > >>>> > >>>> > >>>> Because of the bug in PropertyCache. The two bugs just add to each > >>>> other. > >>> > >>> Thanks for spotting this bug in FixedLength.equals(). I rebuilt > >>> fop.jar and started a fresh profiling session. After 5000 renderings > >>> with only 16Mb the heap is staying around 3Mb. The number of > >>> FixedLength and WeakHashMap$entry object is staying fixed at around > >>> 300. Hip Hip Hooray!!! > >> > >> > >> But you're running the same document over and over again, right? In that > >> case, the WeakHashMap doesn't grow because the cached instances are > >> always reused. That doesn't address the fact that the instances are > >> still not releasable. The memory leak is still there. That's why it's so > >> extremely important to be so damn careful about using static variables. > > > > You are right of course. So if we ran lots of different documents with a > > very high number of variations in FixedLength then the memory leak still > > exists. It does sound to me from what you've been saying about the > > WekHashMap that more work in this area is still needed. > > > > <snip/> > > > > Chris > > > > > > >