tomcat6出典研究:Tomcatのクラスローディング機構

まず、クラスローディング機構Java仮想マシンを見てください。
ブートストラップクラスローダ(読み込みJRE \ libに\ rt.jarのXbootclasspath指定されたJARまたはパケット用)
拡張クラスローダ(標準拡張ディレクトリをロードするための/ JDK / JRE / libに/ EXT)
(CLASSPATH環境変数またはDJava.class.path jarファイルとディレクトリをロードするための)システムクラスローダー
カスタムクラスローダ(ユーザ定義のクラスローダ)
両方の両親に準拠するクラスローダ委譲モデル、読み込みファイルが最初にその親ローダー負荷に委任されたときに、親ローダは成功、その後、ロードされています。親が負荷をダウンロードできない場合は、負荷へのサブローダーに委任されます。
Tomcatのサーブレットコンテナは、2つの理由のために、独自のクラスローダを定義します。
あなたはセキュリティ上の問題を解決することができるので、一方で我々は、それを止めることができますが、仮想マシンのクラスで別の実行をロードするために信頼することはできません。サーブレットコンテナが唯一のWEB-INF / classesディレクトリとそのサブディレクトリロードされたクラスの依存WEB-INF / libにヘッドをエンジニアリングすることができTOMCAT、このローダはインタフェースorg.apache.catalina.Loader.javaを実装する必要があります。

別の態様は、WEB-INF / classesまたはWEB-INF可能/変更は、Tomcatは、このようなローダ実装インタフェースorg.apache下の2つのファイルの変更を監視するスレッドを開始します場合は、以下のファイルが自動的にロードされlibに。 catalina.loader.Reloader.java。はい、あなたはクラスファイルを変更するローカルデバッグは、Tomcatを再起動することではありません

2つのソースファイルを次のように

パブリックインターフェイスローダ{

    // -------------------------------------------- -----------------プロパティ

    / **
     *などされるなど、この方法をリロードするよう、定期的なタスクを実行します
     *このコンテナのクラスローディングコンテキスト内で呼び出されました。予期しない
     *スロー可能オブジェクトがキャッチされ、ログに記録されます。
     * /
    パブリック無効のbackgroundProcess();
    / **
     *このコンテナが使用するJavaクラスローダを返します。
     * /
    パブリッククラスローダのgetClassLoader();
    / **
     *このLoaderは関連していたとのコンテナを返します。
     * /
    公共コンテナgetContainer();
    / **
     *このLoaderは関連していたとのコンテナを設定します。
     *
     * @paramコンテナ関連コンテナ
     * /
    公共ボイドsetContainer(コンテナ容器)
    / **
     *戻り設定するために使用される「標準委譲モデルに従う」フラグ
     *私たちのクラスローダ。
     * /
    パブリックブールによりgetDelegate();
    / **
     *構成するために使用される「標準委譲モデルに従う」フラグを設定し
     、当社のクラスローダ*。
     *
     * @paramデリゲート新しいフラグ
     * /
    パブリック無効setDelegate(ブールデリゲート)。
    / **
     このローダ実装と約*リターン記述情報
     の形式で*対応のバージョン番号、
     説明&GT; /&LT;バージョン&gt; </ code>の* <コード>&LT。
     * /
    パブリック文字列GETINFO();
    / **
     *このローダーのリロードフラグを返します。
     * /
    getReloadableブールパブリック();
    / **
     *このローダーのリロードフラグを設定します。
     *
     * @paramリロード新しいリロードフラグ
     * /
    パブリック無効setReloadable(ブールリロード可能)。
    // ------------------------------------------------ ---------パブリックメソッド
    / **
     *このコンポーネントにプロパティ変更リスナーを追加します。
     *
     追加する* @paramリスナーリスナー
     * /
    公共のボイドのaddPropertyChangeListener(PropertyChangeListenerをリスナー)。
    / **
     *このクラスローダのためのリポジトリのセットに新しいリポジトリを追加します。
     *
     * @paramリポジトリリポジトリ追加する
     * /
    公共ボイドaddRepository(文字列リポジトリ)。
    / **
     *このクラスローダのために定義されたリポジトリのセットを返します。
     何も定義されていない場合*、長さゼロの配列が返されます。
     * /
    パブリック文字列[] findRepositories()。
    / **
     *このローダーに関連する内部リポジトリは、変更されている
     ロードされたクラスを再ロードしなければならない*ように?
     * /
    パブリックブール)(変性;
    / **
     *このコンポーネントからプロパティ変更リスナーを削除します。
     *
     削除する* @paramリスナーリスナー
     * /
    パブリック無効removePropertyChangeListener(PropertyChangeListenerをリスナー)。
}

