原创

浅析tomcat7类加载机制及初始化流程

文章背景,之前看springmvc源码,虽然了解了servlet的执行过程,但是对于servlet的出处却不知道,不清楚jsp是怎么初始化的,只能下载tomcat源码看看,并未买书系统学习,所以不会太深

一、Tomcat类加载机制

1.tomcat类加载机制设计图

 

commonLoader:Tomcat最基本的类加载器,加载路径中的class可以被Tomcat容器本身以及各个Webapp访问;

catalinaLoader:Tomcat容器私有的类加载器,加载路径中的class对于Webapp不可见;

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

WebappClassLoader:各个Webapp私有的类加载器,加载路径中的class只对当前Webapp可见;

2.传统双亲委派模型类加载顺序

 

3.如果parent需要加载子类怎么实现

场景:如果十个web应用都引入了spring的类,由于web类加载器的隔离,那么对内存的开销是很大的。此时我们可以想到shared类加载器,我们肯定都会选择将spring的jar放于shared目录底下,但是此时又会存在一个问题,shared类加载器是webapp类加载器的parent,若spring中的getBean方法需要加载web应用底下的类,这种过程是违反双亲委托机制的。

方案:线程上下文类加载器是指的当前线程所用的类加载器,可以通过Thread.currentThread().getContextClassLoader()获得或者设置,在spring中,他会选择线程上下文类加载器去加载web应用底下的类,在web.xml中定义的listener为org.springframework.web.context.ContextLoaderListener,它最终调用了org.springframework.web.context.ContextLoader类来装载bean,代码如下

this.contextLoader.initWebApplicationContext(event.getServletContext());

//下面逻辑判断类加载器是否相同,不同则赋值

ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
}else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}

4.tomcat7各个加载器分别加载的文件

具体可查看catalina.properties的配置

common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jarcatalinaLoader:$CATALINA_BASE/bin

sharedLoader:可以自行配置

webappClassLoader:

web application下的/WEB_INF/classes 

web application下的/WEB_INF/lib/*.jar

二、初始化过程

1.启动类:Bootstrap.main()

2.项目运行时加载静态方法

CatalinaProperties.loadProperties();加载conf/catalina.properties文件,放入到System.setProperty();

3.Bootstrap.initClassLoaders()类加载

3.1 读取catalina.properties中属性:common.loader,将属性指定的的tomcat/lib目录下的所有jar包全路径加载到

ClassLoader commonLoader = createClassLoader(“common”, null);

3.2 读取catalina.properties中属性:server.loader,如果没配置,则返回ClassLoader catalinaLoader=commonLoader;

3.3 读取catalina.properties中属性:shared.loader,如果没配置,则返回ClassLoader sharedLoader=commonLoader;

4.Catalina.load()容器初始化

4.1 Digester digester = createStartDigester();设定service.xml解析规则;

digester.parse(inputSource);将servive.xml文件解析成java对象;

4.2 容器初始化

getServer().init();–》

LifecycleBase.init()–》

StandardServer.initInternal()–》

services[i].init();–》

LifecycleBase.init()–》

StandardService.initInternal()–》

引擎初始化:engine.init();–》

LifecycleBase.init()–》

StandardEngine.initInternal()

端口监听初始化:connector.init();–》

LifecycleBase.init()–》

Connector.initInternal()–》

protocolHandler.init(); --》

endpoint.init();–》

AbstractJsseEndpoint.init()–》

AbstractEndpoint.init()–》

NioEndpoint.bind();

4.3时序图参考


5.nio模型,参考博客

https://www.jianshu.com/p/76ff17bc6dea

 

 

 

 

 

 

 

正文到此结束