tomcat8.5.57源码阅读笔记2

代码片段:

org.apache.catalina.startup.Bootstrap#main()

if (daemon == null) {
    // Don't set daemon until init() has completed
    Bootstrap bootstrap = new Bootstrap();
    try {
        bootstrap.init();
    } catch (Throwable t) {
        handleThrowable(t);
        t.printStackTrace();
        return;
    }
    // 赋值给守护变量
    daemon = bootstrap;
}

Bootstrap static {}

Bootstrap有一个静态代码块, 用来获取tomcat的工作目录和安装目录.

默认情况下, 是工作目录和安装目录是相同的, 也可以配置成不同的.

// 这里有一个静态代码块
static {
    // Will always be non-null
    // 获取用户目录
    String userDir = System.getProperty("user.dir");

    // Home first
    // tomcat的安装目录
    String home = System.getProperty(Constants.CATALINA_HOME_PROP);

    File homeFile = null;

    if (home != null) {
        File f = new File(home);
        try {
            homeFile = f.getCanonicalFile();
        } catch (IOException ioe) {
            homeFile = f.getAbsoluteFile();
        }
    }

    if (homeFile == null) {
        // First fall-back. See if current directory is a bin directory
        // in a normal Tomcat install
        File bootstrapJar = new File(userDir, "bootstrap.jar");

        if (bootstrapJar.exists()) {
            File f = new File(userDir, "..");
            try {
                homeFile = f.getCanonicalFile();
            } catch (IOException ioe) {
                homeFile = f.getAbsoluteFile();
            }
        }
    }

    if (homeFile == null) {
        // Second fall-back. Use current directory
        File f = new File(userDir);
        try {
            homeFile = f.getCanonicalFile();
        } catch (IOException ioe) {
            homeFile = f.getAbsoluteFile();
        }
    }

    catalinaHomeFile = homeFile;
    System.setProperty(Constants.CATALINA_HOME_PROP, catalinaHomeFile.getPath());

    // Then base
    String base = System.getProperty(Constants.CATALINA_BASE_PROP);
    if (base == null) {
        // 一般情况下, 工作目录 = 安装目录
        catalinaBaseFile = catalinaHomeFile;
    } else {
        File baseFile = new File(base);
        try {
            baseFile = baseFile.getCanonicalFile();
        } catch (IOException ioe) {
            baseFile = baseFile.getAbsoluteFile();
        }
        catalinaBaseFile = baseFile;
    }
    System.setProperty(Constants.CATALINA_BASE_PROP, catalinaBaseFile.getPath());
}

bootstrap.init()

public void init() throws Exception {

    // 创建了三个自己的类加载器
    // commonLoader catalinaLoader sharedLoader
    initClassLoaders();

    Thread.currentThread().setContextClassLoader(catalinaLoader);

    SecurityClassLoad.securityClassLoad(catalinaLoader);

    // Load our startup class and call its process() method
    if (log.isDebugEnabled())
        log.debug("Loading startup class");

    // 反射加载类: Catalina
    Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
    // 反射创建 Catalina
    Object startupInstance = startupClass.getConstructor().newInstance();

    // Set the shared extensions class loader
    if (log.isDebugEnabled())
        log.debug("Setting startup class properties");

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

    // 调用 Catalina#setParentClassLoader(sharedLoader), 设置属性
    // Catalina.parentClassLoader
    method.invoke(startupInstance, paramValues);

    catalinaDaemon = startupInstance;
}

initClassLoaders

/**
 * 创建了三个自己的类加载器 commonLoader catalinaLoader sharedLoader
 */
private void initClassLoaders() {
    try {
        commonLoader = createClassLoader("common", null);
        if (commonLoader == null) {
            // no config file, default to this loader - we might be in a 'single' env.
            commonLoader = this.getClass().getClassLoader();
        }
        catalinaLoader = createClassLoader("server", commonLoader);
        // 给 webapp 用
        sharedLoader = createClassLoader("shared", commonLoader);
    } catch (Throwable t) {
        handleThrowable(t);
        log.error("Class loader creation threw exception", t);
        System.exit(1);
    }
}

创建的三个类加载器并不是三个独立的类加载器, 其结构关系为:

setParentClassLoader

//org.apache.catalina.startup.Catalina#setParentClassLoader
public void setParentClassLoader(ClassLoader parentClassLoader) {
    this.parentClassLoader = parentClassLoader;
}

tomcat 初始化时, 代码逻辑还是比较简单的.

主要干了两件事:

1. 调用 initClassLoaders() , 创建了三个自己的类加载器

2. 反射创建了 Catalina 类, 并调用了其 setParentClassLoader() 方法, 将 sharedLoader 类加载器设置进去

原文地址:https://www.cnblogs.com/elvinle/p/13523257.html