Tomcat源码分析(二)Bootstrap启动类分析

2022/4/19 14:12:35

本文主要是介绍Tomcat源码分析(二)Bootstrap启动类分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录
  • 静态代码块
  • main()方法
  • init()方法
    • initClassLoaders()方法
  • load()方法
  • start()方法

上一章,我们下载源码,并启动了源码,Tomcat源码分析(一)启动Tomcat源码 。
现在,我们来看看Bootstrap启动类做了些什么工作。

静态代码块

设置了catelina.home和catalina.base
点击查看代码
static {
    // Will always be non-null
    // 当前工作目录的路径,总是不会为null
    String userDir = System.getProperty("user.dir");

    // Home first
    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;
    // 设置了catelina.home
    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;
    }
    // 设置了catalina.base
    System.setProperty(Constants.CATALINA_BASE_PROP, catalinaBaseFile.getPath());
}

main()方法

1.加锁新建一个Bootstrap对象,调用init初始化并且赋值给了私有静态对象daemon
2.调用了daemon对象load和start方法,而load和start方法里面利用了反射调用了catalinaDeamon的load和start方法
点击查看代码
/**
 * Main method and entry point when starting Tomcat via the provided
 * scripts.
 *
 * @param args Command line arguments to be processed
 */
public static void main(String args[]) {

    synchronized (daemonLock) {
        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;
        } else {
            // When running as a service the call to stop will be on a new
            // thread so make sure the correct class loader is used to
            // prevent a range of class not found exceptions.
            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 t) {
        // Unwrap the Exception for clearer error reporting
        if (t instanceof InvocationTargetException &&
                t.getCause() != null) {
            t = t.getCause();
        }
        handleThrowable(t);
        t.printStackTrace();
        System.exit(1);
    }
}

init()方法

1.使用initClassLoaders()创建了commonLoader、catalinaLoader和sharedLoader
2.利用反射新建一个org.apache.catalina.startup.Catalina类对象,赋值给了catalinaDeamon。
点击查看代码
/**
 * Initialize daemon.
 * @throws Exception Fatal initialization error
 */
public void init() throws Exception {

    initClassLoaders();

    Thread.currentThread().setContextClassLoader(catalinaLoader);

    SecurityClassLoad.securityClassLoad(catalinaLoader);
    
    
    // Load our startup class and call its process() method
    // 加载启动类并调用其process()方法 
    if (log.isDebugEnabled()) {
        log.debug("Loading startup class");
    }
    Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.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);
    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);
        sharedLoader = createClassLoader("shared", commonLoader);
    } catch (Throwable t) {
        handleThrowable(t);
        log.error("Class loader creation threw exception", t);
        System.exit(1);
    }
}

load()方法

通过反射调用catalinaDaemon的load()方法
点击查看代码
/**
 * Load daemon.
 */
private void load(String[] arguments) throws Exception {

    // Call the load() method
    String methodName = "load";
    Object param[];
    Class<?> paramTypes[];
    if (arguments==null || arguments.length==0) {
        paramTypes = null;
        param = null;
    } else {
        paramTypes = new Class[1];
        paramTypes[0] = arguments.getClass();
        param = new Object[1];
        param[0] = arguments;
    }
    Method method =
        catalinaDaemon.getClass().getMethod(methodName, paramTypes);
    if (log.isDebugEnabled()) {
        log.debug("Calling startup class " + method);
    }
    method.invoke(catalinaDaemon, param);
}

start()方法

 通过反射调用catalinaDaemon的start()方法
点击查看代码
 /**
 * Start the Catalina daemon.
 * @throws Exception Fatal start error
 */
public void start() throws Exception {
    if (catalinaDaemon == null) {
        init();
    }

    Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
    method.invoke(catalinaDaemon, (Object [])null);
}


这篇关于Tomcat源码分析(二)Bootstrap启动类分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程