On 02/27/2009 01:15 PM, Bob Lee wrote:
On Fri, Feb 27, 2009 at 11:04 AM, David M. Lloyd <david.ll...@redhat.com> wrote:
A couple use cases, off the top of my head:

1) I've got a set of FooBars that associate with Classes; now for whatever
reason, I want to change the FooBar that is associated with the Class.  The
old FooBar is now completely unreferenced; keeping a reference to it is a
leak.

What's a FooBar? Use cases should be concrete. :-)

2) I've got an application server deployment that provides some kind of
service by class, so I stash refs on the ClassLoaders of the Classes for
whom the service is provided.  I want to undeploy my application, but all
those classloaders have strong refs to my deployment.  They all have to be
cleared or you face a OOM: PermGen after a few redeployments.  In this case
I'd use a stop() + finalize() on my service which clears them.

Can you provide more detail? It sounds to me like you're saying that
the service impl classes are in the parent class loader and the server
(that binds the services) is in the child class loader, but from my
experience, it's usually the other way around.

It comes back to the whole point of the exercise. Using JBoss Marshalling as a concrete use case -

WeakHashMap<Class<?>, Externalizer>()

*fails* because Externalizer instances are usually customized to the class they externalize (which, by the way, could well be a system class). This means that Externalizer keeps a strong ref to the Class after all.

So we need a map with weak keys -> weak values, and a way to associate a strong ref from the Class. This covers the case of the Class going away. But if the deployment containing the Externalizer goes away? It's a leak, and a big one (it includes the whole classloader of the Externalizer implementation, not to mention the classloader of Externalizer.class itself) unless we can remove the reference somehow. Even if you attempt to work around it by using an intermediate object from the system classloader, like an Object[1], to hold the references, and you manually keep a Set of them and clear them all out on redeploy, you've still leaked an Object[1] on every class or classloader for every redeployment. So it doesn't matter what classloader the service is bound from, though it can exacerbate the problem. If I ever want to associate some data with, say, a class from the system classloader - *even if I make that data be a type from the system classloader* - that data is now permanent, even when I don't need it anymore. So if I cause a deployment to happen again, which re-executes the association, the old data is now leaked.

Your solution puts permanent, uncollectible data on classloaders, no matter how you slice it. There *has* to be a way to clean it up.

- DML

Reply via email to