【问题标题】:Tomcat8 memory leakTomcat8内存泄漏
【发布时间】:2015-03-22 06:00:03
【问题描述】:

当我尝试在 Java 8 上停止 tomcat8 时,出现一些内存泄漏错误:

org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)
 java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:142)
 com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:40)
23-Jan-2015 08:18:10.202 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [pool-5-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread


23-Jan-2015 08:18:10.205 SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [com.util.ThreadLocalProperties$1] (value [com.util.ThreadLocalProperties$1@2fafda6e]) and a value of type [java.util.Properties] (value [{}]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

ThreadLocalProperties 类是:

public class ThreadLocalProperties extends Properties {

    private static final long serialVersionUID = -4260632266508618756L;
    private final ThreadLocal<Properties> localProperties = new ThreadLocal<Properties>() {
        @Override
        protected Properties initialValue() {
            return new Properties();
        }
    };

    public ThreadLocalProperties(Properties properties) {
        super(properties);
    }

    @Override
    public String getProperty(String key) {
        String localValue = localProperties.get().getProperty(key);
        return localValue == null ? super.getProperty(key) : localValue;
    }

    @Override
    public Object setProperty(String key, String value) {
        return localProperties.get().setProperty(key, value);
    }

    public ThreadLocal<Properties> getThreadLocal() {
        return localProperties;
    }
}

然后我像这样开始和停止它:

@WebListener()
public class GeneralListener implements ServletContextListener {

    ThreadLocalProperties threadLocalProperties = new ThreadLocalProperties(System.getProperties());

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        threadLocalProperties.getThreadLocal().remove();
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        System.setProperties(threadLocalProperties);
    }
}

为什么我会得到所有这些内存泄漏错误?同样,当我运行关机时,它并没有关闭它,我必须手动终止该进程。

怎么了?

【问题讨论】:

标签: java tomcat memory-leaks


【解决方案1】:

我认为您的问题类似于this。当您重新部署应用程序时,apache 会在 system.gc(); 不起作用的地方逐步部署它,并且在开发阶段重新部署几次后,永久生成的空间已满,您会收到内存泄漏错误。

请在重新部署几次后继续重新启动您的服务器,以便可以通过重新启动来清除 PermGen 空间。

或者

a 您也可以通过更改服务器中的 PermGen 空间来解决它。 请访问here

希望对你有帮助。

【讨论】:

  • 我不重新部署服务器。我 ./shutdown 和 ./startup 它。我相信它清除了烫发尺寸没有?
  • 另外,当我尝试将烫发大小定义添加到 tomcat8 时,我收到一条警告说它被忽略了
  • 您是否也在运行 Java 8?我不是 100% 确定,但我认为 permgen 空间已与该版本无关。我看不出为什么 Tomcat 记录的这些信息性警告消息与 permgen 空间有任何关系,如果您硬重启服务器,它们也无需担心。
  • 我不是说重新部署你的服务器,我说的是重新部署你的网络应用程序,你试图在 apache tomcat 服务器上运行。您保存和构建应用程序的多次,然后它会创建一个 .war 文件,对吗?并将逐步重新部署。 (这将在几次构建后引发内存泄漏错误。)
  • @Dejel 尝试手动更改 PermGen 空间:要在 Windows 上设置环境变量,请手动创建一个 setenv.bat,并将其放入 ${tomcat-folder}\bin 文件夹中。 ${tomcat-folder}\bin\setenv.bat 设置JAVA_OPTS=-Dfile.encoding=UTF-8 -Xms128m -Xmx1024m -XX:PermSize=64m -XX:MaxPermSize=256m 或更多。它不会进一步显示任何警告,也不会忽略。
【解决方案2】:

没有什么可担心的。这是当tomcat 检测到应用程序已启动它自己的Thread 或创建ThreadLocal 时输出的标准消息。如果您在关闭时终止线程并在不再需要 threadlocals 时删除它们,则不会有问题。

为什么我会得到所有这些内存泄漏错误?同样,当我跑步时 关闭,它不会关闭它,我必须手动杀死 过程。

当应用程序启动 ScheduledExecutor(但任何其他 Thread/TheadPool 都会发生这种情况)并且没有在 contextDestroyed 上关闭它时,我已经看到了这种行为。因此,请检查您是否在应用程序/服务器停止时关闭线程。

现在谈谈你的具体问题为什么服务器没有停止: JDBC 驱动程序在 JVM 中注册为单例,并与所有 Web 应用程序共享。更多信息 here. 解决问题的最佳方法是将 MySQL 驱动程序移到 Tomcat 的 /lib 文件夹中。如果您无法做到这一点,您可以尝试this,但这更像是一种 hack,而不是真正的解决方案。

【讨论】:

  • 谢谢。是的,它真的有帮助!有趣的是,如果我部署名为 Algo 的应用程序,并在 server.xml WEB-INF/web.xml 它会将 Algo War 部署到 Algo 文件夹和 ROOT 文件夹!
  • 将 mysql 驱动程序移动到 Tomcat 的 /lib 文件夹中对我不起作用。
  • 您是否从 /WEB-INF/lib 中删除了驱动程序?此外,如果您的应用程序正在启动线程并且没有停止它们,您也会收到此消息。
猜你喜欢
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 2013-01-20
  • 2011-10-31
  • 2019-08-10
  • 2013-06-24
相关资源
最近更新 更多