2013-11-26 21 views
12

在Java 7中加载KeyStore时,类加载器被泄漏。在Java 7中加载KeyStore泄漏类加载器

我已经使用Tomcat 7.0.47和classloader-leak-prevention中的“查找泄漏”功能进行了确认。这里是test code,webapp with the leak in @Configurationwebapp with the leak in @Controller

从本质上讲,这些行导致泄漏对我来说:

InputStream is = null; 
try { 
    is = new FileInputStream("./app.truststore"); 
    KeyStore keyStore = KeyStore.getInstance("JKS"); 
    keyStore.load(is, "changeit".toCharArray()); 
} catch (Exception e) { 
    System.out.println(e); 
} finally { 
    if (is != null) { 
     is.close(); 
    } 
} 

如果我删除KeyStore.load()一切工作正常,但是这显然不是一个有效的解决方案。

它不适用于Oracle JDK 1.7u15,u17,u21,u25,u40和u45以及OpenJDK 1.7u40和u45。

它适用于Oracle JDK 1.6u39,u41,u43和45以及OpenJDK 1.6.0。

这是在Microsoft Windows Server 2008 R2 Standard 64位上测试的。 OpenJDK是GitHub上alexkasko最新的unofficial builds

有没有人有一个想法可能导致Classloader泄漏?我尝试使用堆转储并调用“GC根”的最短路径,但返回的结果。

+5

嗨,大家知道,我写了一个Spring MVC测试应用程序,并将您的逻辑添加到应用程序初始化程序。然后,我用plumbr的一个评估版来检测它,它立即检测到一个类加载器泄漏。 JRE和JDK为7.0,运行时为基于Apache Tomcat-7.0.42.A.RELEASE的TC Server 2.9.3。 它报告你的应用程序有一个类加载器泄漏,它可以防止在每次取消部署时卸载5348个类。没有你的代码,应用程序是干净的。仍在寻找原因。 – TechTrip

回答

2

该类加载程序确实是而不是泄漏。当部署一堆空应用程序并且PermGen达到某个阈值时,Tomcat的Find Leaks会停止报告应用程序。因此这是一个误报。

1

我用几种不同的方法重新讨论了这一点。我把你的逻辑放在一个webapp中。我尝试的第一个使用Spring MVC和Gemfire,并且将您的代码添加到了Web应用程序初始化程序。当测试代码与一个名为Plumbr的商业工具的评估时,它检测到泄漏的类加载器。但是我无法在eval中看到该报告。

Plumbr人与我联系并向我提供了报告,我可以看到Gemfire似乎是问题的根源。我正在使用Gemfire会话和远程缓存,每隔一段时间它都不会优雅地关闭,在这种情况下会出现泄漏。

我再修剪一切回到最简单的Web应用程序,1个弹簧控制器和1种豆从您的代码收集的逻辑如下:

public class ClassloaderLeakingBean { 

    private static Logger logger = LoggerFactory.getLogger(ClassloaderLeakingBean.class); 
    public void initiateLeak(String trustStore) throws Exception { 
     InputStream is = null; 
     try { 
      is = new FileInputStream(trustStore); 
      KeyStore keyStore = KeyStore.getInstance("JKS"); 
      keyStore.load(is, "password".toCharArray()); 
     } catch (Exception e) { 
      logger.error(e.getMessage(), e); 
     } finally { 
      if (is != null) { 
       is.close(); 
       logger.info("The Input Stream is Closed!"); 
      } 
     } 

    } 
} 

我然后把豆成一个控制器,简称为initiateLeak方法来响应GET请求。这个简化的版本没有显示任何我抛出的类加载器泄漏的迹象。

Java运行时版本如下:

Java版本 “1.7.0” 的Java(TM)SE运行时环境(建立 1.7.0-B147)的Java的HotSpot(TM)64位服务器VM(build 21.0-b17,混合模式)

我使用maven编译代码,源代码和目标为1.7。

我打算进一步作为一个独立的应用程序进行调查,但我还没有看到任何有关Java 7和KeyStore类的classloader泄漏报告。

需要注意的是:我运行的是64位JVM,Windows 7 Enterprise,它的行为可能与32位环境不同。在寻找内存泄漏时,我会亲自远离非官方的构建。

+0

感谢您的努力!我用两个泄露给我的webapps更新了我的原始问题。你有可能确认他们是否泄漏? – Arlo

+0

嗨,阿罗,我想让他们尝试假设我能让他们跑步。会让你知道。感恩节快乐! – TechTrip