Java Tomcat 6内存泄漏日志条目

Java Tomcat 6内存泄漏日志条目,java,spring,memory-leaks,tomcat6,catalina.out,Java,Spring,Memory Leaks,Tomcat6,Catalina.out,下面是CentOS机器上我的Catalina.out文件中唯一条目的输出。我正在用Spring3和我的应用程序运行Tomcat6。有一大堆,所以我只选了一些,不断重复。这种情况并非总是发生,但至少每周发生一次 问题是我能做些什么来防止吼叫的发生? 正确关闭你的webapp。不要让这些线程继续运行 或者,不要继续重新部署webapp。在其destroy()方法中设置一个Servlet来管理它。线程可以检查一个标志,看看它们是否必须继续 在servlet中,在destroy方法中执行以下操作。显然,

下面是CentOS机器上我的Catalina.out文件中唯一条目的输出。我正在用Spring3和我的应用程序运行Tomcat6。有一大堆,所以我只选了一些,不断重复。这种情况并非总是发生,但至少每周发生一次

问题是我能做些什么来防止吼叫的发生?
正确关闭你的webapp。不要让这些线程继续运行


或者,不要继续重新部署webapp。

在其
destroy()
方法中设置一个Servlet来管理它。线程可以检查一个标志,看看它们是否必须继续

在servlet中,在destroy方法中执行以下操作。显然,您需要能够访问
集合
,但如何获得该集合实际上取决于系统的设置方式

destroy() {
    for (MyThread thread : myThreads) {
        thread.stopProcessing();
    }
}
您的
MyThread
类将有如下内容:

public class MyThread {
    private boolean finished = false;

    @Override
    public void run() {
        while (!finished) {
            //do something
        }
    }

    public void stopProcessing() {
        finished = true;
    }
}

当您定义一个外部标志时,假设线程在设置该标志时轮询并退出-它必须是
易失性的
。否则,该线程可能永远看不到其他线程所做的更改

然而,在标准API中已经有一个类似的特性-它被称为
interrupt()
方法和
Thread.currentThread().isInterrupted()
。不需要复制已经存在的逻辑。请参阅:

也就是说,在每个线程上调用
interrupt()
也是一个坏主意,因为不能保证所有线程都响应它。在检查您的异常时,我注意到以下线程未正确清理:

  • com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0
    -关闭C3P0数据源。因为您使用的是Spring,所以只需添加
    destroy method=“close”
    。这条线我们做完了

  • 文件收割机
    -据我所知,此线程是由创建的。关闭应用程序时(或者当不再需要该类时,我从未使用过它),您需要显式调用
    FileCleaningTracker.exitWhenFinished()
    ,或者让Spring来执行此操作(参见上文)。有可能是一些第三方库使用了它,但没有正确关闭-这意味着它有一个bug

  • pool-1-thread-22
    -这是内部实用程序创建的线程之一。确保在关机期间对应用程序中的每个这样的池调用
    shutdown()

  • org.springframework.scheduling.quartz.SchedulerFactoryBean#0#u Worker-2
    -quartz Worker线程(实际运行作业的线程)
    SchedulerFactoryBean
    自动为您关闭调度程序,我认为Tomcat在这里是错误的,我也经常看到这个错误。尽管如此,将SchedulerFactoryBean.waitForJobsToCompleteOnShutdown设置为
    true
    似乎可以解决这个问题

  • com.itezy.shared.domain.DirEntry.data
    -我不确定这个。要么是您自己的线程需要在关闭时中断,要么是H2数据库线程(?)需要检查其堆栈以猜测其来源


底线是:不要只杀死所有移动的线程(实际上,Tomcat在发出此警告后会为您这样做),而是确定线程的来源,并使用特定于框架/库的
close()
方法允许进一步清理。温柔点。

我是否覆盖了系统中每个servlet上的destroy方法?另外,我是否将MyThread类放在每个servlet下?@Bikash否,只需要覆盖一个servlet上的destroy,这个servlet实际上不在任何地方调用,而是启动的(web.xml)。然后,该servlet需要访问线程集合,并在destroy方法中迭代该集合。显然,在创建线程时需要填充该集合,并且需要确保在关闭Tomcat之前完成的线程从集合中移除它们自己,否则将导致内存泄漏<代码>完成必须是易变的,为什么不简单地使用每个线程可用的现有的中断标志呢?看:这是一个毫无帮助的建议,类似于“说不就行了”。OP在他的脑海中正确地关闭了webapp,因为Tomcat(以及几乎所有其他servlet容器)的一个功能是在不需要任何特殊编码的情况下停止webapps。Tomascz的评论不仅描述了错误消息是什么,还描述了如何跟踪它。
public class MyThread {
    private boolean finished = false;

    @Override
    public void run() {
        while (!finished) {
            //do something
        }
    }

    public void stopProcessing() {
        finished = true;
    }
}