最初にUnifiedClassLoader3#loadClass()が呼ばれるのはorg.jboss.system.server.ServerInfoをロードするとき
UnifiedClassLoader3(RepositoryClassLoader).loadClass(String, boolean) line: 357 UnifiedLoaderRepository3.loadClass(String, boolean, ClassLoader) line: 188 UnifiedLoaderRepository3.loadClass(String) line: 572 MBeanServerImpl.instantiate(String, ClassLoader, Object[], String[]) line: 1192 MBeanServerImpl.instantiate(String) line: 233 ServerImpl.createMBean(String, String) line: 480 ServerImpl.doStart() line: 387 ServerImpl.start() line: 315 Main.boot(String[]) line: 195 Main$1.run() line: 463 Thread.run() line: 534
MBeanServerImplはフィールドとしてclassLoaderRepositoryを持っている(デフォルトはUnifiedLoaderRepository3)ので、クラスロードはそこを経由する。
UnifiedLoaderRepository3#loadClass(String)は
-
- classLoadersのひとつめのloadClass()を呼ぶ
- 見つからなければ、TCLのloadClass()
- 見つからなければ、getNativeClassForName()
- 見つからなければ、ClassNotFoundException
UnifiedClassLoader3#loadClass(String, boolean)は
UnifiedLoaderRepository3のgetCachedClass()を呼んでキャッシュを探す
→ キャッシュはMapに単純に入っている(もちろん各クラスはdefineしたClassLoaderに紐づいているハズ)
見つからなければ、synchronized loadClassImpl()
→ クラスロード用ロックを取得*1(Cuncurrentとか使っている。LoadMgr3はユーティリティ)
LoadMgr3.beginLoadTask()でロード開始
→ UnifiedLoaderRepository3#loadClassFromCache()でまたキャッシュを探す
UnifiedLoaderRepository3のpackagesMap*2からパッケージ名(org.jboss.system.server)に対応した、クラスローダのSetを返す
Setがあった…そのクラスローダにクラスを探させるタスクをスケジュールする
Setは無い…自分で探せ UnifiedClassLoader3#loadClassLocally()
→ そのクラスがブラックリストにあれば即ClassNotFound
super.loadClass() … 普通にURLClassLoaderとして探す
見つからなければブラックリストへ
キャッシュclassesに追加
「クラスローダ-ロードしたクラス」マップのloaderToClassesMapを更新
WARをデプロイして実験
MainDeployerがデプロイする:org.jboss.web.tomcat.tc5.Tomcat5、org.jboss.web.tomcat.tc5.TomcatDeployerに委譲
デプロイ時にもいろいろロードするけど、WAR内のクラス(test.web.TestServlet)はロードされない
アクセス時にロードしようとする
UnifiedClassLoader3(RepositoryClassLoader).loadClass(String, boolean) line: 377 UnifiedClassLoader3(ClassLoader).loadClass(String) line: 235 StandardWrapper.isContainerProvidedServlet(String) line: 1532 StandardWrapper.loadServlet() line: 991 StandardWrapper.allocate() line: 750 StandardWrapperValve.invoke(Request, Response) line: 130 StandardContextValve.invoke(Request, Response) line: 178 CustomPrincipalValve.invoke(Request, Response) line: 39 SecurityAssociationValve.invoke(Request, Response) line: 153 JaccContextValve.invoke(Request, Response) line: 59 StandardHostValve.invoke(Request, Response) line: 126 ErrorReportValve.invoke(Request, Response) line: 105 StandardEngineValve.invoke(Request, Response) line: 107 CoyoteAdapter.service(Request, Response) line: 148 Http11Processor.process(InputStream, OutputStream) line: 856 Http11Protocol$Http11ConnectionHandler.processConnection(TcpConnection, Object[]) line: 744 PoolTcpEndpoint.processSocket(Socket, TcpConnection, Object[]) line: 527 MasterSlaveWorkerThread.run() line: 112 ThreadWithAttributes(Thread).run() line: 534
test.web.TestServletが検索されるがClassNotFoundとなり、以降検索されずじまい…なのに正常にサーブレットは処理された。。。??
↓
4.0.2から
jbossweb-tomcat55.sar/META-INF/jboss-service.xmlでUseJBossWebLoader=falseだから、Tomcat側でロードするんだった!
…UseJBossWebLoader=trueにしたらtest.web.TestServletの検索に成功!