tomcat7--container
来源:互联网 发布:美工绩效考核 编辑:程序博客网 时间:2024/04/28 18:25
tomcat 7 启动时 先 启动catalina ,利用 digester 工具包来解析server.xml 创建 server ;
server 包含 service
service 包含 container 和 Connector ;
container 的体系从高到低 依次为 engine > host >context>wrapper。
server 启动 service代码如下:
@Override protected void startInternal() throws LifecycleException { fireLifecycleEvent(CONFIGURE_START_EVENT, null); setState(LifecycleState.STARTING); globalNamingResources.start(); // Start our defined Services synchronized (services) { for (int i = 0; i < services.length; i++) { services[i].start(); } } }
(这里为什么要同步呢? 看起来启动server 是在main线程进行的。)
依次启动service ,service启动代码如下:
@Override protected void startInternal() throws LifecycleException { if(log.isInfoEnabled()) log.info(sm.getString("standardService.start.name", this.name)); setState(LifecycleState.STARTING); // Start our defined Container first if (container != null) { synchronized (container) { container.start(); } } synchronized (executors) { for (Executor executor: executors) { executor.start(); } } // Start our defined Connectors second synchronized (connectors) { for (Connector connector: connectors) { try { // If it has already failed, don't try and start it if (connector.getState() != LifecycleState.FAILED) { connector.start(); } } catch (Exception e) { log.error(sm.getString( "standardService.connector.startFailed", connector), e); } } } }
先启动的是container:
container 体系如下 :
container 容器有4中实现,级别从高到低为 engine >host >context >wapper。所有的 容器均继承 containerBase 。
containerbase 包含一个 pipeline 和 startStopExecutor 任务执行器 ;
每个容器调用containerbase 的方法启动,containerbase 启动代码如下:
// Start our child containers, if any Container children[] = findChildren(); List<Future<Void>> results = new ArrayList<Future<Void>>(); for (int i = 0; i < children.length; i++) { results.add(startStopExecutor.submit(new StartChild(children[i]))); }
results.add(startStopExecutor.submit(new StartChild(children[i])));
这里用到了 threadpoolExcuter 封装的线程池,封装成任务执行器;把每一个注册的子容器提交给一个任务执行器来启动
private static class StartChild implements Callable<Void> { private Container child; public StartChild(Container child) { this.child = child; } @Override public Void call() throws LifecycleException { child.start(); return null; } }每一个 startChild 线程启动一个container,这是递归调用的,子容器又会启动子容器,最底层的容器最先启动完成。
然后等待直到每一个子容器启动完成:
for (Future<Void> result : results) { try { result.get(); } catch (Exception e) { log.error(sm.getString("containerBase.threadedStartFailed"), e); fail = true; } }
子容器全部启动完成之后,启动 pipeline
// Start the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start();
containerbase 持有一个standardPipeline,pipeline 也持有自己所在容器的引用
/** * The Pipeline object with which this Container is associated. */ protected Pipeline pipeline = new StandardPipeline(this);
pipeline启动代码如下:pipeline会先启动server.xml自定义的Valve ,最后启动 basic Valve。
@Override protected synchronized void startInternal() throws LifecycleException { // Start the Valves in our pipeline (including the basic), if any Valve current = first; if (current == null) { current = basic; } while (current != null) { if (current instanceof Lifecycle) ((Lifecycle) current).start(); current = current.getNext(); } setState(LifecycleState.STARTING); }
basic Valve 是容器初始化时绑定给pipeline的:
standardEngine 的初始化代码如下:
/** * Create a new StandardEngine component with the default basic Valve. */ public StandardEngine() { super(); pipeline.setBasic(new StandardEngineValve()); /* Set the jmvRoute using the system property jvmRoute */ try { setJvmRoute(System.getProperty("jvmRoute")); } catch(Exception ex) { log.warn(sm.getString("standardEngine.jvmRouteFail")); } // By default, the engine will hold the reloading thread backgroundProcessorDelay = 10; }
可见,engine 容器的 pipeline绑定的 basic Valve 就是 StandardEngineValve 。
StandardEngineValve 就是一个实例,不包含任何别的组件了,因此Valve 的start() 只是设置一个启动状态,然后什么也不做。
当创建各级容器实例的时候,(创建容器实例在 Catalina 启动Server 之前就完成了。)
1. StandardHost 给子容器 context 绑定了一个监听器。
/** * Add a child Container, only if the proposed child is an implementation * of Context. * * @param child Child container to be added */ @Override public void addChild(Container child) { child.addLifecycleListener(new MemoryLeakTrackingListener()); if (!(child instanceof Context)) throw new IllegalArgumentException (sm.getString("standardHost.notContext")); super.addChild(child); }
这个监听器当context启动完成之后,把context 的 classLoader 绑定到host 。记录内存泄漏用。。(控制台用的。。)
2. Engine
在Catalina 创建默认的StandardEngine 时,同时也将自己的classLoader 传递给了 StandardEngine, 也就是CommonClassLoader。
3. Contetxt
当使用Digetser创建 Context 时, Context 会创建一个 WabAppLoader 的实例,这个loader 是支持热部署的。
当 Digester 实例化 Context 之后, 还会调用 Context 的 setLoader() 方法,这个方法里启动了WebAppLoader ,调用 它的StartInternal() 方法。
// Construct a class loader based on our current repositories list try { classLoader = createClassLoader(); 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]); } // Configure our repositories setRepositories(); setClassPath(); setPermissions(); ((Lifecycle) classLoader).start();
首先创建一个WebAppClassLoader ,这个才是 WebappLoader 这个组件持有的真正的类加载器。
这里那么它的父类加载器是谁呢? 想想上面提到的 Engine 容器的设置的 classLoader ,就是这个Catalina 传递的 CommomClassLoader了。
if (parentClassLoader == null) { parentClassLoader = container.getParentClassLoader(); }CommomClassLoader 加载所有Server 都能访问的类库
一个 WebappClassLoader 加载一个 webapp
server 是在main 线程运行的,service 也是在main 线程运行的,(待续)
- tomcat7--container
- tomcat7
- tomcat7
- tomcat7
- 部署工程到tomcat7,出现奇葩的错误:严重: A child container failed during start
- Container
- Container
- Container
- Container
- Container
- Container move to Container
- tomcat7配置
- Tomcat7 deployment
- tomcat7编译
- tomcat7.0
- tomcat7配置
- tomcat7+jndi
- tomcat7.0
- ios UIButton得 几种触发方式
- 五大常用算法之五:分支限界法
- 记录我的旅程
- 使用shc简单加密后的脚本文件恢复
- 寻找最大的k个数
- tomcat7--container
- 2亿个整数中求最大的100万之和
- Unity学习(十二): 平滑差值
- 2014年安徽省事业单位改革详细信息
- 爱立信软件+服务收入占67% CEO称转型到了关键点
- mysql创建单个和联合索引
- 常用intent列表 Android Intent 用法汇总
- PAT 1005. Spell It Right (20)
- A - 畅通工程(最小生成树)