tomcat7--container
2014-02-25 18:21
459 查看
tomcat 7 启动时 先 启动catalina ,利用 digester 工具包来解析server.xml 创建 server ;
server 包含 service
service 包含 container 和 Connector ;
container 的体系从高到低 依次为 engine > host >context>wrapper。
server 启动 service代码如下:
(这里为什么要同步呢? 看起来启动server 是在main线程进行的。)
依次启动service ,service启动代码如下:
先启动的是container:
container 体系如下 :
container 容器有4中实现,级别从高到低为 engine >host >context >wapper。所有的 容器均继承 containerBase 。
containerbase 包含一个 pipeline 和 startStopExecutor 任务执行器 ;
每个容器调用containerbase 的方法启动,containerbase 启动代码如下:
results.add(startStopExecutor.submit(new StartChild(children[i])));
这里用到了 threadpoolExcuter 封装的线程池,封装成任务执行器;把每一个注册的子容器提交给一个任务执行器来启动
然后等待直到每一个子容器启动完成:
子容器全部启动完成之后,启动 pipeline
containerbase 持有一个standardPipeline,pipeline 也持有自己所在容器的引用
pipeline启动代码如下:pipeline会先启动server.xml自定义的Valve ,最后启动 basic Valve。
basic Valve 是容器初始化时绑定给pipeline的:
standardEngine 的初始化代码如下:
可见,engine 容器的 pipeline绑定的 basic Valve 就是 StandardEngineValve 。
StandardEngineValve 就是一个实例,不包含任何别的组件了,因此Valve 的start() 只是设置一个启动状态,然后什么也不做。
当创建各级容器实例的时候,(创建容器实例在 Catalina 启动Server 之前就完成了。)
1. StandardHost 给子容器 context 绑定了一个监听器。
这个监听器当context启动完成之后,把context 的 classLoader 绑定到host 。记录内存泄漏用。。(控制台用的。。)
2. Engine
在Catalina 创建默认的StandardEngine 时,同时也将自己的classLoader 传递给了 StandardEngine, 也就是CommonClassLoader。
3. Contetxt
当使用Digetser创建 Context 时, Context 会创建一个 WabAppLoader 的实例,这个loader 是支持热部署的。
当 Digester 实例化 Context 之后, 还会调用 Context 的 setLoader() 方法,这个方法里启动了WebAppLoader ,调用 它的StartInternal() 方法。
首先创建一个WebAppClassLoader ,这个才是 WebappLoader 这个组件持有的真正的类加载器。
这里那么它的父类加载器是谁呢? 想想上面提到的 Engine 容器的设置的 classLoader ,就是这个Catalina 传递的 CommomClassLoader了。
一个 WebappClassLoader 加载一个 webapp
server 是在main 线程运行的,service 也是在main 线程运行的,(待续)
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 线程运行的,(待续)
相关文章推荐
- tomcat 安全设置
- tomcat安全设置
- tomcat中的程序部署到weblogic10.3.6
- 在Eclipse中运行Tomcat6源代码,保证正确的classpath
- Tomcat安装配置
- Apache+Tomcat集群之环境搭建 .
- 高并发Tomcat7.0配置
- 双tomcat的部署
- Tomcat启动时一闪而过,看不多错误信息
- tomcat 配置细节
- tomcat环境变量的配置
- [转载]Cool, Tomcat is able to handle more than 13,000 concurrent connections
- Ubuntu 12.10 安装Tomcat 7
- 如何修改tomcat的默认端口
- ecliper for javaee +tomcat 环境搭建与 helloworld实现
- Enable JMX on tomcat and debug with eclipse(linux)
- MyEclipse Tomcat插件内存配置 + JAVA内存配置
- tomcat7+mysql5.5+jdk1.7环境搭建
- Tomcat7.0下安装Solr4.6.1
- eclipse中安装tomcat插件