Каждый раз, когда Tomcat публикует проект после завершения работы. sh, он печатает следующий журнал. И откроет несколько процессов Java в linux, займёт много памяти, долго найдет причину, не знает как с этим справиться, надеюсь, большой человек поможет ответить.
四月 02, 2019 3:59:47 下午 org.apache.coyote.AbstractProtocol pause
信息: Pausing ProtocolHandler ["http-bio-80"]
四月 02, 2019 3:59:47 下午 org.apache.coyote.AbstractProtocol pause
信息: Pausing ProtocolHandler ["ajp-bio-8009"]
四月 02, 2019 3:59:47 下午 org.apache.catalina.core.StandardService stopInternal
信息: Stopping service Catalina
四月 02, 2019 3:59:47 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
严重: The web application [/ShiJie] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak.
四月 02, 2019 3:59:47 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
严重: The web application [/ShiJie] appears to have started a thread named [pool-3-thread-1] but has failed to stop it. This is very likely to create a memory leak.
四月 02, 2019 3:59:47 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
严重: The web application [/ShiJie] appears to have started a thread named [I/O dispatcher 1] but has failed to stop it. This is very likely to create a memory leak.
四月 02, 2019 3:59:47 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
Я использую этот код, но они не работают при tomcat shutdown.sh, но они работают при запуске.sh
public class ThreadListener implements ServletContextListener {
private static final Logger logger = LoggerFactory.getLogger(ThreadListener.class);
/**
* 线程池
*/
private static ExecutorService exec = Executors.newCachedThreadPool();
@Override
public void contextInitialized(ServletContextEvent sce) {
logger.info("监听器初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
logger.info("监听器关闭中");
exec.shutdownNow();
ThreadLocalImmolater.getInstance().immolate();
logger.info("关闭数据库连接");
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
logger.info(String.format("deregistering jdbc driver: %s", driver));
} catch (SQLException e) {
logger.error(String.format("Error deregistering driver %s", driver), e);
}
}
// //清理线程
// try {
// logger.info("销毁线程池");
// ThreadPoolService.getExecutor().shutdownNow();
// logger.info("清理线程");
// ThreadLocalImmolater.getInstance().immolate();
// } catch (Exception e) {
// logger.error(String.format("清理线程出错,错误信息:%s", e));
// e.printStackTrace();
// }
}
}
<listener>
<display-name>MyListener</display-name>
<listener-class>common.ThreadListener</listener-class>
</listener>
public class ThreadLocalImmolater {
private static final Logger logger = LoggerFactory.getLogger(ThreadLocalImmolater.class);
Boolean debug;
private final static ThreadLocalImmolater INSTANCE = new ThreadLocalImmolater();
public static ThreadLocalImmolater getInstance(){
return INSTANCE;
}
public ThreadLocalImmolater() {
debug = true;
}
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);
for (final Thread thread : Thread.getAllStackTraces().keySet()) {
count += clear(threadLocalsField.get(thread));
count += clear(inheritableThreadLocalsField.get(thread));
// if (thread != null) {
// thread.setContextClassLoader(null);
// }
}
logger.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;
}
private void log(int i, final Object threadLocal) {
if (!debug) {
return;
}
if (threadLocal.getClass() != null &&
threadLocal.getClass().getEnclosingClass() != null &&
threadLocal.getClass().getEnclosingClass().getName() != null) {
logger.info("threadLocalMap(" + i + "): " +
threadLocal.getClass().getEnclosingClass().getName());
}
else if (threadLocal.getClass() != null &&
threadLocal.getClass().getName() != null) {
logger.info("threadLocalMap(" + i + "): " + threadLocal.getClass().getName());
}
else {
logger.info("threadLocalMap(" + i + "): cannot identify threadlocal class name");
}
}
}