通过tomcat源码查看其如何实现应用相互隔离

前言

tomcat之所以创造了一堆自己的classloader体系,其目的之一就是为了实现应用的相互隔离,而对于许多应用,需要有共享的lib以便不浪费资源。那么,tomcat是如何实现这些功能的呢?通过tomcat源码,我会为大家详细介绍

tomcat的classloader体系

tomcat的具体的classloader体系如下图

这里写图片描述

BootstrapClassLoader,ExtensionClassLoader,SystemClassLoader这三个类我就不多介绍了,具体可参考我的《tomcat类加载体系》这篇博客

从Bootstrap的init开始

commonLoader、catalinaLoader和sharedLoader是在Tomcat容器初始化的的过程刚刚开始(即调用Bootstrap的init方法时)创建的。catalinaLoader会被设置为Tomcat主线程的线程上下文类加载器,并且使用catalinaLoader加载Tomcat容器自身的class。Bootstrap的init方法代码如代码清单1:

                            代码清单1
/**
     * Initialize daemon.
     */


     public void init()
        throws Exception
    {

        // Set Catalina path
        setCatalinaHome();
        setCatalinaBase();
        //初始化commonLoader、catalinaLoader和sharedLoader;
        initClassLoaders();
        //将catalinaLoader设置为Tomcat主线程的线程上下文类加载器;
        Thread.currentThread().setContextClassLoader(catalinaLoader);
        //线程安全的加载class。 
        SecurityClassLoad.securityClassLoad(catalinaLoader);

        // Load our startup class and call its process() method
        if (log.isDebugEnabled())
            log.debug("Loading startup class");
        Class<?> startupClass =
            catalinaLoader.loadClass
            ("org.apache.catalina.startup.Catalina");
        Object startupInstance = startupClass.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;

    }

其中有关类加载器的执行步骤如下:

  1. 初始化commonLoader、catalinaLoader和sharedLoader;
  2. 将catalinaLoader设置为Tomcat主线程的线程上下文类加载器;
  3. 线程安全的加载class。

再之后就是加载Catalina,设置catalinaDaemon参数

初始化类加载器initClassLoaders()

initClassLoaders方法的实现如代码清单2:

                            代码清单2
    private void initClassLoaders() {
        try {
            commonLoader = createClassLoader("common", null);
            if( commonLoader == null ) {
//no config file, default to thisloader- we might be in a 'single' env.
                commonLoader=this.getClass().getClassLoader();
            }
            catalinaLoader = createClassLoader("server", commonLoader);
            sharedLoader = createClassLoader("shared", commonLoader);
        } catch (Throwable t) {
            log.error("Class loader creation threw exception", t);
            System.exit(1);
        }
    }

我们可以看到initClassLoaders调用createClassLoader方法来创建commonLoader、catalinaLoader和sharedLoader,我们来看看createClassLoader的实现,其代码清单3:

                            代码清单3
    private ClassLoader createClassLoader(String name, ClassLoader parent)
        throws Exception {

        String value = CatalinaProperties.getProperty(name + ".loader");
        if ((value == null) || (value.equals("")))
            return parent;

        ArrayList<String> repositoryLocations = new ArrayList<String>();
        ArrayList<Integer> repositoryTypes = new ArrayList<Integer>();
        int i;

        StringTokenizer tokenizer = new StringTokenizer(value, ",");
        while (tokenizer.hasMoreElements()) {
            String repository = tokenizer.nextToken();

            // Local repository
            boolean replace = false;
            String before = repository;
            while ((i=repository.indexOf(CATALINA_HOME_TOKEN))>=0) {
                replace=true;
                if (i>0) {
                repository = repository.substring(0,i) + getCatalinaHome()
                    + repository.substring(i+CATALINA_HOME_TOKEN.length());
                
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值