[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends-ml 11072] JavaVM でクラスは いつロードされるか?



村山@netgeneです.

帰りの電車での質問の返事です.

「JavaVMにおいて,クラスはいつロードされるか?」

できるだけ完結に答えると,概ね以下のようになります.
#完結に答えてさえも,この程度にはなる.
#口頭で答えられるような質問ではない.

##書いた後で思ったけど,これだけで一仕事ですな.
##誰も説明する人がいないわけだ.f(^^;


○JVM仕様では厳密に「どの時点でロードする」と決まっているわけ
ではなく,ある程度の幅があるように定められている.JavaVMで実際に
必要とされる初回実行時までならば,それこそJVM起動以前も含めて
どの時点で「ロード」することも許されているはず.

ということは,特に理由がない限りは実行時のパフォーマンスのことを
考えて可能な限りlazyに実装するだろうから,多くのJVMでは初回実行時
ギリギリまでロードするのを遅らせるように実装されていると考えられる.

昔はAOTコンパイラなんてのもあったので,その場合は「コンパイル時」に
すべて静的にリンクしたりもしていたようです.最近はHotSpotVMや
IBM JITの様に動的最適化をバリバリかけるVMの方が主流なので,事前に
静的リンクすることはあまりないでしょう.


○仕様書で関係する箇所は,主に以下の通り.

・"4.9.1 The Verification Process"
http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#9766

"Pass4:
For efficiency reasons, certain tests that could in principle be 
performed in Pass 3 are delayed until the first time the code for the 
method is actually invoked. In so doing, Pass 3 of the verifier avoids 
loading class files unless it has to."....

ある種の処理は初回実行時まで遅らせて良いとかどうとかいうことが
書かれています.

・" 5 Loading, Linking, and Initializing"全体.
http://java.sun.com/docs/books/vmspec/2nd-edition/html/ConstantPool.doc.html
この章ではクラスのロード処理が記述されている.

このうち特に,
"5.3 Creation and Loading"
と
"5.4.3 Resolution"
http://java.sun.com/docs/books/vmspec/2nd-edition/html/ConstantPool.doc.html#73492
辺りが強く関係しています.

・試訳及び簡単な解説.
http://www.takilab.cs.kobe-u.ac.jp/~java/publications/javaVM5.html#5.4.3
http://www.takilab.cs.kobe-u.ac.jp/~java/publications/comment5.html#t17

・new命令を例にした,もう少し具体的な解説.
http://www.netgene.co.jp/java/docs/javaPressVol17.html#4


○"ConstantPool Resolution"とは,
「コンスタントプールから実装依存の具体的な値を動的に決定する処理」
である.

「コンスタントプールの決定」の具体的な処理は,コンスタントプールの
各項目の種類やJVM実装により異なる.このうち「クラス参照に対する決定
処理」では,その時点で必要なクラスがまだロードされていない時に,
クラスをロードする処理を引き起こすことがある.

もう少し具体的に言うと,new(インスタンス生成),getstatic(static
フィールドの読み込み), putstatic(staticフィールドへの書き込み),
invokestatic(staticメソッドの呼び出し,),リフレクション(自己反映計算)
メソッドの使用,JVMの起動などの処理がクラスのロードを引き起こす可能性を
持つ.
http://www.takilab.cs.kobe-u.ac.jp/~java/publications/javaVM5.html#5.5


「クラス参照の決定(resolution)」
と
「動的なクラスのロード」
とは,厳密には同じではない.

が,事実上は

「クラス参照の決定が行われる時に,そのクラス参照が表すクラスがまだロード
  されていない時に,そのクラス,及びそのクラスの直接又は間接のスーパー
  クラス,直接又は間接のスーパーインターフェースがロードされる」

と考えて,ほぼ正しいはずです.

○一例として,次のような感じで処理が進むと考えるとイメージし易いでしょう.

1,あるメソッドが実行中にnew,getstaticなどで,まだ決定済みでない
クラス参照があった場合に,クラス参照の決定処理が開始される.

2,クラス定義自体がまだロードされていない場合は,このクラス参照の
決定より先にクラス定義(クラスファイル)のロードが開始される.

3,そのクラスをロードした後に,そのスーパークラスやスーパーインター
フェースもロードされる.(この辺はちょっとうろ覚え.)

4,newのような処理では,これ以上はロードされない可能性が高い.
invokestatic(staticメソッドの呼び出し)では,その後にメソッド参照の
解決とバイトコード=ベリファイヤによるメソッドのベリファイなどが行われる
はず.JITコンパイルが行われることもある.

○この他,例えば動的最適化のために,上の例よりは早い段階でロードする
戦略を採る可能性もある.

例えばあるメソッドAがあって,そのメソッドがボトルネックになっており,
動的最適化の対象になったとする.Aからは他のクラスのメソッドBやクラスCが
利用されていたが,Aを最適化する段階では,まだ一度も呼び出されずロードも
されていない.

この場合でもメソッドBやクラスCの詳細を知ることで,エスケープ解析などを
使ったより強力な最適化がかけられるかもしれない.もしそうならば一度も
呼び出されていないクラスをロードする方がロードしないよりパフォー
マンス上有利になるので,この段階でロードするようなJVM実装もあり得る
とは思う.

-- 
村山敏清 株式会社ネットジーン 〒164-0001 
東京都中野区中野3-33-3 インツ中野ビル 5F
E-mail:murayama@xxxxxxxxxxxxx 
TEL:(03)5328-3670 FAX:(03)5328-3673
http://www.netgene.co.jp/