See below.

On Wed, 5 Sep 2001, Elli Albek wrote:

> Date: Wed, 5 Sep 2001 00:58:19 -0700
> From: Elli Albek <[EMAIL PROTECTED]>
> Reply-To: [EMAIL PROTECTED]
> To: [EMAIL PROTECTED]
> Subject: Re: BeanUtils and class loading + EJB comment
>
> how about this caching strategy:
>
> The class java.beans.Introspector is using the Class object as the cache
> hashtable key.

It is actually now a two level key -- effectively it is ClassLoader +
Class Name.  This is required to make sure that the same class, loaded
from a different class loader, has its own introspection informatio.

> This is fine, two Class objects with the same name but with different class
> loader do not return true for equals().

True ... they are totally independent of each other, and not even castable
or assignment compatible.

> If we use that as the key, than one cache can contain all the beans.

I agree that using the Class object itself as the key would be unique,

> The
> problem becomes when class loaders are created repeatedly, like in the case
> of JSP page development. In that case, if the programmers do not call the
> clear functions there will be a memory leak.
> What java.beans.Introspector is doing is to key by the Class, and have two
> flush functions, one for the entire cache, and one for a specific class.
> This can work here as well. If we need to flush by a class loader (I don't
> think it is necessary, repeated class loading happens only at development
> time, there is no real problem in nuking all the cache) it is still possible
> to iterate over all the keys and remove those that come from that class
> loader.
>
> Another option is to make the cache a WeakHashMap. In that case the class
> will eventually expire, and the class loader can be freed.
> I am not sure whether WeakHashMap or SoftRefHashMap is more suitable here.
> Since we deal with class objects, the issue is much more complicated. The
> class org.apache.commons.collections.SoftRefHashMap will not be helpful
> here. The cached values will expire, but the keys (the actual Class objects)
> stay in the map. In that case the class is still referenced and the
> ClassLoader cannot be garbage collected.
> java.util.WeakHashMap is also not a sure bet. The weak reference is supposed
> to be cleared after all other strong references are cleared. I am not sure
> how that can happen with Class Objects. The class loader will maintain a
> reference to them. The class loader cannot be released until all the Class
> objects are, but they are still reachable through a weak reference (so the
> class loader cannot release). This becomes a chicken and an egg problem.
>
> So I think the safest is to use the java.beans.Introspector approach, it
> seems the be the safest. I think using the class loader as a key might cause
> some unexpected behaviours, because of the parent child relationships of
> class loaders. probably the safest thing is to key by class and nuke the
> whole cache all together. Class loaders also do not implement hashcode() and
> equals(). This also makes them suspects for table keys. (though the Object
> class hashcode() and equals() are supposed to be enough in that case).
>

Nuking the entire cache is certainly feasible -- just call the clear
method with no arguments.  However, it seems to me that it's overkill in
most circumstances.  I don't see that the parent/child relationships would
make any difference - if I know that I'm throwing away a particular class
loader, I would want to throw away just the objects loaded by that class
loader, and keep the rest.  Hence, I think it is appropriate to offer both
method signatures (indpendent of whatever choice we make for the internal
representation).

Regarding using class loaders as keys, the features we need are that
* The same (class loader) object always returns the same hash code value
* No two (class loader) objects return the same hash code value

The first property is required by the contract for the hashCode() method,
so the default implementation in java.lang.Object will provide it.  The
second is not guaranteed, but in practice seems to be provided by JVMs I
have used when using arbitrary objects as keys.

That being said, keying a single-level cache by Class would solve this (as
long as java.lang.Class implements hashCode() and equals() correctly :-).

> E
>

Craig


Reply via email to