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 线程运行的,(待续)








0 0
原创粉丝点击