How to clean threadlocals

Does anyone have an example on how to do this? or are they handled by the garbage collector? im using tomcat6

+43
java tomcat thread-local
Oct 06 '10 at 1:57
source share
6 answers

Javadoc says the following:

"Each thread contains an implicit reference to its copy of the local local variable, if the thread is alive and the ThreadLocal instance is available, after the thread disappears, all its instances of local-local instances are prone to garbage collection (unless other references to these copies exist )

If your application or (if you are talking about request streams), the container uses the thread pool, which means that the threads do not die. If necessary, you will need to independently solve problems with local residents. The only clean way to do this is to call the ThreadLocal.remove() method.

There are two reasons why you can clear thread locators for threads in a thread pool:

  • to prevent memory leak (or hypothetical resource) or
  • to prevent accidental leakage of information from one request to another through flow locators.

Problems with local local memory should usually not be a serious problem with limited thread pools, since stream locators can be overwritten anyway; those. when the stream is reused. However, if you make a mistake when creating new ThreadLocal instances over and over (instead of using the static variable to store a singleton instance), the local thread values ​​will not be overwritten and will accumulate in each threadlocals thread. This could cause a serious leak.




Assuming you're talking about stream locales that are created / used during the processing of a web request HTTP request, then one way to avoid local stream leaks is to register a ServletRequestListener with your webapp ServletContext and implement listener requestDestroyed to clear the stream locators for the current flow.

Note that in this context, you also need to consider the possibility of information leakage from one request to another.

+49
06 Oct 2018-10-10T00:
source share

Here is some code to clear all local stream variables from the current stream when you have no reference to the actual local stream variable. You can also generalize it to clear local thread variables for other threads:

  private void cleanThreadLocals() { try { // Get a reference to the thread locals table of the current thread Thread thread = Thread.currentThread(); Field threadLocalsField = Thread.class.getDeclaredField("threadLocals"); threadLocalsField.setAccessible(true); Object threadLocalTable = threadLocalsField.get(thread); // Get a reference to the array holding the thread local variables inside the // ThreadLocalMap of the current thread Class threadLocalMapClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap"); Field tableField = threadLocalMapClass.getDeclaredField("table"); tableField.setAccessible(true); Object table = tableField.get(threadLocalTable); // The key to the ThreadLocalMap is a WeakReference object. The referent field of this object // is a reference to the actual ThreadLocal variable Field referentField = Reference.class.getDeclaredField("referent"); referentField.setAccessible(true); for (int i=0; i < Array.getLength(table); i++) { // Each entry in the table array of ThreadLocalMap is an Entry object // representing the thread local reference and its value Object entry = Array.get(table, i); if (entry != null) { // Get a reference to the thread local object and remove it from the table ThreadLocal threadLocal = (ThreadLocal)referentField.get(entry); threadLocal.remove(); } } } catch(Exception e) { // We will tolerate an exception here and just log it throw new IllegalStateException(e); } } 
+29
May 20 '13 at 7:17
source share

It is impossible to clear ThreadLocal values, except from the thread that places them there first (or when the thread collects garbage - not in the case of workflows). This means that you should take care to clear ThreadLocal when the servlet request is complete (or before transferring the AsyncContext to another thread in Servlet 3), because after that moment you will never be able to get this particular worker thread and therefore will memory leak in situations where your web application will not be deployed until the server is restarted.

A good place to do this is ServletRequestListener.requestDestroyed () .

If you use Spring, all the necessary postings are already installed, you can just put things in the request area without worrying about cleaning them up (which happens automatically):

 RequestContextHolder.getRequestAttributes().setAttribute("myAttr", myAttr, RequestAttributes.SCOPE_REQUEST); . . . RequestContextHolder.getRequestAttributes().getAttribute("myAttr", RequestAttributes.SCOPE_REQUEST); 
+11
Jan 25 2018-12-15T00:
source share

I would like to add my answer to this question, even if it is old. I ran into the same problem (gson threadlocal was not removed from the request stream), and even got a convenient server reboot at any time when it ran out of memory (which takes a long time!).

In the context of a java web application installed in dev mode (the server is set up to fail every time it perceives a code change and, possibly, also works in debug mode), I quickly found out that threadlocals might be awesome someday to be a pain. I used threadlocal Invocation for each request. Inside Invocation. Sometimes I also used gson to generate my answer. I would wrap Invocation inside a try block in a filter and destroy it inside a finally block.

What I observed (at the moment I have no indicators for backup), I added that if I made changes to several files and the server constantly bounced between my changes, I would become impatient and restart the server (tomcat to be exact ) from the IDE. Most likely, I would end the "Out of memory" exception.

As I got around this, I need to include the ServletRequestListener application in the application, and my problem disappeared. I think what happens is that in the middle of the request, if the server fails several times, my threadlocals are not cleared (including gson), so I get this warning about threadlocals and two or three warnings later, the server crashes. When the ServletResponseListener explicitly closes my threadlocals, the gson problem disappeared.

Hope this makes sense and gives you an idea of ​​how to overcome threadlocal related issues. Always cover them around your point of use. In the ServletRequestListener, check each threadlocal wrapper and, if it still has a valid reference to some object, destroy it at that point.

I should also indicate what makes it a habit to wrap threadlocal as a static variable inside the class. This way you can be sure that by destroying it in the ServeltRequestListener, you do not have to worry about other instances of the same class hanging around.

0
Jun 05 '13 at 6:45
source share

The JVM will automatically clear all non-referenced objects that are in the ThreadLocal object.

Another way to clean these objects (say, for example, these objects may be all unsafe stream objects that exist around) is to put them inside some Object Holder class that basically holds it, and you can override the finalize method to clear the object that is inside of it. Again, this depends on the garbage collector and its policies when it will reference the finalize method.

Here is a sample code:

 public class MyObjectHolder { private MyObject myObject; public MyObjectHolder(MyObject myObj) { myObject = myObj; } public MyObject getMyObject() { return myObject; } protected void finalize() throws Throwable { myObject.cleanItUp(); } } public class SomeOtherClass { static ThreadLocal<MyObjectHolder> threadLocal = new ThreadLocal<MyObjectHolder>(); . . . } 
0
Apr 10 '14 at 3:51
source share

Read the Javadoc documentation carefully:

'Each thread contains an implicit reference to its copy of a local local variable, if the thread is alive and an instance of ThreadLocal is available; after the stream disappears, all its copies of locally-streaming instances are subject to garbage collection (if there are no other references to these copies).

There is no need to clean anything, there is an AND condition for leaks to survive. Thus, even in the web container where the stream is stored in the application, until the webapp class is unloaded (only a link in a static class loaded in the parent class loader will prevent this, and this has nothing to do with ThreadLocal, but common problems with common jars with static data), then the second stage AND condition is no longer fulfilled, so the local copy of the stream has the right to garbage collection.

A local thread cannot cause a memory leak, because the implementation is consistent with the documentation.

0
Jan 01 '16 at 13:38 on
source share



All Articles