classloader leak patterns

30
クラスローダ リークパターン なにそれおいしいの? Takayoshi Kimura Senior Software Maintenance Engineer, JBoss Global Support Service Red Hat

Upload: nekop

Post on 18-Jan-2015

8.421 views

Category:

Technology


3 download

DESCRIPTION

 

TRANSCRIPT

Page 1: ClassLoader Leak Patterns

クラスローダリークパターン

なにそれおいしいの?

Takayoshi Kimura

Senior Software Maintenance Engineer, JBossGlobal Support Service

Red Hat

Page 2: ClassLoader Leak Patterns

自己紹介

Page 3: ClassLoader Leak Patterns

nekop

● JBossの中の人● Emacsで Java書く人●オープンソース大好きっ子●ネコよりイヌが好き

Page 4: ClassLoader Leak Patterns

宣伝

Page 5: ClassLoader Leak Patterns

JBossではエンジニアを募集しております!

Page 6: ClassLoader Leak Patterns

JBossで働きませんか● Javaとオープンソースが好きな人におすすめ

●おやつ無料●飲み物自動販売機無料

Page 7: ClassLoader Leak Patterns

JBossで働きませんか●主に「オープンソースで遊ぶ」のと「技術的な人助け」

● Linuxカーネルから Javaアーキテクトまで豊富な同僚

Page 8: ClassLoader Leak Patterns

 本題 

Page 9: ClassLoader Leak Patterns

クラスローダリーク

Page 10: ClassLoader Leak Patterns

何が起こる?● java.lang.OutOfMemoryError: perm gen space

●クラス定義情報が置いてあるメモリ領域 (Perm)を消費しっぱなし

Page 11: ClassLoader Leak Patterns

いつリークする?●クラスローダが破棄、再作成されるタイミング

●具体例として、アプリケーションサーバに再デプロイを行ったとき

Page 12: ClassLoader Leak Patterns

なぜリークする?●そのクラスローダへの参照が残ってるから

●そのクラスローダからロードされたクラスへの参照が残ってるから

●クラスローダをまたがる参照

Page 13: ClassLoader Leak Patterns

パターンその1

ThreadLocal

Page 14: ClassLoader Leak Patterns

ThreadLocal

●同一スレッド上で値の受け渡しができて便利

●フレームワークなどでよく使われている

Page 15: ClassLoader Leak Patterns

ThreadLocalの参照構造● ThreadLocalに設定した値はThreadから強参照される

●詳しく知りたい人はソース嫁

Page 16: ClassLoader Leak Patterns

ThreadLocal開放条件● ThreadLocalへ到達可能な強参照が一つもない場合開放される

● Threadが開放されたら一緒に開放される

Page 17: ClassLoader Leak Patterns

ありがちなリークコードpublic class ThreadLocalKeyValue {

private ThreadLocal tl = new ThreadLocal();

public void add(Object key, Object value) { tl.set(new KeyValuePair(key, value)); }

public Object getKey() { return ((KeyValuePair)tl.get()).key; }

public Object getValue() { return ((KeyValuePair)tl.get()).value; }

private class KeyValuePair { public Object key, value; public KeyValuePair(Object key, Object value) { this.key = key; this.value = value; } }}

Page 18: ClassLoader Leak Patterns

テストThreadLocalKeyValue target = new ThreadLocalKeyValue();ReferenceQueue queue = new ReferenceQueue();PhantomReference ref = new PhantomReference(target, queue);

target.add("foo", "bar");target = null;

System.gc();System.out.println("Released?: " + ref.isEnqueued());

Page 19: ClassLoader Leak Patterns

テスト結果falseって何よ

( ゚Д ゚ )

Page 20: ClassLoader Leak Patterns

修正public class ThreadLocalKeyValue {

private ThreadLocal tl = new ThreadLocal();

public void add(Object key, Object value) { tl.set(new KeyValuePair(key, value)); }

public Object getKey() { return ((KeyValuePair)tl.get()).key; }

public Object getValue() { return ((KeyValuePair)tl.get()).value; }

private static class KeyValuePair { public Object key, value; public KeyValuePair(Object key, Object value) { this.key = key; this.value = value; } }}

Page 21: ClassLoader Leak Patterns

テスト結果true

Page 22: ClassLoader Leak Patterns

ハァ ?( ゚Д ゚ )

Page 23: ClassLoader Leak Patterns

ThreadLocalまとめ● 設定した値は Threadから強参照される● ThreadLocalに渡す「値」の参照関係に注意● スレッドのコントロールが自分に無い環境では

Threadの開放に伴う ThreadLocalの開放は期待できない– アプリケーションサーバ上では当然スレッドはプールされている

– リークしないのは「入れたら確実に消す (一時的な利用 )」か「入れっぱなしでも値の参照関係が安全だと保証できる」場合のみ

Page 24: ClassLoader Leak Patterns

ThreadLocalと Tomcat

● Tomcatはアンデプロイ時に ThreadLocalをリフレクションで開放してくれる機能がある– アプリケーションやフレームワーク、ライブラリのクラスローダリークバグを隠してしまういやんな機能

– 心当たりのあるフレームワーク /ライブラリ開発者さんは直してください!

● でもその機能にスレッドセーフじゃないバグがあるので 6.0.27以降は無効になっている– https://issues.apache.org/bugzilla/show_bug.

cgi?id=48895

Page 25: ClassLoader Leak Patterns

パターンその2

java.util.logging

Page 26: ClassLoader Leak Patterns

java.util.loggingの Level

● Level継承するとクラスローダがリークする

●ここ嫁● http://blogs.sun.com/fkieviet/entry/cl

assloader_leaks_the_dreaded_java

Page 27: ClassLoader Leak Patterns

パターンその 3既成

ライブラリ

Page 28: ClassLoader Leak Patterns

既成ライブラリ● 元々複数のクラスローダ上で動作することを想定していないライブラリ– ContextClassLoaderや staticフィールドの誤用– ThreadLocalやWeakHashMapなどの参照構造の理解不足

Page 29: ClassLoader Leak Patterns

既成ライブラリ● Commons-logging

– だいぶ前に一通り直ったけど、利用する側のコードによってはリークする

● Commons-beanutils– 1.8.0時点で一応メジャーな問題は全部解決している

– https://issues.apache.org/jira/browse/BEANUTILS-291

● 他にもいっぱいあるよ!

Page 30: ClassLoader Leak Patterns