Oops, forgot the plain text. 

The beanutils package does not contain any notion of dynamic class loading.
It is very possible that in an application the beanutils package will be in
a class loader that is a parent of the beans that it loads.
In that case, there can potentially be more than one instance of the same
bean class (coming from different child class loaders).
Also when the classes are reloading (by replacing the child class loaders),
the cache still contains instances of the old Class objects.
This prevents garbage collection of the old class loader. It cannot be
garbage collected unless all its classes are freed.

As a minimum, the descriptor cache (PropertyUtils.descriptorsCache) should
use the Class object of the bean as the key to the table and not the name of
the class (which is a String). There also must be an API function to clear
the cache, so advanced users can synchronize it with their class loading
(Doesn't tomcat have similar problem?)

I added another advice for EJB users at the end.

The code can be something like:

// In PropertyUtils:

    public static void clear() {
        descriptorsCache.clear();
        mappedDescriptorsCache.clear();
    } 

    public static PropertyDescriptor[] getPropertyDescriptors(Object bean) {

        if (bean == null)
            throw new IllegalArgumentException("No bean specified");

        // Look up any cached descriptors for this bean class
        PropertyDescriptor descriptors[] = null;
        descriptors =
            (PropertyDescriptor[]) descriptorsCache.get(bean.getClass());
        if (descriptors != null)
            return (descriptors);

        // Introspect the bean and cache the generated descriptors
        BeanInfo beanInfo = null;
        try {
            beanInfo = Introspector.getBeanInfo(bean.getClass());
        } catch (IntrospectionException e) {
            return (new PropertyDescriptor[0]);
        }
        descriptors = beanInfo.getPropertyDescriptors();
        if (descriptors == null)
            descriptors = new PropertyDescriptor[0];
        descriptorsCache.put(bean.getClass(), descriptors);
        return (descriptors);

    }

EJB users that have a class deployed in more than one JAR (and therefore
more than one instance in the VM) can try that:
First, do the code change above. This is supposed to work, but still have a
potential memory leak for not garbage collecting the ClassLoader objects
(they can be very big).
Since the classes will be loaded more than once, every time a new class
loader will load them it will invoke the static initializers.
You can put in ONE of your EJB classes a static initializer that will get
the cache hashtable and clear it.

class MyBean implements javax.ejb. .... {

    static{
        PropertyUtils.clear();
    }
// other EJB functions
}

Make sure that this happens once per jar. Meaning, if your JAR contains 10
EJBs, only one class should have this static block.
I did not try that, so this is just a suggestion.

E

Reply via email to