SlideShare a Scribd company logo
クラスローダーについて

   わかる! JVM
 あらかわ (@ashigeru)
本日の内容
 クラスロードの仕組み
 クラスローダーの名前空間
 リローディングの技術
 その他の話題
  アンロードの条件
  パッケージプライベート
  シリアライゼーション




          2010/08/06 #jvmjvm   2
2.17.2 Loading
5 Loading, Linking, and Initializing
5.3.2 Loading Using a User-defined Class Loader

クラスロードの仕組み


                      2010/08/06 #jvmjvm          3
クラスローダーの作り方
  1.   java.lang.ClassLoaderのサブクラスを定義
  2.   findClass()をオーバーライド
  3.   クラスファイルをdefineClass()に食わせる
  4.   結果のjava.lang.Classを返す

public class MyClassLoader extends ClassLoader {
  @Override
  protected Class<?> findClass(String name) throws … {
      byte[] content = …;
      Class<?> aClass = defineClass(name, content, 0, content.length);
      return aClass;
  }
  …

                              2010/08/06 #jvmjvm                    4
ロード処理の委譲
 ロード中に他のクラスローダーを利用できる
  loadClass()は最初に委譲先からクラスを検索
  委譲先になければfindClass()を起動




            2010/08/06 #jvmjvm   5
“推奨”の委譲スタイル
 すでにロード済みのクラスがあればそれを返す
 委譲先(親クラスローダー)でロード
 委譲先でロードできなければ自身でロード




         2010/08/06 #jvmjvm   6
“推奨”委譲スタイルの問題
 委譲先(親)とライブラリが衝突する
  親のライブラリの内容が優先される
  パッケージ名変更で乗り切るバッドノウハウ




          2010/08/06 #jvmjvm   7
現実の委譲スタイル
 某アプリケーションサーバー (PARENT_LAST)
   委譲先(親)を最後に検索する
    自身のクラスローダーをまず最初に検索
    親のライブラリに影響を受けにくい
 OSGi
   パッケージごとにクラスの公開/非公開を選べる
    委譲しても非公開クラスはロードできない
    「親の親」はデフォルトで非公開扱い
   複数の委譲先を持てる
    必要なライブラリだけを選べる

            2010/08/06 #jvmjvm   8
ここまでのまとめ
 java.lang.ClassLoaderを継承してカスタムクラ
  スローダーを作成
  findClass()をオーバーライドする
  defineClass()にクラスファイルバイナリを渡す
 他のクラスローダーにロードを委譲できる
  通常は委譲先から順にクラスを探索




              2010/08/06 #jvmjvm   9
5.3 Creation and Loading (defining loaders)
5.4.3.1 Class and Interface Resolution

クラスローダーの空間


                      2010/08/06 #jvmjvm      10
同じ名前のクラス
 同じ名前のクラスは単一JVM上に存在できる?
  WARなどが典型的




           2010/08/06 #jvmjvm   11
定義ローダー
 同じ名前でも定義ローダーが違えば別クラス
  defineClass()を実行したローダーのこと
  Class.getClassLoader()はこれを返す




              2010/08/06 #jvmjvm   12
参照先のロード
 自身の定義ローダーで参照先をロード
  下記のような依存関係は解決できない




          2010/08/06 #jvmjvm   13
PARENT_LASTの挙動
 子が定義ローダーになりライブラリが共存可能
  子になければ親のライブラリを利用




          2010/08/06 #jvmjvm   14
ドッペルゲンガー (1)
 PARENT_LASTでcommons-loggingを利用
  commons-loggingは親子ともに所持
  子のLogFactoryが優先される




              2010/08/06 #jvmjvm   15
ドッペルゲンガー (2)
 commons-loggingの実装を探しにいく
  子には特別の実装が無いため次に親を探す




             2010/08/06 #jvmjvm   16
ドッペルゲンガー (3)
 LogFactoryの実装にLog4jFactoryを利用
   Log4jFactoryの定義ローダーはCL1




               2010/08/06 #jvmjvm   17
ドッペルゲンガー (4)
 Log4jFactoryは親のLogFactoryを継承
   定義ローダーの関係で親のものを利用する
   LogFactoryが二つ出現




               2010/08/06 #jvmjvm   18
ドッペルゲンガー (5)
 Log4jFactoryをLogFactory(CL2)に変換失敗
   2つのLogFactoryは完全に別物
   推奨の移譲スタイルはそれなりに意味がある




