Well, possibly I'm mistaken, but it seems that this affects non-static fields
too. Please see
http://www.nabble.com/ThreadLocal-in-SegmentReader-to18306230.html where the
use case is described in the details.
In short: it seems that the scope of ThreadLocals does not matter. What
really matters is that they are referenced by ThreadLocals map in the thread
which is still alive.


Robert Engels wrote:
> 
> This is only an issue for static ThreadLocals ...
> 
> On Jul 11, 2008, at 11:32 PM, Roman Puchkovskiy wrote:
> 
>>
>> The problem here is not because ThreadLocal instances are not GC'd  
>> (they are
>> GC'd, and your test shows this clearly).
>> But even one instance which is not removed from its Thread is  
>> enough to
>> prevent the classloader from being unloaded, and that's the problem.
>>
>>
>> Michael McCandless-2 wrote:
>>>
>>> OK, I created a simple test to test this (attached).  The test just
>>> runs 10 threads, each one creating a 100 KB byte array which is  
>>> stored
>>> into a ThreadLocal, and then periodically the ThreadLocal is replaced
>>> with a new one.  This is to test whether GC of a ThreadLocal, even
>>> though the thread is still alive, in fact leads to GC of the objects
>>> held in the ThreadLocal.
>>>
>>> Indeed on Sun JRE 1.4, 1.5 and 1.6 it appears that the objects are in
>>> fact properly collected.
>>>
>>> So this is not a leak but rather a "delayed collection" issue.   
>>> Java's
>>> GC is never guaranteed to be immediate, and apparently when using
>>> ThreadLocals it's even less immediate than "normal".  In the original
>>> issue, if other things create ThreadLocals, then eventually Lucene's
>>> unreferenced ThreadLocals would be properly collected.
>>>
>>> So I think we continue to use non-static ThreadLocals in Lucene...
>>>
>>> Mike
>>>
>>>
>>>
>>>
>>>
>>>
>>> robert engels wrote:
>>>
>>>> Once again, these are "static" thread locals. A completely different
>>>> issue. Since the object is available statically, the weak reference
>>>> cannot be cleared so stale entries will never be cleared as long as
>>>> the thread is alive.
>>>>
>>>> On Jul 9, 2008, at 4:46 PM, Adrian Tarau wrote:
>>>>
>>>>> Just a few examples of "problems" using ThreadLocals.
>>>>>
>>>>> http://opensource.atlassian.com/projects/hibernate/browse/HHH-2481
>>>>> http://www.theserverside.com/news/thread.tss?thread_id=41473
>>>>>
>>>>> Once again, I'm not pointing to Lucene SegmentReader as a "bad"
>>>>> implementation, and maybe the current "problems" of ThreadLocals
>>>>> are not a problem for SegmentReader but it seems safer to use
>>>>> ThreadLocals to pass context information which is cleared when the
>>>>> call exits instead of storing long-lived objects.
>>>>>
>>>>>
>>>>> robert engels wrote:
>>>>>>
>>>>>> Aside from the pre-1.5 thread local "perceived leak", there are no
>>>>>> issues with ThreadLocals if used properly.
>>>>>>
>>>>>> There is no need for try/finally blocks, unless you MUST release
>>>>>> resources immediately, usually this is not the case, which is why
>>>>>> a ThreadLocal is used in the first place.
>>>>>>
>>>>>> From the ThreadLocalMap javadoc...
>>>>>>
>>>>>>  /**
>>>>>>      * ThreadLocalMap is a customized hash map suitable only for
>>>>>>      * maintaining thread local values. No operations are exported
>>>>>>      * outside of the ThreadLocal class. The class is package
>>>>>> private to
>>>>>>      * allow declaration of fields in class Thread.  To help deal
>>>>>> with
>>>>>>      * very large and long-lived usages, the hash table entries  
>>>>>> use
>>>>>>      * WeakReferences for keys. However, since reference queues
>>>>>> are not
>>>>>>      * used, stale entries are guaranteed to be removed only when
>>>>>>      * the table starts running out of space.
>>>>>>      */
>>>>>>
>>>>>> /**
>>>>>>          * Heuristically scan some cells looking for stale  
>>>>>> entries.
>>>>>>          * This is invoked when either a new element is added, or
>>>>>>          * another stale one has been expunged. It performs a
>>>>>>          * logarithmic number of scans, as a balance between no
>>>>>>          * scanning (fast but retains garbage) and a number of  
>>>>>> scans
>>>>>>          * proportional to number of elements, that would find all
>>>>>>          * garbage but would cause some insertions to take O(n)
>>>>>> time.
>>>>>>          *
>>>>>>          * @param i a position known NOT to hold a stale entry.  
>>>>>> The
>>>>>>          * scan starts at the element after i.
>>>>>>          *
>>>>>>          * @param n scan control: <tt>log2(n)</tt> cells are
>>>>>> scanned,
>>>>>>          * unless a stale entry one is found, in which case
>>>>>>          * <tt>log2(table.length)-1</tt> additional cells are
>>>>>> scanned.
>>>>>>          * When called from insertions, this parameter is the  
>>>>>> number
>>>>>>          * of elements, but when from replaceStaleEntry, it is the
>>>>>>          * table length. (Note: all this could be changed to be
>>>>>> either
>>>>>>          * more or less aggressive by weighting n instead of just
>>>>>>          * using straight log n. But this version is simple, fast,
>>>>>> and
>>>>>>          * seems to work well.)
>>>>>>          *
>>>>>>          * @return true if any stale entries have been removed.
>>>>>>          */
>>>>>>
>>>>>>
>>>>>> The instance ThreadLocals (and what the refer to) will be GC'd
>>>>>> when the containing Object is GC'd.
>>>>>>
>>>>>> There IS NO MEMORY LEAK in ThreadLocal. If the ThreadLocal refers
>>>>>> to an object that has native resources (e.g. file handles), it may
>>>>>> not be released until other thread locals are created by the
>>>>>> thread (or the thread terminates).
>>>>>>
>>>>>> You can avoid this "delay" by calling remove(), but in most
>>>>>> applications it should never be necessary - unless a very strange
>>>>>> usage...
>>>>>>
>>>>>> On Jul 9, 2008, at 2:37 PM, Adrian Tarau wrote:
>>>>>>
>>>>>>> From what I know, storing objects in ThreadLocal is safe as long
>>>>>>> as you release the object within a try {} finall {} block or
>>>>>>> store objects which are independent of the rest of the code(no
>>>>>>> dependencies).Otherwise it can get pretty tricky(memory leaks,
>>>>>>> classloader problems) after awhile.
>>>>>>>
>>>>>>> It is pretty convenient to pass HTTP request information with a
>>>>>>> ThreadLocal in a servlet(but you should cleanup the variable
>>>>>>> before leaving the servlet) but I'm not sure how safe it is in
>>>>>>> this case.
>>>>>>>
>>>>>>> robert engels wrote:
>>>>>>>> Using synchronization is a poor/invalid substitute for thread
>>>>>>>> locals in many cases.
>>>>>>>>
>>>>>>>> The point of the thread local in these referenced cases is too
>>>>>>>> allow streaming reads on a file descriptor. if you use a shared
>>>>>>>> file descriptor/buffer you are going to continually invalidate
>>>>>>>> the buffer.
>>>>>>>>
>>>>>>>> On Jul 8, 2008, at 5:12 AM, Michael McCandless wrote:
>>>>>>>>
>>>>>>>>>
>>>>>>>>> Well ... SegmentReader uses ThreadLocal to hold a thread-
>>>>>>>>> private instance of TermVectorsReader, to avoid synchronizing
>>>>>>>>> per-document when loading term vectors.
>>>>>>>>>
>>>>>>>>> Clearing this ThreadLocal value per call to SegmentReader's
>>>>>>>>> methods that load term vectors would defeat its purpose.
>>>>>>>>>
>>>>>>>>> Though, of course, we then synchronize on the underlying file
>>>>>>>>> (when using FSDirectory), so perhaps we are really not saving
>>>>>>>>> much by using ThreadLocal here.  But we are looking to relax
>>>>>>>>> that low level synchronization with LUCENE-753.
>>>>>>>>>
>>>>>>>>> Maybe we could make our own ThreadLocal that just uses a
>>>>>>>>> HashMap, which we'd have to synchronize on when getting the  
>>>>>>>>> per-
>>>>>>>>> thread instances.  Or, go back to sharing a single
>>>>>>>>> TermVectorsReader and synchronize per-document.
>>>>>>>>>
>>>>>>>>> Jason has suggested moving to a model where you ask the
>>>>>>>>> IndexReader for an object that can return term vectors / stored
>>>>>>>>> fields / etc, and then you interact with that many times to
>>>>>>>>> retrieve each doc.  We could then synchronize only on
>>>>>>>>> retrieving that object, and provide a thread-private instance.
>>>>>>>>>
>>>>>>>>> It seems like we should move away from using ThreadLocal in
>>>>>>>>> Lucene and do "normal" synchronization instead.
>>>>>>>>>
>>>>>>>>> Mike
>>>>>>>>>
>>>>>>>>> Adrian Tarau wrote:
>>>>>>>>>
>>>>>>>>>> Usually ThreadLocal.remove() should be called at the end(in a
>>>>>>>>>> finally block), before the current call leaves your code.
>>>>>>>>>>
>>>>>>>>>> Ex : if during searching ThreadLocal is used, every search(..)
>>>>>>>>>> method should cleanup any ThreadLocal variables, or even
>>>>>>>>>> deeper in the implementation. When the call leaves Lucene any
>>>>>>>>>> used ThreadLocal should be cleaned up.
>>>>>>>>>>
>>>>>>>>>> Michael McCandless wrote:
>>>>>>>>>>>
>>>>>>>>>>> ThreadLocal, which we use in several places in Lucene, causes
>>>>>>>>>>> a leak in app servers because the classloader never fully
>>>>>>>>>>> deallocates Lucene's classes because the ThreadLocal is
>>>>>>>>>>> holding strong references.
>>>>>>>>>>>
>>>>>>>>>>> Yet, ThreadLocal is very convenient for avoiding
>>>>>>>>>>> synchronization.
>>>>>>>>>>>
>>>>>>>>>>> Does anyone have any ideas on how to solve this w/o falling
>>>>>>>>>>> back to "normal" synchronization?
>>>>>>>>>>>
>>>>>>>>>>> Mike
>>>>>>>>>>>
>>>>>>>>>>> Begin forwarded message:
>>>>>>>>>>>
>>>>>>>>>>>> From: "Yonik Seeley" <[EMAIL PROTECTED]>
>>>>>>>>>>>> Date: July 7, 2008 3:30:28 PM EDT
>>>>>>>>>>>> To: [EMAIL PROTECTED]
>>>>>>>>>>>> Subject: Re: ThreadLocal in SegmentReader
>>>>>>>>>>>> Reply-To: [EMAIL PROTECTED]
>>>>>>>>>>>>
>>>>>>>>>>>> On Mon, Jul 7, 2008 at 2:43 PM, Michael McCandless
>>>>>>>>>>>> <[EMAIL PROTECTED]> wrote:
>>>>>>>>>>>>> So now I'm confused: the SegmentReader itself should no
>>>>>>>>>>>>> longer be reachable,
>>>>>>>>>>>>> assuming you are not holding any references to your
>>>>>>>>>>>>> IndexReader.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Which means the ThreadLocal instance should no longer be
>>>>>>>>>>>>> reachable.
>>>>>>>>>>>>
>>>>>>>>>>>> It will still be referenced from the Thread(s)  
>>>>>>>>>>>> ThreadLocalMap
>>>>>>>>>>>> The key (the ThreadLocal) will be weakly referenced, but the
>>>>>>>>>>>> values
>>>>>>>>>>>> (now stale) are strongly referenced and won't be actually
>>>>>>>>>>>> removed
>>>>>>>>>>>> until the table is resized (under the Java6 impl at least).
>>>>>>>>>>>> Nice huh?
>>>>>>>>>>>>
>>>>>>>>>>>> -Yonik
>>>>>>>>>>>>
>>>>>>>>>>>> ------------------------------------------------------------ 
>>>>>>>>>>>> ---------
>>>>>>>>>>>> To unsubscribe, e-mail: java-user-
>>>>>>>>>>>> [EMAIL PROTECTED]
>>>>>>>>>>>> For additional commands, e-mail: java-user- 
>>>>>>>>>>>> [EMAIL PROTECTED]
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> ------------------------------------------------------------- 
>>>>>>>>>>> --------
>>>>>>>>>>> To unsubscribe, e-mail: java-dev- 
>>>>>>>>>>> [EMAIL PROTECTED]
>>>>>>>>>>> For additional commands, e-mail: java-dev-
>>>>>>>>>>> [EMAIL PROTECTED]
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -------------------------------------------------------------- 
>>>>>>>>>> -------
>>>>>>>>>> To unsubscribe, e-mail: [EMAIL PROTECTED]
>>>>>>>>>> For additional commands, e-mail: java-dev- 
>>>>>>>>>> [EMAIL PROTECTED]
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --------------------------------------------------------------- 
>>>>>>>>> ------
>>>>>>>>> To unsubscribe, e-mail: [EMAIL PROTECTED]
>>>>>>>>> For additional commands, e-mail: java-dev- 
>>>>>>>>> [EMAIL PROTECTED]
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ---------------------------------------------------------------- 
>>>>>>>> -----
>>>>>>>> To unsubscribe, e-mail: [EMAIL PROTECTED]
>>>>>>>> For additional commands, e-mail: [EMAIL PROTECTED]
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> ----------------------------------------------------------------- 
>>>>>>> ----
>>>>>>> To unsubscribe, e-mail: [EMAIL PROTECTED]
>>>>>>> For additional commands, e-mail: [EMAIL PROTECTED]
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [EMAIL PROTECTED]
>>> For additional commands, e-mail: [EMAIL PROTECTED]
>>>
>>
>> -- 
>> View this message in context: http://www.nabble.com/Fwd%3A- 
>> ThreadLocal-in-SegmentReader-tp18326720p18416022.html
>> Sent from the Lucene - Java Developer mailing list archive at  
>> Nabble.com.
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [EMAIL PROTECTED]
>> For additional commands, e-mail: [EMAIL PROTECTED]
>>
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 
> 
> 

-- 
View this message in context: 
http://www.nabble.com/Fwd%3A-ThreadLocal-in-SegmentReader-tp18326720p18416841.html
Sent from the Lucene - Java Developer mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to