nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

ModuleClassLoader

JBoss Advent Calendar 2012の12日目のエントリです。JBoss AS7のクラスローディングを行っているJBoss Modulesのクラスローダ、ModuleClassLoaderの実装を見ていきましょう。

ModuleClassLoaderの定義はModuleClassLoader extends ConcurrentClassLoaderとなっており、ConcurrentClassLoader extends SecureClassLoaderとなっています。一般的にクラスローダをちょこっとカスタマイズするときによく利用されるURLClassLoaderもextends SecureClassLoaderです。

ModuleClassLoaderもConcurrentClassLoaderも、ついでに言えばURLClassLoaderもJava 7では全てClassLoader.registerAsParallelCapable()を呼び出している並列クラスローディング対応クラスローダです。

ConcurrentClassLoaderは一回だけ他のConcurrentClassLoaderに移譲することを許容する並列クラスローダの基底実装です。import文にsun.misc.Unsafeがありますが見なかったことにしましょう。

ModuleClassLoader.findClass()はロード対象クラスが既にロード済みかどうかをチェックし、まだの場合はModule.loadModuleClass()を呼び出します。Module.loadModuleClass()ではまずロード対象がシステムモジュールかどうかを判断します。システムモジュールの場合はシステムモジュールからロードして終わりです。そうではない場合はロード対象のパス名(パッケージ名)から該当するLocalLoaderを取得して、ロードします。このLocalLoaderは実際には自モジュールから参照可能なモジュールのModuleClassLoaderを参照しており、定義はModuleClassLoaderに内部クラスとして存在しています。パス名とLocalLoaderのMapはモジュールの依存関係解決フェーズで構築されており、対象モジュールを高速にルックアップすることを可能にしています。実際にクラスをロードするのはModuleClassLoader.loadClassLocal()メソッドで、内部クラスのLocalLoader.loadClassLocal()から呼ばれます。

コールスタック。

  • ModuleClassLoader.loadClassLocal()
    • 実際のロード処理
  • ModuleClassLoader.LocalLoader.loadClassLocal()
  • Module.loadModuleClass()
    • 対象ModuleClassLoaderをルックアップ
  • ModuleClassLoader.findClass()
    • ロード済みをチェックしてからModuleに移譲
  • ModuleClassLoader.performLoadClassUnChecked()
  • ModuleClassLoader.performLoadClassChecked()
  • ModuleClassLoader.performLoadClass()
  • ModuleClassLoader.loadClass()
    • ここからfindClass()まではConcurrentClassLoaderに定義されている
  • Class.forName()

ねっ、簡単でしょ?