               2010/08/06 #jvmjvm     19
ここまでのまとめ
 同じクラスでも定義ローダーが違えば別物
  ドッペルゲンガーが出現することも
 参照先のクラスは定義ローダーを使う
  PARENT_LASTなどと組み合わせると混乱する




           2010/08/06 #jvmjvm   20
クラスローダーを利用した擬似的なクラスリローディング

リローディングの技術


            2010/08/06 #jvmjvm   21
リローディングの技術
 JVMを立てたままクラスをリロードして即座に
  変更を反映
  JUnit 3系 – GUIについてたアレ
  Seasar 2 – Hot Deploy
  他にもいろいろあると思う




              2010/08/06 #jvmjvm   22
リローディングの仕組み (1)
 リローディング用のクラスローダーを子に作成
  親には利用したいクラスローダーを指定




          2010/08/06 #jvmjvm   23
リローディングの仕組み (2)
 親からクラスファイルのバイナリを拝借
  parent.getResourceAsStream() など




                2010/08/06 #jvmjvm   24
リローディングの仕組み (3)
 リローディング用のクラスローダーで定義
  親を探しに行かない
  普通はパッケージを限定する




          2010/08/06 #jvmjvm   25
リローディングの仕組み (4)
 リクエストごとにクラスローダーを作り直す
  リクエストごとにクラスをリロード
  クラスの更新を反映させられる




          2010/08/06 #jvmjvm   26
リローディングとセッション
 セッション情報でドッペルゲンガー




          2010/08/06 #jvmjvm   27
ここまでのまとめ
 定義ローダーを毎回捨ててリローディング
  強制的に自分が定義ローダーになるようにする
 モデルの引継ぎが意外と大変
  自作するとたいていハマる




          2010/08/06 #jvmjvm   28
2.17.8 Unloading of Classes and Interfaces
5.3 Creation and Loading (runtime packages)
(Object Serialization Specification)

その他の話題


                     2010/08/06 #jvmjvm       29
ネタ
 アンロードの条件
 パッケージプライベート
 シリアライゼーション




          2010/08/06 #jvmjvm   30
アンロードの条件 (1)
 このプログラムはどうなる?
  C0, C1, C2, …は全てロード可能とする



ClassLoader cl = new InfiniteClassLoader();
for (long i = 0; i < Long.MAX_VALUE; i++) {
   cl.loadClass("C" + i);
}




                    2010/08/06 #jvmjvm        31
アンロードの条件 (2)
 クラスローダーがGCで回収可能になるまで、ク
  ラスは一つもアンロードされない
  先ほどの例は80,000~くらいでメモリ枯渇した

 インスタンスやjava.lang.Classを保持している
  とクラスローダーがGC回収可能にならない
  一つでもリークしたら全てのクラスがリーク
  共有空間でキャッシュしてたりすると大変
  ライフサイクルの管理が重要になる


             2010/08/06 #jvmjvm   32
アンロードの条件 (3)
 クラスをアンロードさせたい場合には定期的に
  クラスローダーを捨てる
  キャッシュするならライフサイクルに注意
  特に共有空間に漏れないように
  動的クラス生成を行うフレームワークは要注意
  アスペクトウィービング
  スクリプト言語のJITコンパイラ
 ただし、アンロードは「最適化」という扱い
  メモリ効率の向上
  アンロード自体に対応していない可能性も

           2010/08/06 #jvmjvm   33
アンロードの条件 (4)
 2,000,000クラスまで確認 (飽きた)
   クラスローダーを毎回捨てている




ClassLoader cl = new InfiniteClassLoader();
for (long i = 0; i < Long.MAX_VALUE; i++) {
   ClassLoader cl = new InfiniteClassLoader();
   cl.loadClass("C" + i);
}


                    2010/08/06 #jvmjvm           34
パッケージプライベート (1)
 パッケージプライベートのアクセス制御は?
     package a;
     public class Hoge {
       /*package*/ int foo() {
           return 100;
       }
     }

     package a;
     public class HogeTest {
       @Test
       public void about_package() {
           Hoge hoge = new Hoge();
           assertThat(hoge.foo(), is(100));
       }
     }

                  2010/08/06 #jvmjvm          35
パッケージプライベート (2)
 同じパッケージで別のクラスローダー
  OSGi環境でのテストでよくやる




