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

ClassLoader Leak Patterns

Jan 18, 2015

Download

Technology

nekop

 
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
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