2013-11-26 9 views
12

Java 7でKeyStoreをロードすると、Classloaderがリークします。Java 7でKeyStoreをロードするとクラスローダーがリークする

Tomcat 7.0.47およびclassloader-leak-preventionの「リークの検索」機能を使用してこれを確認しました。ここにはtest codewebapp with the leak in @Configurationおよびwebapp with the leak in @Controllerがあります。

は、基本的にこれらの行は私のためにリークが発生:私はKeyStore.load()を削除すると、すべてが正常に動作しますが、それは明らかに機能するソリューションではありません

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(); 
    } 
} 

Oracle JDK 1.7u15、u17、u21、u25、u40、u45、OpenJDK 1.7u40、u45では動作しません。

これは、Oracle JDK 1.6u39、u41、u43、およびOpenJDK 1.6.0で動作します。

これは、Microsoft Windows Server 2008 R2 Standard 64 Bitでテストされました。 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という商用ツールの評価に対してこのコードをテストすると、漏れたクラスローダーが検出されました。しかし、私は評価で報告書を見ることができませんでした。

Plumbrの人々が私に連絡してレポートを私に提出し、私はGemfireが問題の根源であるように見えました。私はGemfireセッションとリモートキャッシュを使用していましたが、それは正常に終了せず、この場合はリークとして現れました。

私は当時、最も単純なWebアプリケーション、1つのスプリングコントローラと、次のようにあなたのコードから収集されたロジックで1つの豆にすべてをトリミング:私は、単にinitiateLeakと呼ばれるコントローラに豆を投げた

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!"); 
      } 
     } 

    } 
} 

GETリクエストに応答してメソッドを呼び出します。この単純化されたバージョンは、私がそれに投げるものであっても、クラスローダの漏れの兆候を示さなかった。

Javaランタイムのバージョンは次のとおりです。

Javaバージョン "1.7.0" は、Java(TM)SEランタイム環境(ビルド 1.7.0-b147)は、Java HotSpot(TM)64ビットサーバーをVM(ビルド21.0-b17、混合モード)

1.7のソースとターゲットでmavenを使用してコードをコンパイルしました。

私はこれをさらにスタンドアロンのアプリケーションとして調査するつもりですが、Java 7とKeyStoreクラスに対してクラスローダーリークの報告はありませんでした。

私は64bit JVM、Windows 7 Enterpriseで動作していますが、これは32ビット環境とは異なる動作をする可能性があります。メモリリークを探す際に私は個人的に非公式のビルドから離れています。

+0

あなたの努力に感謝します!私は私のために漏れる2つのwebappsで私の元の質問を更新しました。彼らが漏れているかどうかを確認することは可能でしょうか? – Arlo

+0

こんにちはアルロー、私はそれらを実行することができますと仮定して試してみたいと思います。お知らせします。ハッピー感謝祭! – TechTrip

関連する問題