Java Tomcat 6内存泄漏日志条目
下面是CentOS机器上我的Catalina.out文件中唯一条目的输出。我正在用Spring3和我的应用程序运行Tomcat6。有一大堆,所以我只选了一些,不断重复。这种情况并非总是发生,但至少每周发生一次 问题是我能做些什么来防止吼叫的发生?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方法中执行以下操作。显然,
正确关闭你的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()
也是一个坏主意,因为不能保证所有线程都响应它。在检查您的异常时,我注意到以下线程未正确清理:
-关闭C3P0数据源。因为您使用的是Spring,所以只需添加com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0
。这条线我们做完了destroy method=“close”
-据我所知,此线程是由创建的。关闭应用程序时(或者当不再需要该类时,我从未使用过它),您需要显式调用文件收割机
,或者让Spring来执行此操作(参见上文)。有可能是一些第三方库使用了它,但没有正确关闭-这意味着它有一个bugFileCleaningTracker.exitWhenFinished()
-这是内部实用程序创建的线程之一。确保在关机期间对应用程序中的每个这样的池调用pool-1-thread-22
shutdown()
-quartz Worker线程(实际运行作业的线程)org.springframework.scheduling.quartz.SchedulerFactoryBean#0#u Worker-2
自动为您关闭调度程序,我认为Tomcat在这里是错误的,我也经常看到这个错误。尽管如此,将SchedulerFactoryBean.waitForJobsToCompleteOnShutdown设置为SchedulerFactoryBean
似乎可以解决这个问题true
-我不确定这个。要么是您自己的线程需要在关闭时中断,要么是H2数据库线程(?)需要检查其堆栈以猜测其来源com.itezy.shared.domain.DirEntry.data
底线是:不要只杀死所有移动的线程(实际上,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;
}
}