2017-12-20 5 views
0

TomcatのThreadLocalリークでこのarticleを読んでいます。最初の例には次のコードが含まれています:カスタムThreadLocalクラスのThreadLocalリークの説明

public class MyCounter { 
     private int count = 0; 

     public void increment() { 
       count++; 
     } 

     public int getCount() { 
       return count; 
     } 
} 

public class MyThreadLocal extends ThreadLocal<MyCounter> { 
} 

public class LeakingServlet extends HttpServlet { 
     private static MyThreadLocal myThreadLocal = new MyThreadLocal(); 

     protected void doGet(HttpServletRequest request, 
         HttpServletResponse response) throws ServletException, IOException { 

       MyCounter counter = myThreadLocal.get(); 
       if (counter == null) { 
         counter = new MyCounter(); 
         myThreadLocal.set(counter); 
       } 

       response.getWriter().println(
           "The current thread served this servlet " + counter.getCount() 
               + " times"); 
       counter.increment(); 
     } 
} 

すべてのクラスはwebapp内にあります。それは、私は理解していないクラスローダ(ThreadLocalのない)漏れ、のための以下の説明概説:

をLeakingServletが少なくとも一度呼び出され、 がそれを務め、そのスレッドが停止されていない場合は、我々が作成しましたクラスローダーのリーク!

リークは、ThreadLocal インスタンスのカスタムクラスと、スレッドにバインドされた値のカスタムクラスがあるために発生します。 実際に重要なことは、両方のクラスが webappクラスローダーによって読み込まれていることです。

ThreadLocalリークの説明はひどいです。要求を処理したスレッドが停止していない場合、ThreadLocalのリークはどのようにして得られますか(実際には記事にclassloaderが漏れています)これは、スレッドがTomcatスレッドプールの一部であり、MyThreadLocal.remove()が閉じられていないため、スレッドがプールに戻されてからMyCounter/MyThreadLocalのWebアプリケーションクラスローダーをガベージコレクトできないことを意味しますか?これはMyThreadLocal.remove()と呼ばれるでしょうか?わかりません。

答えて

1

説明が正しくありません:

我々は一部が間違っていること

ThreadLocalのインスタンスのカスタムクラスを持っているので、漏れが発生しています。スレッドクラスのThreadLocalMapはキーのためにweakReferencesを使用しているため、threadLocalインスタンスがカスタムクラスであるかどうかは関係ありません。私は自分のカスタムThreadLocalクラスでテストしたところ、メモリリークはありませんでした。

また、スレッドにバインドされた値のカスタムクラスです。

これは正しいです。値の場合、スレッドは弱参照を使用しないので、クラスローダーがガベージコレクションされないようにするカスタムクラスの場合、そのクラスローダーによってロードされたすべてのクラスはスレッドプールからスレッドが削除されるまでメモリ内に留まります。

+0

"MyThreadLocal.remove()を呼び出すとこれが解決されますか?" – erickson

+0

それはいつ呼びますか?現在のスレッドからThreadLocalを消去するだけです。 AtomicLongはカスタムクラスの代わりにAtomicLongを使用する方が良いですし、AtomicLongはあなたのアプリケーションをロードしたのと同じクラスローダではなく、ブートストラップクラスローダによってロードされるので、クラスローダのリークはありません。 – CodesInTheDark

+0

別の解決方法は、作成したImprovedThreadLocalを使用することです。 githubで見つけてください。 – CodesInTheDark

関連する問題