当前位置:  开发笔记 > 编程语言 > 正文

在Tomcat中重新部署应用程序时发生内存泄漏

如何解决《在Tomcat中重新部署应用程序时发生内存泄漏》经验,为你挑选了1个好方法。

我有部署在Tomcat 7.0.70中的WebApplication.我模拟了以下情况:

    我创建了堆转储.

    然后我发送了Http请求,并在服务的方法中打印了当前线程及其classLoader.然后我调用了Thread.currentThread.sleep(10000).

    在同一时刻,我在Tomcat的管理页面中点击了"取消部署此应用程序".

    我创建了新的堆转储.

    几分钟后,我创建了新的肝转储.


结果


线程转储

在下面的屏幕上,您可以看到,在我单击"redeploy"之后,除了线程"http-apr-8081-exec-10"之外,所有线程(与此Web应用程序关联)都被终止.当我设置Tomcat的属性"renewThreadsWhenStoppingContext == true"时,你可以看到一段时间后这个线程("http-apr-8081-exec-10")被杀死并且新线程(http-apr-8081-exec-11) )而不是它.所以我没想到在创建堆转储3之后会有旧的WCL,因为没有任何旧的线程或对象.

在此输入图像描述

堆转储1

在以下两个屏幕上,您可以看到当应用程序运行时,只有一个WCL(其参数"started"= true).线程"http-apr-8081-exec-10"有contextClassLoader = URLClassLoader(因为它在Tomcat的池中).我只是谈论这个线程,因为你将能够看到这个线程将处理我未来的HTTP请求.

在此输入图像描述

在此输入图像描述

发送HTTP请求

现在我发送HTTP请求,并在我的代码中获取有关当前线程的信息.您可以看到我的请求由线程"http-apr-8081-exec-10"处理

??? 23, 2016 9:28:16 AM c.c.c.f.s.r.ReportGenerationServiceImpl INFO:  request has been handled in 
   thread = http-apr-8081-exec-10,  its contextClassLoader = WebappClassLoader
   context: /hdi
   delegate: false
   repositories:
   /WEB-INF/classes/
   ----------> Parent Classloader: java.net.URLClassLoader@4162ca06

然后我单击"重新部署我的Web应用程序",我在控制台中收到以下消息.

 ??? 23, 2016 9:28:27 AM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
 SEVERE: The web application [/hdi] appears to have started a thread named [http-apr-8081-exec-10] but has failed to stop it. This is very likely to create a memory leak.

堆垃圾2

在以下屏幕上,您可以看到WebAppClassLoader有两个实例.其中一个(编号#1)是旧的(其属性"已启动"= false).WCL#2是在重新部署应用程序后创建的(其属性"started"= true).我们审查的主题有contextClassLoader ="org.apache.catalina.loader.WebappClassLoader".为什么?我希望看到contextClassLoader ="java.net.URLClassLoader"(毕竟,当任何线程完成其工作时,它将返回到Tomcat的池,并且其属性"contextClassLoader"被设置为任何基类类加载器).

在此输入图像描述

在此输入图像描述

在此输入图像描述

Heapd转储3

你可以看到没有线程"http-apr-8081-exec-10",但有线程"http-apr-8081-exec-11",它有contextClassLoader ="WebappClassLoader"(为什么不是URLClassLoader?) .

最后我们有以下内容:有一个线程"http-apr-8081-exec-11",其中包含对WebappClassLoader#1的引用.当我在WCL#1上制作"最近的GC根"时,我会看到线程11的引用.

在此输入图像描述

在此输入图像描述

问题.

在线程完成其工作后,如何强制说Tomcat返回旧值contextClassLoader(URLClassLoader)?

如何确保Tomcat在线程续订期间不复制旧值"contextClassLoader"?

也许,你知道解决我问题的其他方法吗?



1> Naveed Kamra..:

在生产环境中,Tomcat通常不是一个好的选择。我在一些生产应用程序上使用了Tomcat,但我发现即使正确设置了堆大小和其他配置,并且每次重新加载应用程序时,内存消耗都在增加。在不重新启动tomcat服务之前,不会完全回收内存。我们确实测试了所有此类实验,例如清除日志,重新部署所有应用程序,每月或每周在最不繁忙的时间定期重启tomcat。但是最后我不得不说,我们已经将生产环境转移到了Glassfish和WebSphere。

希望您已经浏览了以下页面:

Java Web应用程序中的内存泄漏

Tomcat修复内存泄漏?

https://developers.redhat.com/blog/2014/08/14/find-fix-memory-leaks-java-application/

http://www.tomcatexpert.com/blog/2010/04/06/tomcats-new-memory-leak-prevention-and-detection

如果您的Web应用程序未与Tomcat紧密结合,那么您可以考虑使用另一个Web容器。现在,我们甚至在开发机器和生产上都使用Glassfish,而在做出这一决定的那一天,我们节省了很多时间。尽管Glassfish和其他此类服务器在启动时会花费更多时间,因为它们不像Tomcat那样轻巧,但是使用寿命会更轻松。

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有