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()
と呼ばれるでしょうか?わかりません。
"MyThreadLocal.remove()を呼び出すとこれが解決されますか?" – erickson
それはいつ呼びますか?現在のスレッドからThreadLocalを消去するだけです。 AtomicLongはカスタムクラスの代わりにAtomicLongを使用する方が良いですし、AtomicLongはあなたのアプリケーションをロードしたのと同じクラスローダではなく、ブートストラップクラスローダによってロードされるので、クラスローダのリークはありません。 – CodesInTheDark
別の解決方法は、作成したImprovedThreadLocalを使用することです。 githubで見つけてください。 – CodesInTheDark