文档详情

tomcatreload时内存泄漏的处理hotdeployment.docx

发布:2017-06-09约7千字共6页下载文档
文本预览下载声明
我做的应用是以Spring为系统的基础框架,mysql为后台数据库.在tomcat上发布后,总是不能进行热部署(reload),多次reload后,就会出OutOfMemory PermGen,为此烦恼了很久,总于下定决心找找根源.经过3天的不懈努力,小有成果,记录下来实际上下面的分析都已经没什么用了,如果你使用tomcat6.0.26及以后的版本,我所说的这些情况都已经被处理了,并且比我处理的还要多很多.可以下载tomcat6.0.26的源代码看看WebappClassLoader类的处理就成了.通过分析工具的分析(用了YourKit,以及JDK1.6/bin下的jps/jmap/jhat),发现有下面几个方面会造成memory leak.1.SystemClassLoader与WebappClassLoader加载的类相互引用,tomcat reload只是卸载WebappClassloader中的class,SystemClassLoader是不会卸载的(否则其他应用也停止了).但是WebappClassloader加载的类被SystemClassLoader引用的化,WebappClassloader中的相关类就不会被JVM进行垃圾收集目前发现2种容易产生这种leak的现象.a.在使用java.lang.ThreadLocal的时候很容易产生这种情况b.使用jdbc驱动,而且不是在tomcat中配置的公共连接池.则java.sql.DriverManager一定会产生这种现象ThreadLocal.set(Object),如果这个Object是WebappsClassLoader加载的,使用之后没有做ThreadLocal.set(null)或者ThreadLocal.remove(),就会产生memory leak.由于ThreadLocal实际上操作的是java.lang.Thread类中的ThreadLocalMap,Thread类是由SystemClassLoder加载的.而这个线程实例(main thread)在tomcat reload的时候不会销毁重建,必然就产生了SystemClassLoder中的类引用WebappsClassLoader的类.DriverManager也是由SystemClassLoder载入的,当初始化某个JDBC驱动的时候,会向DriverManager中注册该驱动,通常是***.driver,例如com.mysql.jdbc.Driver这个Driver是通过class.forName()加载的,通常也是加载到WebappClassLoader.这就出现了两个classLoader中的类的交叉引用.导致memory leak.解决办法:写一个ServletContextListener,在contextDestroyed方法中统一删除当前Thread的ThreadLocalMap中的内容.public class ApplicationCleanListener implements ServletContextListener {public void contextInitialized(ServletContextEvent event) {}public void contextDestroyed(ServletContextEvent event) {???????? //处理ThreadLocal?? ThreadLocalCleanUtil.clearThreadLocals();?? /*?? * 如果数据故驱动是通过应用服务器(tomcat etc...)中配置的公用连接池,这里不需要否则必须卸载Driver?? *??? * 原因: DriverManager是System classloader加载的, Driver是webappclassloader加载的,?? * driver保存在DriverManager中,在reload过程中,由于system?? * classloader不会销毁,driverManager就一直保持着对driver的引用,?? * driver无法卸载,与driver关联的其他类?? * ,例如DataSource,jdbcTemplate,dao,service....都无法卸载?? */?? try {??? System.out.println(clean jdbc Driver......);??? for (Enumeration e = DriverManager.getDrivers(); e????? .hasMoreElements();) {???? Driver driver = (Driver) e.
显示全部
相似文档