tomcat初始化过程

本文详细介绍了Tomcat的初始化过程,从main方法开始,包括启动类的守护线程化,参数加载,再到init方法中类加载器的初始化,尤其是类加载器的层级结构,如common、server和shared的设置。此外,还提到了上下文类加载器的设定,以及如何利用反射机制调整类加载器的父类关系。
摘要由CSDN通过智能技术生成

tomcat初始化过程

main方法

public static void main(String[] args) {
    synchronized(daemonLock) {
        if (daemon == null) {
            Bootstrap bootstrap = new Bootstrap();

            try {
                bootstrap.init();
            } catch (Throwable var5) {
                handleThrowable(var5);
                var5.printStackTrace();
                return;
            }

            daemon = bootstrap;
        } else {
            Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
        }
    }

    try {
        String command = "start";
        if (args.length > 0) {
            command = args[args.length - 1];
        }

        if (command.equals("startd")) {
            args[args.length - 1] = "start";
            daemon.load(args);
            daemon.start();
        } else if (command.equals("stopd")) {
            args[args.length - 1] = "stop";
            daemon.stop();
        } else if (command.equals("start")) {
            daemon.setAwait(true);
            daemon.load(args);
            daemon.start();
            if (null == daemon.getServer()) {
                System.exit(1);
            }
        } else if (command.equals("stop")) {
            daemon.stopServer(args);
        } else if (command.equals("configtest")) {
            daemon.load(args);
            if (null == daemon.getServer()) {
                System.exit(1);
            }

            System.exit(0);
        } else {
            log.warn("Bootstrap: command \"" + command + "\" does not exist.");
        }
    } catch (Throwable var7) {
        Throwable t = var7;
        if (var7 instanceof InvocationTargetException && var7.getCause() != null) {
            t = var7.getCause();
        }

        handleThrowable(t);
        t.printStackTrace();
        System.exit(1);
    }

}

初始化启动类,将启动类变成守护线程,根据参数的 方法名称进行加载参数并调用方法。

init方法

public void init() throws Exception {
    this.initClassLoaders();
    Thread.currentThread().setContextClassLoader(this.catalinaLoader);
    SecurityClassLoad.securityClassLoad(this.catalinaLoader);
    if (log.isDebugEnabled()) {
        log.debug("Loading startup class");
    }

    Class<?> startupClass = this.catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
    Object startupInstance = startupClass.getConstructor().newInstance();
    if (log.isDebugEnabled()) {
        log.debug("Setting startup class properties");
    }

    String methodName = "setParentClassLoader";
    Class<?>[] paramTypes = new Class[]{Class.forName("java.lang.ClassLoader")};
    Object[] paramValues = new Object[]{this.sharedLoader};
    Method method = startupInstance.getClass().getMethod(methodName, paramTypes);
    method.invoke(startupInstance, paramValues);
    this.catalinaDaemon = startupInstance;
}

初始化类加载器

private void initClassLoaders() {
    try {
        this.commonLoader = this.createClassLoader("common", (ClassLoader)null);
        if (this.commonLoader == null) {
            this.commonLoader = this.getClass().getClassLoader();
        }

        this.catalinaLoader = this.createClassLoader("server", this.commonLoader);
        this.sharedLoader = this.createClassLoader("shared", this.commonLoader);
    } catch (Throwable var2) {
        handleThrowable(var2);
        log.error("Class loader creation threw exception", var2);
        System.exit(1);
    }

}

init方法调用initClassLoaders方法。我们可以看到该类的类加载器是common,默认的父类加载器是应用类加载器,且server,shared类的父类加载器是common类加载器。

private ClassLoader createClassLoader(String name, ClassLoader parent) throws Exception {
    // 从根目录下的conf/catalina.properties文件中找到 name.loader 对应的value,这个value就是每个加载器需要加载的所有jar包路径。
    // 其中只有commonLoader类加载器会加载tomcat所依赖的jar包,其他两个不会加载。
    String value = CatalinaProperties.getProperty(name + ".loader");
    if (value != null && !value.equals("")) {
        value = this.replace(value);
        List<Repository> repositories = new ArrayList();
        String[] repositoryPaths = getPaths(value);
        String[] arr$ = repositoryPaths;
        int len$ = repositoryPaths.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            String repository = arr$[i$];

            try {
                new URL(repository);
                repositories.add(new Repository(repository, RepositoryType.URL));
            } catch (MalformedURLException var11) {
                if (repository.endsWith("*.jar")) {
                    repository = repository.substring(0, repository.length() - "*.jar".length());
                    repositories.add(new Repository(repository, RepositoryType.GLOB));
                } else if (repository.endsWith(".jar")) {
                    repositories.add(new Repository(repository, RepositoryType.JAR));
                } else {
                    repositories.add(new Repository(repository, RepositoryType.DIR));
                }
            }
        }

        return ClassLoaderFactory.createClassLoader(repositories, parent);
    } else {
        return parent;
    }
}
Thread.currentThread().setContextClassLoader(this.catalinaLoader);
SecurityClassLoad.securityClassLoad(this.catalinaLoader);

设置上下文类加载器。

Class<?> startupClass = this.catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.getConstructor().newInstance();

使用catalinaLoader来加载tomcat容器自身的class,并生成catalina的实例。

String methodName = "setParentClassLoader";
Class<?>[] paramTypes = new Class[]{Class.forName("java.lang.ClassLoader")};
Object[] paramValues = new Object[]{this.sharedLoader};
Method method = startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);
this.catalinaDaemon = startupInstance;

通过反射机制使实例去调用shareLoader的setParentClassLoader方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值