2013-11-26 46 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