GeeCON Prague 2014*
The moose likes Java in General and the fly likes ThreadLocal and GC Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Java » Java in General
Bookmark "ThreadLocal and GC" Watch "ThreadLocal and GC" New topic
Author

ThreadLocal and GC

Sergey Alaev
Greenhorn

Joined: Dec 30, 2009
Posts: 7


Any ideas/comments?
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

An idea: TellTheDetails.
Sergey Alaev
Greenhorn

Joined: Dec 30, 2009
Posts: 7
Details are simple: as above test shows, ThreadLocal values are NOT garbage collected if not removed manually from ThreadLocal instance, even if we have no strong references to our ThreadLocal instance.
This seems illogical to me....
Mohamed Sanaulla
Saloon Keeper

Joined: Sep 08, 2007
Posts: 3071
    
  33

From the Documentation for the ThreadLocal

Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).


And you really cannot force the Garbage collection by using System.GC().


Mohamed Sanaulla | My Blog
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Are you sure that the thread that executed before() has terminated (and was eligible to be garbage collected, so the JUnit framework didn't keep any reference to it) sooner than the test() and test2() were called? I don't know the JUnit internal mechanisms well enough to tell.

Besides, I'd say that PhanthomReference and reference queues are more robust mechanism for determining when an object was garbage collected. Then you could monitor collection of the owning thread too, or better write the test outside any framework, so that you have full control over references to threads that were used.

What Mohamed said should also be considered.

Edit: thread locals should really get cleared when the thread terminates, not when it is garbage collected. I had thought otherwise.
Sergey Alaev
Greenhorn

Joined: Dec 30, 2009
Posts: 7
Mohamed Sanaulla wrote:From the Documentation for the ThreadLocal

and the ThreadLocal instance is accessible;



This is not the case - i've deleted reference to ThreadLocal instance as you can see.
About System.gc() - you are right, but usually(and in this case) it works as intended. You can use any good profiler to see that GarbageObject will not be garbage-collected anyway.


Sergey Alaev
Greenhorn

Joined: Dec 30, 2009
Posts: 7
2Martin Vajsar

Both tests are running in the same thread, but that is not the case.
Problem is that any value hold in ThreadLocal instance is indirectly referenced by Thread instance - i.e. in my case GarbageObject will NOT be collected before current thread finishes.

Actually, i hoped that GarbageObject will be collected after i destroyed reference to ThreadLocal instance - why not?
Sergey Alaev
Greenhorn

Joined: Dec 30, 2009
Posts: 7
Martin Vajsar wrote:
Edit: thread locals should really get cleared when the thread terminates, not when it is garbage collected. I had thought otherwise.


Thus, the question is why it has been designed this way?
thead locals are inaccessible anyway without appropriate instance of ThreadLocal
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18874
    
  40

Sergey Alaev wrote:
This is not the case - i've deleted reference to ThreadLocal instance as you can see.


The Threadlocal class actually stores the values in the Thread object itself -- so interestingly, you actually don't need to make the ThreadLocal instance unreachable. It is perfectly fine to keep the references to it.

On the other hand, the Thread object needs to be unreachable -- meaning the thread that set the thread local value needs to terminate, and no other thread is holding a reference to that thread's Thread object.


[EDIT: A bit more detail. On the third hand, I was also under the impression that the value is stored in a weak map, that is keyed on the thread local. This would imply that if the thread local goes, then the running thread loses it too.... meaning the value is eligible for GC if either the Thread object or ThreadLocal object becomes unreachable.]

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Henry Wong wrote:
On the other hand, the Thread object needs to be unreachable

It should not be so. Firstly, the documentation states that values are kept while the thread is alive, not while it is referenced, and secondly, the exit() method in Thread that is called by the JVM when thread terminates clears the local values of the thread, as can be seen in the JDK source.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  16

I may be wrong, but isn't a thread always reachable as long as it's alive?
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Stephan van Hulst wrote:I may be wrong, but isn't a thread always reachable as long as it's alive?

It certainly is, but on the other hand, it may be reachable long after it had terminated. The thread locals are cleared when it terminates, not when it becomes unreachable.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18874
    
  40

Martin Vajsar wrote:
Stephan van Hulst wrote:I may be wrong, but isn't a thread always reachable as long as it's alive?

It certainly is, but on the other hand, it may be reachable long after it had terminated. The thread locals are cleared when it terminates, not when it becomes unreachable.


Wow, this is a fast moving topic. I just changed my last post -- only to find out that it is three posts behind, and my last edit may never be read.

I now think that the value should become unreachable, when the thread local becomes unreachable too -- maybe it would be a good idea to modify the test harness to call system.gc() a few times (or in a loop). And see if it eventually disappears.

Henry
Sergey Alaev
Greenhorn

Joined: Dec 30, 2009
Posts: 7
Henry Wong wrote:
I now think that the value should become unreachable, when the thread local becomes unreachable too -- maybe it would be a good idea to modify the test harness to call system.gc() a few times (or in a loop). And see if it eventually disappears.

Henry


It will not disappear because as i've written above it is hard-referenced to current Thread instance.
Question now is WHY it is hard-referenced
Because i cant believe it is a bug.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18874
    
  40

Duh... I forget that weak hash maps needs to be used in order to clear entries. Only the key is weak. And there isn't a thread that will clear them periodically. After the GC, try changing your test to create another thread local object, and using it; maybe that will trigger the Thread's weak hashmap to clear it's entries. And of course, GC again.

Henry
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18874
    
  40

Martin Vajsar wrote:
It should not be so. Firstly, the documentation states that values are kept while the thread is alive, not while it is referenced, and secondly, the exit() method in Thread that is called by the JVM when thread terminates clears the local values of the thread, as can be seen in the JDK source.


Yup. I stand corrected.

I just confirmed that the data is deleted upon thread termination -- it doesn't require the unreachability of the Thread instance.

Henry
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18874
    
  40

Sergey Alaev wrote:
It will not disappear because as i've written above it is hard-referenced to current Thread instance.
Question now is WHY it is hard-referenced
Because i cant believe it is a bug.


Henry Wong wrote:I forget that weak hash maps needs to be used in order to clear entries. Only the key is weak. And there isn't a thread that will clear them periodically. After the GC, try changing your test to create another thread local object, and using it; maybe that will trigger the Thread's weak hashmap to clear it's entries. And of course, GC again.


This one is also confirmed, but it is a bit more complex. The trigger that will delete entries (if the thread is still alive but the thread local becomes unreachable), is a rehash of the weak map internal to the thread object. This requires creating a few thread local objects until the rehash occurs.

Henry
 
GeeCON Prague 2014
 
subject: ThreadLocal and GC