public interface Reloader {
    /**
     * Add a new repository to the set of places this ClassLoader can look for
     * classes to be loaded.
     *
     * @param repository Name of a source of classes to be loaded, such as a
     *  directory pathname, a JAR file pathname, or a ZIP file pathname
     *
     * @exception IllegalArgumentException if the specified repository is
     *  invalid or does not exist
     */
    public void addRepository(String repository);
    /**
     * Return a String array of the current repositories for this class
     * loader.  If there are no repositories, a zero-length array is
     * returned.
     */
    public String[] findRepositories();

    /**
     * Have one or more classes or resources been modified so that a reload
     * is appropriate?
     */
    public boolean modified();
}
tomcat类加载器的UML图如下
先来看看WebappLoader.java,它创建了一个WebappClassLoader的实例作为自己的类加载器。它实现了Loader.java接口,并且跟其他catalina组件一样,也实现了 org.apache.catalina.Lifecycle接口以便能被其他容器打开和关闭。同时也实现了java.beans.PropertyChangeListener接口,当属性改变时通知相关容器。而WebappLoader本身的重启是由Context(tomcat的容器)来控制的。
WebappLoader的启动的时候会发生下面几个工作:
如果没有初始化,则初始化并且注册容器;如果是第一次初始化,为JNDI注册流处理器;创建类加载器;设置repository;设置classpath;设置权限;为目录绑定类加载器。
public void start() throws LifecycleException {
        // Validate and update our current component state
        if( ! initialized ) init();
        if (started)
            throw new LifecycleException
                (sm.getString("webappLoader.alreadyStarted"));
        if (log.isDebugEnabled())
            log.debug(sm.getString("webappLoader.starting"));
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        if (container.getResources() == null) {
            log.info("No resources for " + container);
            return;
        }
        // Register a stream handler factory for the JNDI protocol
        URLStreamHandlerFactory streamHandlerFactory =
            new DirContextURLStreamHandlerFactory();
        if (first) {
            first = false;
            try {
                URL.setURLStreamHandlerFactory(streamHandlerFactory);
            } catch (Exception e) {
                // Log and continue anyway, this is not critical
                log.error("Error registering jndi stream handler", e);
            } catch (Throwable t) {
                // This is likely a dual registration
                log.info("Dual registration of jndi stream handler: " 
                         + t.getMessage());
            }
        }

        // Construct a class loader based on our current repositories list
        try {
            classLoader = createClassLoader();
            classLoader.setResources(container.getResources());
            classLoader.setDelegate(this.delegate);
            if (container instanceof StandardContext)
                classLoader.setAntiJARLocking(((StandardContext) container).getAntiJARLocking());

            for (int i = 0; i < repositories.length; i++) {
                classLoader.addRepository(repositories[i]);
            }

            // Configure our repositories
            setRepositories();
            setClassPath();
            setPermissions();

            if (classLoader instanceof Lifecycle)
                ((Lifecycle) classLoader).start();

            // Binding the Webapp class loader to the directory context
            DirContextURLStreamHandler.bind
                ((ClassLoader) classLoader, this.container.getResources());

            StandardContext ctx=(StandardContext)container;
            Engine eng=(Engine)ctx.getParent().getParent();
            String path = ctx.getPath();
            if (path.equals("")) {
                path = "/";
            }   
            ObjectName cloname = new ObjectName
                (ctx.getEngineName() + ":type=WebappClassLoader,path="
                 + path + ",host=" + ctx.getParent().getName());
            Registry.getRegistry(null, null)
                .registerComponent(classLoader, cloname, null);

        } catch (Throwable t) {
            log.error( "LifecycleException ", t );
            throw new LifecycleException("start: ", t);
        }
    }


发布了34 篇原创文章 · 获赞 2 · 访问量 4万+

おすすめ

転載: blog.csdn.net/zjj2006/article/details/17509447