           2010/08/06 #jvmjvm   36
実行時パッケージ
 実行時パッケージごとにプライベート
  クラスの定義ローダーごとに別パッケージ扱い
  先ほどの例は “IllegalAccessError”




            2010/08/06 #jvmjvm   37
シリアライゼーション
 ObjectInputStreamが使うクラスローダーは?




             2010/08/06 #jvmjvm   38
ObjectInputStream (1)
 一番近いユーザー定義クラスローダーを利用
  コールスタック上のクラスの定義ローダー
  この例ではBarのCL1を利用してデシリアライズ




           2010/08/06 #jvmjvm   39
ObjectInputStream (2)
 親ローダーにシリアライゼーションフレームワ
  ークを置いても使いにくい
  フレームワーククラスの定義ローダーを常に利用
  ObjectInputStreamにはクラスローダーを指定
   できない
 以下のメソッドを上書きすれば対応は可能
  resolveClass
  resolveProxy




                  2010/08/06 #jvmjvm   40
ObjectInputStream (3)
 以下の組み合わせは怪しい
  カスタムクラスローダー
  オブジェクト永続化 (XML, JSON等も含む)

 OSGi + Object DBは個人的に鬼門
  どのクラスローダーでロードすれば?
  クラスローダーをまたいでネストしたモデルは?
  あまりいい思い出がない



              2010/08/06 #jvmjvm   41
参考文献
 Java仮想マシン仕様 第2版
    ISBN: 4-89471-356-X
 Java言語仕様 第3版
    ISBN: 4-89471-715-8
 JSR 202: Java Class File Specification Update
    http://jcp.org/en/jsr/summary?id=202
 “オブジェクト直列化形式”
    http://java.sun.com/javase/ja/6/docs/ja/techno
     tes/guides/serialization/



