Tomcatソース分析(クラスローダ)
1.Tomcatには5種類のClassLoader:commonLoader:servlet仕様パッケージ、servlet-apiなどの共通jarパッケージをロードする.JAr、/common catalinaLoader:Tomcatをロードするための実装jarパッケージ、例えばcatalina.JAr,/server sharedLoader:strutsコアパッケージのようなすべてのアプリケーションをロードするための共有jarパッケージを下に置くことができます./shared webappClassLoaderはwebアプリケーションの下のclassをロードするために使用され、1つのwebアプリケーションにはwebappClassLoader JasperLoaderがwebアプリケーションの下でjspによってコンパイルされたservletをロードするために使用されます.Webアプリケーションには、JREClassLoader|commonLoader/catalinaLoader sharedLoaderの親子エージェント関係があります. / \ webappClassLoader ........webappClassLoader | | JasperLoader JasperLoader 2.WebAppClassLoaderロードポリシー1.まずclassが既にロードするか否かを判断し、ロードされている場合はそのまま戻る、ロードされていない場合は第2ステップ2に進む.システムローダを使用してclassをロードし、ロードに成功すると戻り、失敗するとステップ3に進む.WebAppClassLoaderがプロキシモードを設定している場合は、親ローダでロードします.そうでない場合は直接4をロードする.WebAppClassLoaderがプロキシモードを設定していない場合は、自分でロードし、失敗した後に親ローダを使用してWebappClassLoaderクラスloadClassメソッドをロードします.
public Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
if (log.isDebugEnabled())
log.debug("loadClass(" + name + ", " + resolve + ")");
Class clazz = null;
// Log access to stopped classloader
if (!started) {
try {
throw new IllegalStateException();
} catch (IllegalStateException e) {
log.info(sm.getString("webappClassLoader.stopped", name), e);
}
}
// (0) Check our previously loaded local class cache
clazz = findLoadedClass0(name);
if (clazz != null) {
if (log.isDebugEnabled())
log.debug(" Returning class from cache");
if (resolve)
resolveClass(clazz);
return (clazz);
}
// (0.1) Check our previously loaded class cache
clazz = findLoadedClass(name);
if (clazz != null) {
if (log.isDebugEnabled())
log.debug(" Returning class from cache");
if (resolve)
resolveClass(clazz);
return (clazz);
}
// (0.2) Try loading the class with the system class loader, to prevent
// the webapp from overriding J2SE classes
try {
clazz = system.loadClass(name);
if (clazz != null) {
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
// Ignore
}
// (0.5) Permission to access this class when using a SecurityManager
if (securityManager != null) {
int i = name.lastIndexOf('.');
if (i >= 0) {
try {
securityManager.checkPackageAccess(name.substring(0,i));
} catch (SecurityException se) {
String error = "Security Violation, attempt to use " +
"Restricted Class: " + name;
log.info(error, se);
throw new ClassNotFoundException(error, se);
}
}
}
boolean delegateLoad = delegate || filter(name);
// (1) Delegate to our parent if requested
if (delegateLoad) {
if (log.isDebugEnabled())
log.debug(" Delegating to parent classloader1 " + parent);
ClassLoader loader = parent;
if (loader == null)
loader = system;
try {
clazz = loader.loadClass(name);
if (clazz != null) {
if (log.isDebugEnabled())
log.debug(" Loading class from parent");
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
}
// (2) Search local repositories
if (log.isDebugEnabled())
log.debug(" Searching local repositories");
try {
clazz = findClass(name);
if (clazz != null) {
if (log.isDebugEnabled())
log.debug(" Loading class from local repository");
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
// (3) Delegate to parent unconditionally
if (!delegateLoad) {
if (log.isDebugEnabled())
log.debug(" Delegating to parent classloader at end: " + parent);
ClassLoader loader = parent;
if (loader == null)
loader = system;
try {
clazz = loader.loadClass(name);
if (clazz != null) {
if (log.isDebugEnabled())
log.debug(" Loading class from parent");
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
}
throw new ClassNotFoundException(name);
}