Submit Search
クラスローダーについて
•
27 likes
•
9,594 views
S
Suguru ARAKAWA
Follow
1 of 42
Download now
Downloaded 111 times
More Related Content
クラスローダーについて
1.
クラスローダーについて
わかる! JVM あらかわ (@ashigeru)
2.
本日の内容 クラスロードの仕組み クラスローダーの名前空間
リローディングの技術 その他の話題 アンロードの条件 パッケージプライベート シリアライゼーション 2010/08/06 #jvmjvm 2
3.
2.17.2 Loading 5 Loading,
Linking, and Initializing 5.3.2 Loading Using a User-defined Class Loader クラスロードの仕組み 2010/08/06 #jvmjvm 3
4.
クラスローダーの作り方 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
5.
ロード処理の委譲 ロード中に他のクラスローダーを利用できる
loadClass()は最初に委譲先からクラスを検索 委譲先になければfindClass()を起動 2010/08/06 #jvmjvm 5
6.
“推奨”の委譲スタイル すでにロード済みのクラスがあればそれを返す 委譲先(親クラスローダー)でロード
委譲先でロードできなければ自身でロード 2010/08/06 #jvmjvm 6
7.
“推奨”委譲スタイルの問題 委譲先(親)とライブラリが衝突する
親のライブラリの内容が優先される パッケージ名変更で乗り切るバッドノウハウ 2010/08/06 #jvmjvm 7
8.
現実の委譲スタイル 某アプリケーションサーバー (PARENT_LAST)
委譲先(親)を最後に検索する 自身のクラスローダーをまず最初に検索 親のライブラリに影響を受けにくい OSGi パッケージごとにクラスの公開/非公開を選べる 委譲しても非公開クラスはロードできない 「親の親」はデフォルトで非公開扱い 複数の委譲先を持てる 必要なライブラリだけを選べる 2010/08/06 #jvmjvm 8
9.
ここまでのまとめ java.lang.ClassLoaderを継承してカスタムクラ
スローダーを作成 findClass()をオーバーライドする defineClass()にクラスファイルバイナリを渡す 他のクラスローダーにロードを委譲できる 通常は委譲先から順にクラスを探索 2010/08/06 #jvmjvm 9
10.
5.3 Creation and
Loading (defining loaders) 5.4.3.1 Class and Interface Resolution クラスローダーの空間 2010/08/06 #jvmjvm 10
11.
同じ名前のクラス 同じ名前のクラスは単一JVM上に存在できる?
WARなどが典型的 2010/08/06 #jvmjvm 11
12.
定義ローダー 同じ名前でも定義ローダーが違えば別クラス
defineClass()を実行したローダーのこと Class.getClassLoader()はこれを返す 2010/08/06 #jvmjvm 12
13.
参照先のロード 自身の定義ローダーで参照先をロード
下記のような依存関係は解決できない 2010/08/06 #jvmjvm 13
14.
PARENT_LASTの挙動 子が定義ローダーになりライブラリが共存可能
子になければ親のライブラリを利用 2010/08/06 #jvmjvm 14
15.
ドッペルゲンガー (1) PARENT_LASTでcommons-loggingを利用
commons-loggingは親子ともに所持 子のLogFactoryが優先される 2010/08/06 #jvmjvm 15
16.
ドッペルゲンガー (2) commons-loggingの実装を探しにいく
子には特別の実装が無いため次に親を探す 2010/08/06 #jvmjvm 16
17.
ドッペルゲンガー (3) LogFactoryの実装にLog4jFactoryを利用
Log4jFactoryの定義ローダーはCL1 2010/08/06 #jvmjvm 17
18.
ドッペルゲンガー (4) Log4jFactoryは親のLogFactoryを継承
定義ローダーの関係で親のものを利用する LogFactoryが二つ出現 2010/08/06 #jvmjvm 18
19.
ドッペルゲンガー (5) Log4jFactoryをLogFactory(CL2)に変換失敗
2つのLogFactoryは完全に別物 推奨の移譲スタイルはそれなりに意味がある 2010/08/06 #jvmjvm 19
20.
ここまでのまとめ 同じクラスでも定義ローダーが違えば別物
ドッペルゲンガーが出現することも 参照先のクラスは定義ローダーを使う PARENT_LASTなどと組み合わせると混乱する 2010/08/06 #jvmjvm 20
21.
クラスローダーを利用した擬似的なクラスリローディング リローディングの技術
2010/08/06 #jvmjvm 21
22.
リローディングの技術 JVMを立てたままクラスをリロードして即座に
変更を反映 JUnit 3系 – GUIについてたアレ Seasar 2 – Hot Deploy 他にもいろいろあると思う 2010/08/06 #jvmjvm 22
23.
リローディングの仕組み (1) リローディング用のクラスローダーを子に作成
親には利用したいクラスローダーを指定 2010/08/06 #jvmjvm 23
24.
リローディングの仕組み (2) 親からクラスファイルのバイナリを拝借
parent.getResourceAsStream() など 2010/08/06 #jvmjvm 24
25.
リローディングの仕組み (3) リローディング用のクラスローダーで定義
親を探しに行かない 普通はパッケージを限定する 2010/08/06 #jvmjvm 25
26.
リローディングの仕組み (4) リクエストごとにクラスローダーを作り直す
リクエストごとにクラスをリロード クラスの更新を反映させられる 2010/08/06 #jvmjvm 26
27.
リローディングとセッション セッション情報でドッペルゲンガー
2010/08/06 #jvmjvm 27
28.
ここまでのまとめ 定義ローダーを毎回捨ててリローディング
強制的に自分が定義ローダーになるようにする モデルの引継ぎが意外と大変 自作するとたいていハマる 2010/08/06 #jvmjvm 28
29.
2.17.8 Unloading of
Classes and Interfaces 5.3 Creation and Loading (runtime packages) (Object Serialization Specification) その他の話題 2010/08/06 #jvmjvm 29
30.
ネタ アンロードの条件 パッケージプライベート
シリアライゼーション 2010/08/06 #jvmjvm 30
31.
アンロードの条件 (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
32.
アンロードの条件 (2) クラスローダーがGCで回収可能になるまで、ク
ラスは一つもアンロードされない 先ほどの例は80,000~くらいでメモリ枯渇した インスタンスやjava.lang.Classを保持している とクラスローダーがGC回収可能にならない 一つでもリークしたら全てのクラスがリーク 共有空間でキャッシュしてたりすると大変 ライフサイクルの管理が重要になる 2010/08/06 #jvmjvm 32
33.
アンロードの条件 (3) クラスをアンロードさせたい場合には定期的に
クラスローダーを捨てる キャッシュするならライフサイクルに注意 特に共有空間に漏れないように 動的クラス生成を行うフレームワークは要注意 アスペクトウィービング スクリプト言語のJITコンパイラ ただし、アンロードは「最適化」という扱い メモリ効率の向上 アンロード自体に対応していない可能性も 2010/08/06 #jvmjvm 33
34.
アンロードの条件 (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
35.
パッケージプライベート (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
36.
パッケージプライベート (2) 同じパッケージで別のクラスローダー
OSGi環境でのテストでよくやる 2010/08/06 #jvmjvm 36
37.
実行時パッケージ 実行時パッケージごとにプライベート
クラスの定義ローダーごとに別パッケージ扱い 先ほどの例は “IllegalAccessError” 2010/08/06 #jvmjvm 37
38.
シリアライゼーション ObjectInputStreamが使うクラスローダーは?
2010/08/06 #jvmjvm 38
39.
ObjectInputStream (1) 一番近いユーザー定義クラスローダーを利用
コールスタック上のクラスの定義ローダー この例ではBarのCL1を利用してデシリアライズ 2010/08/06 #jvmjvm 39
40.
ObjectInputStream (2) 親ローダーにシリアライゼーションフレームワ
ークを置いても使いにくい フレームワーククラスの定義ローダーを常に利用 ObjectInputStreamにはクラスローダーを指定 できない 以下のメソッドを上書きすれば対応は可能 resolveClass resolveProxy 2010/08/06 #jvmjvm 40
41.
ObjectInputStream (3) 以下の組み合わせは怪しい
カスタムクラスローダー オブジェクト永続化 (XML, JSON等も含む) OSGi + Object DBは個人的に鬼門 どのクラスローダーでロードすれば? クラスローダーをまたいでネストしたモデルは? あまりいい思い出がない 2010/08/06 #jvmjvm 41
42.
参考文献 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
Download