tomcat5.5 reload 出现方法区溢出的问题

来源:互联网 发布:天翼飞young3.09 算法 编辑:程序博客网 时间:2024/06/05 19:35

        最近在用eclipse调试一个老项目,server用的tomcat5.5, reload了几次应用就报错,方法区溢出:

Exception in thread "main" java.lang.OutOfMemoryError: PermGen space。

用visualvm查看heap dump,发现项目中的第三方jar包的类都被重新加载了好几次,最后方法区空间不足,一直进行fullgc,却无法回收重复的类。
  用tomcat7相同环境下运行正常,reload几次后,方法区空间不足时,会回收所有原先WebappClassLoader重复加载的类,
2个tomcat jvm运行模式和参数都一致,都是使用默认的垃圾回收机制,后来tomcat5.5试着用了CMS垃圾收集器还是报原先的错误:-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
应该是tomcat5.5 reload代码实现有问题
tomcat7的reload源码,应该tomcat7在reload时清理引用做了写改进吧,WebappClassLoader处理内存泄露 clearReferences():
    /**     * Clear references.     */    protected void clearReferences() {        // De-register any remaining JDBC drivers        clearReferencesJdbc();        // Stop any threads the web application started        clearReferencesThreads();        // Check for leaks triggered by ThreadLocals loaded by this class loader        checkThreadLocalsForLeaks();        // Clear RMI Targets loaded by this class loader        clearReferencesRmiTargets();        // Null out any static or final fields from loaded classes,        // as a workaround for apparent garbage collection bugs        if (clearReferencesStatic) {            clearReferencesStaticFinal();        }         // Clear the IntrospectionUtils cache.        IntrospectionUtils.clear();        // Clear the classloader reference in common-logging        if (clearReferencesLogFactoryRelease) {            org.apache.juli.logging.LogFactory.release(this);        }        // Clear the resource bundle cache        // This shouldn't be necessary, the cache uses weak references but        // it has caused leaks. Oddly, using the leak detection code in        // standard host allows the class loader to be GC'd. This has been seen        // on Sun but not IBM JREs. Maybe a bug in Sun's GC impl?        clearReferencesResourceBundles();        // Clear the classloader reference in the VM's bean introspector        java.beans.Introspector.flushCaches();    }
查了相关的资料:
 一般程序库可能存在内存泄漏的地方有:
 1.JDBC驱动注册
2.一些日志框架
3.在ThreadLocal中保存对象,但是并不去删除它 
4.启动了线程,但没有停止它 
而Java API存在内存泄漏的地方包括:
1.使用javax.imageio API (the Google Web Toolkit can trigger this) 
2.使用java.beans.Introspector.flushCaches() (Tomcat does this to prevent memory leaks caused by this caching) 
3.使用XML解析器(the root cause is unknown due to a bug in the JRE) 
4.使用RMI远程方法调用(somewhat ironically, causes a leak related to the garbage collector)  
 5.从Jar文件中读取资源




0 0