                      2010/08/06 #jvmjvm          42

More Related Content

PPTX
Tomcatの実装から学ぶクラスローダリーク #渋谷Java
PDF
ClassLoader Leak Patterns
PPTX
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
PDF
TLS 1.3 と 0-RTT のこわ〜い話
PPTX
Metaspace
PDF
これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本
PDF
Garbage First Garbage Collection (G1 GC) #jjug_ccc #ccc_cd6
ODP
スレッドダンプの読み方
Tomcatの実装から学ぶクラスローダリーク #渋谷Java
ClassLoader Leak Patterns
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
TLS 1.3 と 0-RTT のこわ〜い話
Metaspace
これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本
Garbage First Garbage Collection (G1 GC) #jjug_ccc #ccc_cd6
スレッドダンプの読み方

What's hot (20)

PDF
LogbackからLog4j 2への移行によるアプリケーションのスループット改善 ( JJUG CCC 2021 Fall )
PDF
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
PDF
Cloud Foundry にアプリケーションを push する際の典型的な10のエラー
PDF
CPUから見たG1GC
PPTX
Keycloakの実際・翻訳プロジェクト紹介
PDF
Unified JVM Logging
PDF
Where狙いのキー、order by狙いのキー
PDF
TDD のこころ
PDF
人生がときめくAPIテスト自動化 with Karate
PDF
単なるキャッシュじゃないよ!?infinispanの紹介
PDF
MySQLで論理削除と正しく付き合う方法
PPTX
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
PDF
JVMのGCアルゴリズムとチューニング
PDF
テスト文字列に「うんこ」と入れるな
PDF
より速く より運用しやすく 進化し続けるJVM(Java Developers Summit Online 2023 発表資料)
PPTX
WayOfNoTrouble.pptx
PPTX
【修正版】Django + SQLAlchemy: シンプルWay
PDF
フロー効率性とリソース効率性について #xpjug
LogbackからLog4j 2への移行によるアプリケーションのスループット改善 ( JJUG CCC 2021 Fall )
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
Cloud Foundry にアプリケーションを push する際の典型的な10のエラー
CPUから見たG1GC
Keycloakの実際・翻訳プロジェクト紹介
Unified JVM Logging
Where狙いのキー、order by狙いのキー
TDD のこころ
人生がときめくAPIテスト自動化 with Karate
単なるキャッシュじゃないよ!?infinispanの紹介
MySQLで論理削除と正しく付き合う方法
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
JVMのGCアルゴリズムとチューニング
テスト文字列に「うんこ」と入れるな
より速く より運用しやすく 進化し続けるJVM(Java Developers Summit Online 2023 発表資料)
WayOfNoTrouble.pptx
【修正版】Django + SQLAlchemy: シンプルWay
フロー効率性とリソース効率性について #xpjug
Ad

Viewers also liked (18)

PPTX
java.lang.OutOfMemoryError #渋谷java
PDF
JVM のいろはにほ #javajo
PDF
Concurrent Mark-Sweep Garbage Collection #jjug_ccc
PPTX
jcmd をさわってみよう
PPTX
GCについて
PDF
GCが止まらない
PPT
Javaバイトコード入門
PPTX
Java トラブル解析支援ツール HeapStats のご紹介
PPTX
HeapStats(Java解析ツールバトル)
PDF
渋谷java−あなたのプロジェクトで気軽にjavaをバージョンアップするために必要なこと
PDF
JVM-Reading-ConcurrentMarkSweep
PDF
負荷テストを行う際に知っておきたいこと 初心者編
PDF
新版 OutOfMemoryErrorを知る
PPTX
第六回渋谷Java Java8のJVM監視を考える
PDF
徹底解説!Project Lambdaのすべて[JJUG CCC 2013 Fall H-2]
PPTX
HotSpotコトハジメ
PDF
Javaはどのように動くのか~スライドでわかるJVMの仕組み
PDF
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
java.lang.OutOfMemoryError #渋谷java
JVM のいろはにほ #javajo
Concurrent Mark-Sweep Garbage Collection #jjug_ccc
jcmd をさわってみよう
GCについて
GCが止まらない
Javaバイトコード入門
Java トラブル解析支援ツール HeapStats のご紹介
HeapStats(Java解析ツールバトル)
渋谷java−あなたのプロジェクトで気軽にjavaをバージョンアップするために必要なこと
JVM-Reading-ConcurrentMarkSweep
負荷テストを行う際に知っておきたいこと 初心者編
新版 OutOfMemoryErrorを知る
第六回渋谷Java Java8のJVM監視を考える
徹底解説!Project Lambdaのすべて[JJUG CCC 2013 Fall H-2]
HotSpotコトハジメ
Javaはどのように動くのか~スライドでわかるJVMの仕組み
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Ad

Similar to クラスローダーについて (20)

PDF
Javaセキュアコーディングセミナー東京第1回 講義
PDF
Layout analyzerでのgroovyの利用について
PDF
Grails 2.0.0.M1の話
PPT
Clojure+Leiningenで3分Hadoop
PDF
JBoss AS 7 / EAP 6 modules and class loading
PPTX
TDC20111031_Groovy_Geb
PDF
Javaのログ出力: 道具と考え方
PPT
PDF
Lombok java
PDF
Java Concurrency, A(nother) Peek Under the Hood [Java Day Tokyo 2016 3-C]
PDF
Spock's world
PDF
Java開発の強力な相棒として今すぐ使えるGroovy
PDF
gen-class とバイトコード(第3回 gen-class 勉強会資料)
PDF
SDLoader SeasarCon 2009 Whire
KEY
Kawaz的jQuery入門
PDF
Mavenへのはじめの一歩
PDF
JavaScript.Next
PDF
第三回ありえる社内勉強会 「いわががのLombok」
PDF
JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]
PDF
JBoss Application Server におけるディレクトリトラバーサルの脆弱性
Javaセキュアコーディングセミナー東京第1回 講義
Layout analyzerでのgroovyの利用について
Grails 2.0.0.M1の話
Clojure+Leiningenで3分Hadoop
JBoss AS 7 / EAP 6 modules and class loading
TDC20111031_Groovy_Geb
Javaのログ出力: 道具と考え方
Lombok java
Java Concurrency, A(nother) Peek Under the Hood [Java Day Tokyo 2016 3-C]
Spock's world
Java開発の強力な相棒として今すぐ使えるGroovy
gen-class とバイトコード(第3回 gen-class 勉強会資料)
SDLoader SeasarCon 2009 Whire
Kawaz的jQuery入門
Mavenへのはじめの一歩
JavaScript.Next
第三回ありえる社内勉強会 「いわががのLombok」
JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]
JBoss Application Server におけるディレクトリトラバーサルの脆弱性

クラスローダーについて