WAR == single classloader was: Benefits of activeReferenceQueue

David Holmes david.holmes at oracle.com
Tue Jul 29 08:09:56 UTC 2014


Hi Jaroslav,

Please don't keep creating new email threads as yu are making it very 
hard to track the discussion.

On 29/07/2014 6:05 PM, Jaroslav Tulach wrote:
> Hello David.
>
> Dne Út 29. července 2014 12:16:33, David Holmes napsal(a):
>> So ... activeReferenceQueue is a reference queue that embodies a thread
>> that does the polling and implements a psuedo-finalization mechanism.
>> This works fine in the normal case where the lifetime of the queue is
>> the lifetime of the "application". In the WAR case (and I don't know the
>> details of WAR deployment) each time it is deployed in the same VM we
>> get a new activeReferenceQueue and a new thread.
>
> WAR contains a set of JARs that form a "classpath". Each time WAR is re-
> deployed, a new classloader with a new "classpath" is created. I don't know
> anything certain about WARs either, but this is my naive vision of what
> happens.
>
>> The basic issue is that the thread has a strong reference to the queue
>> and has no idea when it should exit and so the thread and queue remain
>> forever even if there is no user code with a reference to the queue -
>> does that sum it up?
>
> Plus, because there is a single classloader which loads all the classes from a
> WAR, by keeping the activerReferenceQueue thread alive and holding reference
> to the queue, we hold reference to its class and the classloader and thus all
> classes referenced by it.
>
> And this memory leak accumulates with every re-deploy.

I see.

>> Can the thread not hold a weakreference to the queue and poll using
>> remove(timeout) and then terminate when the queue reference is gone?
>
> The NetBeans team does not consider active polling good practice. But of
> course, you are right. Such solution has been analyzed in earlier. See below.

I'll follow this up in the other thread where Peter Levart responded.

Thanks,
David

> -jt
>
>>> Those problems could be fixed by using active polling as I wrote in
>>> today's morning email:
>>>   > class Impl extends ReferenceQueue {}
>>>   >
>>>   > Reference<Impl> ref = new WeakReference<Impl>(new Impl());
>>>   >
>>>   >
>>>   >
>>>   > while (true) {
>>>   >
>>>   >
>>>   >
>>>   > Impl impl = ref.get();
>>>   >
>>>   > if (impl == null) {
>>>   >
>>>   >
>>>   >
>>>   > // no other Reference objects using the Impl queue.
>>>   >
>>>   > // exit this cleaner thread
>>>   >
>>>   > return;
>>>   >
>>>   >
>>>   >
>>>   > }
>>>   >
>>>   > Reference<?> ref = impl.remove(15000);
>>>   >
>>>   > if (ref == null) {
>>>   >
>>>   >
>>>   >
>>>   > impl = null; // don't hold strong ref to Impl queue
>>>   >
>>>   > System.gc(); // XXX: is anyone else holding reference to Impl queue?
>>>   >
>>>   > continue;
>>>   >
>>>   >
>>>   >
>>>   > }
>>>   >
>>>   > // do something with ref
>>>   >
>>>   >
>>>   >
>>>   > }
>>>   >
>>>   >
>>>   >
>>>   > this could work, althrough the problem is the XXX part.
>>>   >
>>>   >
>>>   >
>>>   > I need to release my own pointer to the Impl queue, tell the system
>>>
>>> to try
>>>
>>>   > to garbage collect it. If it has not been removed, grap new strong
>>>
>>> pointer
>>>
>>>   > to the Impl queue and wait again. I am not aware of any other way to
>>>   > ask
>>>   >
>>>   > for GC than System.gc, and having System.gc being called every 15s will
>>>   >
>>>   > likely decrease VM performance a bit.
>>>   >
>>>   >
>>>   >
>>>   > The proper solution (no reflection, no repeated polling) would in fact
>>>   > be
>>>   >
>>>   > simple: Being able to call:
>>>   >
>>>   >
>>>   >
>>>   > impl.remove();
>>>   >
>>>   >
>>>   >
>>>   > without anyone having strong reference to impl - e.g. without impl
>>>
>>> being on
>>>
>>>   > stack during the remove call.
>>>
>>> I don't know what else to add. So I wait for further question.
>>>
>>> -jt
>>>
>>> [1]
>>> http://bits.netbeans.org/dev/javadoc/org-openide-util/org/openide/util/Uti
>>> lities.html#activeReferenceQueue()
>>>
>>> [2] https://netbeans.org/bugzilla/show_bug.cgi?id=206621
>



More information about the core-libs-dev mailing list