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