Tomcat源码走读 03-tomcat的类加载器

03-tomcat的类加载器

tomcat类加载器结构图:
在这里插入图片描述
1)bootstrap ClassLoader:它用来加载 Java 的核心类,是用原生代码来实现的,并不继承自 java.lang.ClassLoader,负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类。

2)extension ClassLoader:它负责加载JRE的扩展目录,lib/ext或者由java.ext.dirs系统属性指定的目录中的JAR包的类。由Java语言实现,父类加载器为null。

3)application ClassLoader:它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。

4)common ClassLoader:Tomcat最基本的类加载器,加载路径中的class可以被Tomcat容器本身以及各个Webapp访问,位于 c a t a l i n a . b a s e / l i b , {catalina.base}/lib, catalina.base/lib,{catalina.base}/lib/.jar, c a t a l i n a . h o m e / l i b , {catalina.home}/lib, catalina.home/lib,{catalina.home}/lib/.jar

5)catalina ClassLoader:Tomcat容器私有的类加载器,加载路径中的class对于Webapp不可见。

6)shared ClassLoader: 各个Webapp共享的类加载器,加载路径中的class对于所有Webapp可见,但是对于Tomcat容器不可见

7)webapp ClassLoader: 各个Webapp私有的类加载器,加载路径中的class只对当前Webapp可见,从而保证各个web应用之间相互隔离。

8)jsp ClassLoader: 而JasperLoader的加载范围仅仅是这个JSP文件所编译出来的那一个.Class文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替换掉目前的
JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的HotSwap功能。

加载器初始化逻辑位于bootstrap.init()

1. initClassLoaders()

private void initClassLoaders() {
            commonLoader = createClassLoader("common", null);
            if( commonLoader == null ) {
                commonLoader=this.getClass().getClassLoader();
            }
            catalinaLoader = createClassLoader("server", commonLoader);
            sharedLoader = createClassLoader("shared", commonLoader);
    }

这里面初始化了commonLoader, catalinaLoader, sharedLoader,分别从catalina.properties中读取common.loader, server.loader, shared.loader配置获取各自的类加载路径:
/*
common.loader= c a t a l i n a . b a s e / l i b , {catalina.base}/lib, catalina.base/lib,{catalina.base}/lib/.jar, c a t a l i n a . h o m e / l i b , {catalina.home}/lib, catalina.home/lib,{catalina.home}/lib/.jar
server.loader=
shared.loader=
*/
同时从上面的代码可以知道catalinaLoader和sharedLoader的父加载器为commonLoader。

2. Thread.currentThread().setContextClassLoader(catalinaLoader); 设置当前线程上下文环境classLoader为catalinaLoader。

3. SecurityClassLoad.securityClassLoad(catalinaLoader); catalinaLoader加载需要的类。

public static void securityClassLoad(ClassLoader loader)
        throws Exception {
        loadCorePackage(loader);
        loadCoyotePackage(loader);
        loadLoaderPackage(loader);
        loadRealmPackage(loader);
        loadSessionPackage(loader);
        loadUtilPackage(loader);
        loadValvesPackage(loader);
        loadJavaxPackage(loader);
        loadConnectorPackage(loader);
        loadTomcatPackage(loader);
    }

4. 通过反射设置Catalina.java的父加载器为sharedLoader

5. webappLoader的创建在StandardContext的startInternal()中。

if (getLoader() == null) {
            WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
            webappLoader.setDelegate(getDelegate());
            setLoader(webappLoader); //设置当前Context的loader
 }
if ((loader != null) && (loader instanceof Lifecycle))
                    ((Lifecycle) loader).start(); //调用当前Context的loader.start()

01-tomcat架构简介中介绍过一个Context就是一个web应用上下文,所以这里就是在给当前应用设置classLoader。

6. 在((Lifecycle) loader).start()中调用WebappLoader.startInternal()来使用webloader加载web应用路径的资源。

protected void startInternal() throws LifecycleException {
        URLStreamHandlerFactory streamHandlerFactory =
                DirContextURLStreamHandlerFactory.getInstance();
        try {
            classLoader = createClassLoader(); //创建webappClassLoader对象
            classLoader.setResources(container.getResources()); //设置资源
            classLoader.setDelegate(this.delegate);
            classLoader.setSearchExternalFirst(searchExternalFirst);
            if (container instanceof StandardContext) {
                classLoader.setAntiJARLocking(
                        ((StandardContext) container).getAntiJARLocking());
                classLoader.setClearReferencesStatic(
                        ((StandardContext) container).getClearReferencesStatic());
                classLoader.setClearReferencesStopThreads(
                        ((StandardContext) container).getClearReferencesStopThreads());
                classLoader.setClearReferencesStopTimerThreads(
                        ((StandardContext) container).getClearReferencesStopTimerThreads());
                classLoader.setClearReferencesHttpClientKeepAliveThread(
                        ((StandardContext) container).getClearReferencesHttpClientKeepAliveThread());
            }
            for (int i = 0; i < repositories.length; i++) {
                classLoader.addRepository(repositories[i]);
            }
            setRepositories(); //加载资源里面的类,jar等
            setClassPath(); //设置classpath属性到servletcontext中
            setPermissions(); //设置权限
            ((Lifecycle) classLoader).start();
            DirContextURLStreamHandler.bind(classLoader,
                    this.container.getResources());
            StandardContext ctx=(StandardContext)container;
            String contextName = ctx.getName();
            if (!contextName.startsWith("/")) {
                contextName = "/" + contextName;
            }
            ObjectName cloname = new ObjectName
                (MBeanUtils.getDomain(ctx) + ":type=WebappClassLoader,context="
                 + contextName + ",host=" + ctx.getParent().getName());
            Registry.getRegistry(null, null)
                .registerComponent(classLoader, cloname, null);
        } catch (Throwable t) {
        }
        setState(LifecycleState.STARTING);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值