RE: [OJB-developers] ObjectCache and IdentityFactory]
Brought to you by:
thma
From: Florian B. <bf...@fl...> - 2002-03-26 08:17:59
|
Hi Thomas, <snip> > > > <snip ObjectCache based solution for IdentityFactory> > > That is my intention, as the ObjectCache itself also has a memory leak > > problem that would be fixed by this. For each object in the > > HashTable a > > SoftReference is created that wraps the object. When the gc > > collects the > > object, the SoftReference object itself stays in memory. > > > > Oops, are you sure about that? Can't SoftReference objects be collected in > general, or is their collection simply deferred to the next run of the > garbage collector? I'm quite sure about the memory leak. SoftReference objects behave like all other objects, i.e. they are collected when there are no references to the objects left. Lets look at ObjectCacheImpl: public void cache(Identity oid, Object obj) { if ((obj != null)) { SoftReference ref = new SoftReference(obj); objectTable.put(oid.toString(), ref); } } This creates a new SoftReference with the object to cache being the referent of the SoftReference. The referent is subject to special handling by the GC, i.e. it can be collected if there are not other references to obj. The following code (in lookup) removes entries of the Hashtable where the values have been collected: if (ref != null) { obj = ref.get(); if (obj == null) { gcCount++; objectTable.remove(oid); } } If the entry is processed by this code the SoftReference will be gc'd because there is no reference left to it (normal gc behaviour). The problem is, when you have entries in the Hashtable that, at some point in time, get collected, but there is never ever again a lookup of the object. In this case the entry in the Hashtable remains and therefore a couple of objects (Identity, Map.Entry, SoftReference) remain in memory. Other implementations of such caches or WeakHashMap/SoftHashMaps work differently. They maintain an instance of java.lang.ref.ReferenceQueue and pass this instance to all created SoftReference/WeakReference objects. Whenever the referent of a Soft/WeakReference is collected, the SoftReference/WeakReference is added to the ReferenceQueue. Now, whenever you modify the map (by put, remove etc.) the ReferenceQueue is processed and the entries are removed. This leads to another typical issue in such implementations: Usually the KEY of the map is encapsulated in a Soft/WeakReference. This is done to make cleaning up efficient, because you can only access a map by keys, but has the disadvantage that not the objects that might be larger in size (usually the value) are collected if memory is running low. There are some other disadvantages with this approach (like entries never get thrown out when you do not modify a map over some time, unpredictable processing time of modification operations), and in general the more I look into these implementations the more I get the feeling that all of them contain somewhat ugly hacks that prevent them from being a reliable and calculable solution for a cache (i.e. efficient lookup, efficient in modification and retrieval of the cache, calculable and constant time of lookup and modification, ...) best regards, Florian |