tomcatメモリ漏れ問題が解決されました.スレッドプールが閉じられません.
3136 ワード
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の解決策があります.以下の方法で解決すればいいです.
これを理解すれば、方法があります.
これらのentryはWeakReferenceを継承しています.以上のコードは各threadのthreadMapのentryをnullに設定するべきです.このように元のentryは引用源がなく、Weak ReferenceとしてGCでクリアされます.
コール先コード:
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になります.