tomcatメモリ漏れ問題が解決されました.スレッドプールが閉じられません.


org.apache.cantalina.loader.WebappClass Loader Base.clearreferences Threads The web appication
but ハイ failed ト stop it. This is very likely ト create a. memory leak. Stock トレイ 保存先  thread:
SEVRE:The web appration[xxxxx]appars to have started a thread named[pool-4-thread-x]but has failed to stop it.This is very to create a memory leak.Feb 28,2015 9:04 oramg.apperalalalallass.
いいえ、まだいくつかのThreadLocalが解放されませんでした.そして、Threadのリリースできない警告が残りました.
資料を調べる
http://stackoverflow.com/questions/5292349/is-this-very-likely-to-create-a-memory-leak-in-tomcat
回答にはThreadLocalの解決策があります.以下の方法で解決すればいいです.
public Integer immolate() {
    int count = 0;
    try {
        final Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
        threadLocalsField.setAccessible(true);
        final Field inheritableThreadLocalsField = Thread.class.getDeclaredField("inheritableThreadLocals");
        inheritableThreadLocalsField.setAccessible(true);
//つまりtomcat容器では、スレッドごとのクラスリーダーは、結局はデフォルトでwebapp Class Loaderとして設定されています.いくつかのスレッドが即時に閉じられない時、webapp classiloaderはこれらのスレッドが持つ強い引用のため、正常なgcができなくなります.
これを理解すれば、方法があります.
        for (final Thread thread : Thread.getAllStackTraces().keySet()) {
            count += clear(threadLocalsField.get(thread));
            count += clear(inheritableThreadLocalsField.get(thread));

            if (thread != null) {
                thread.setContextClassLoader(null);
            }
        }

        log.info("immolated " + count + " values in ThreadLocals");
    } catch (Exception e) {
        throw new Error("ThreadLocalImmolater.immolate()", e);
    }
    return count;
}

private int clear(final Object threadLocalMap) throws Exception {
    if (threadLocalMap == null)
        return 0;
    int count = 0;
    final Field tableField = threadLocalMap.getClass().getDeclaredField("table");
    tableField.setAccessible(true);
    final Object table = tableField.get(threadLocalMap);
    for (int i = 0, length = Array.getLength(table); i < length; ++i) {
        final Object entry = Array.get(table, i);
        if (entry != null) {
            final Object threadLocal = ((WeakReference)entry).get();
            if (threadLocal != null) {
                log(i, threadLocal);
                Array.set(table, i, null);
                ++count;
            }
        }
    }
    return count;
}
回答のコードによると、ThreadLocalのエラーはいくつかのスレッドのThreadLocalがリリースできないと推定されています.なぜリリースできないのですか?スレッドはまだ停止されていません.ThreadLocalは一つのThreadのThreadMapの下にあるイベントで維持されています.
これらのentryはWeakReferenceを継承しています.以上のコードは各threadのthreadMapのentryをnullに設定するべきです.このように元のentryは引用源がなく、Weak ReferenceとしてGCでクリアされます.
 
コール先コード:
while (!executorService.awaitTermination(100, TimeUnit.MILLISECONDS)){
    BootStrap.log.info("      !!!!!!!");
    if(null !=executorService){
        executorService.shutdownNow();
        immolate();
    }
   executorService=null;
   break;
}
このようにこれらのまだ停止していないスレッドの文脈Class Loaderはwebapp Class Loaderとは無関係になりました.webapp Class Loaderは正常なGCになります.