Win a copy of Programmer's Guide to Java SE 8 Oracle Certified Associate (OCA) this week in the OCAJP forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

ThreadLocal and GC

 
Sergey Alaev
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


Any ideas/comments?
 
Martin Vajsar
Sheriff
Posts: 3752
62
Chrome Netbeans IDE Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
An idea: TellTheDetails.
 
Sergey Alaev
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 3159
33
Google App Engine Java Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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().
 
Martin Vajsar
Sheriff
Posts: 3752
62
Chrome Netbeans IDE Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Marshal
Pie
Posts: 21362
84
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
Martin Vajsar
Sheriff
Posts: 3752
62
Chrome Netbeans IDE Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Pie
Posts: 6081
71
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I may be wrong, but isn't a thread always reachable as long as it's alive?
 
Martin Vajsar
Sheriff
Posts: 3752
62
Chrome Netbeans IDE Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Marshal
Pie
Posts: 21362
84
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Marshal
Pie
Posts: 21362
84
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Marshal
Pie
Posts: 21362
84
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Marshal
Pie
Posts: 21362
84
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic