[PATCH 0/2] Class- and class loader-local storage (Bug ID #6493635)

David M. Lloyd david.lloyd at redhat.com
Fri Feb 27 19:44:18 UTC 2009

On 02/27/2009 01:15 PM, Bob Lee wrote:
> On Fri, Feb 27, 2009 at 11:04 AM, David M. Lloyd <david.lloyd at 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.


More information about the core-libs-dev mailing list