• 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 类加载器设置进去

  • 相关阅读:
    cinder-volume报错vmdk2 is reporting problems, not sending heartbeat. Service will appear "down".
    Linux下截取指定时间段日志并输出到指定文件
    使用diff或者vimdiff比较远程文件(夹)与本地文件夹
    OpenStack视图
    awk 计算某一列的和
    opencontrail—VXLAN模式下数据包的传输过程
    shell-计算虚拟机创建时间
    gnocchi resource批量删除
    openflow控制器和交换机之间的消息
    openflow packet_out和packet_in分析
  • 原文地址:https://www.cnblogs.com/elvinle/p/13523257.html
Copyright © 2020-2023  润新知