首页 > 解决方案 > 在centos中,当Tomcat 7关闭时,就发生了这很可能造成内存泄漏。不知道为什么

问题描述

每次Tomcat发布一个项目,关闭后。sh,它打印如下日志。并且会在linux中打开几个Java进程,占用内存很大,找了半天原因,不知道怎么处理,希望大佬帮忙解答。

四月 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 时不起作用,但在startup.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");
        }
    }

}

标签: javaspringmemorymemory-leaks

解决方案


推荐阅读