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);
    }