Life cycle management initialization action for Tomcat series analysis

Source: Internet
Author: User

There are many components in Tomcat, and it is difficult to manage the lifecycle of these components by abstracting out a lifecycle management interface, and then all of the components implement that interface, and when the parent component starts, the colleague is responsible for starting and starting the entire Tomcat. , the end of the action.

Looking at the Tomcat boot process, first constructs the Bootstrap class, invokes the Init method in it, completes the class loader initialization, facilitates the later load class to use, and then calls the Load method, in fact the Tomcat real start action is by the Catalina class to complete. And the Load method that calls Catalina in Bootstrap is done by reflection, according to how Tomcat works, which is to understand the decoupling and can easily change the way it starts. The Catalina class inherits the embedded class, and embedded inherits the Standardservice class. The lifecycle interface is implemented as Standardservice or Containerbase (the base parent class for the container component). So that it can be easily and uniformly processed.

A reference to a server in Standardservice indicates that there is a service service under the server, and the standard server implementation is Standardserver:

Start the new server        //Get server here is a standard implementation of Standardservice        if (getserver () instanceof Lifecycle) {            try {// Return standardserver and call the Initialize Method                Getserver (). Initialize ();            } catch (Lifecycleexception e) {                if ( Boolean.getboolean ("Org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))                    throw new Java.lang.Error (e);                else                       log.error ("Catalina.start", e);                            }        }

You can see whether the implementation is lifecycle first, and if it is called the initialization method, look at the method:

public void Initialize ()        throws Lifecycleexception    {        if (initialized) {                log.info (sm.getstring (" StandardServer.initialize.initialized "));            return;        } Call Lifecycle's Firelifecycleevent method        lifecycle.firelifecycleevent (init_event, null);        initialized = True; ..... A server can have more than one service, which is initialized separately        //Initialize our defined Services for        (int i = 0; i < services.length; i++) {
   services[i].initialize ();        }    }

Lifecycle is a class that provides lifecycle management, which holds a reference to the lifecycle implementation class. It is necessary to take a look at this firelifecycleevent method, because the initialization action is all implemented here:

public void Firelifecycleevent (String type, Object data) {//Initialize session state if (Lifecycle.INIT_EVENT.equals (type)) {        State = "INITIALIZED";        } else if (Lifecycle.BEFORE_START_EVENT.equals (type)) {state = "starting_prep";        } else if (Lifecycle.START_EVENT.equals (type)) {state = "starting";        } else if (Lifecycle.AFTER_START_EVENT.equals (type)) {state = "STARTED";        } else if (Lifecycle.BEFORE_STOP_EVENT.equals (type)) {state = "stopping_prep";        } else if (Lifecycle.STOP_EVENT.equals (type)) {state = "stopping";        } else if (Lifecycle.AFTER_STOP_EVENT.equals (type)) {state = "STOPPED";        } else if (Lifecycle.DESTROY_EVENT.equals (type)) {state = "destroyed"; }//completes the generation of lifecycle events lifecycleevent event = new Lifecycleevent (lifecycle, type, data); Gets the lifecycle listener for this component Lifecyclelis        Tener interested[] = listeners; for (int i = 0; i < interested.length;    i++)//Pass the event, through the listener to complete the initialization action of the component Interested[i].lifecycleevent (event); }

This applies to the listener mode, receiving different events to complete the different actions. Different components hold a lifecyclesupport reference that, when the component is new, completes the addition of the corresponding event by this reference:

Public Standardserver () {        super ();        Serverfactory.setserver (this);        Globalnamingresources = new Namingresources ();        Globalnamingresources.setcontainer (this);        if (isusenaming ()) {            if (Namingcontextlistener = = null) {                Namingcontextlistener = new Namingcontextlistener (); C7/>addlifecyclelistener (Namingcontextlistener);}}}    

Add the corresponding listener, so as long as the corresponding call Lifecyclesupport Firelifecycleevent method, constructs a different event, the listener responds to different actions. In addition to constructing the method's initialization listener, it is possible to invoke addlifecyclelistener through the reflection mechanism to complete the listener's addition. For example, the following listeners in our config file server.xml are all injected dynamically by reflection, because we cannot get the listeners with which the user will be.

<listener classname= "Org.apache.catalina.core.AprLifecycleListener" sslengine= "on"/>
<!--Initialize Jasper prior to WebApps is loaded. Documentation At/docs/jasper-howto.html--
<listener classname= "Org.apache.catalina.core.JasperListener"/>
<!--Prevent memory leaks due to use of particular Java/javax apis-->
<listener classname= "Org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<!--JMX support for the TOMCAT server. Documentation At/docs/non-existent.html--
<listener classname= "Org.apache.catalina.mbeans.ServerLifecycleListener"/>
<listener classname= "Org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>

Specifically these listeners have done what initialization action, do not look, too many. When you have finished your initialization, call the subcomponents here is the service initialization method, we know that a service consists of a container and multiple connector, see Standardservice Source code is really like this, Take a look at the service initialization action:

public void Initialize () throws Lifecycleexception {//Service shouldn ' t is used with embeded, so it Doesn ' t matter if (initialized) {if (log.isinfoenabled ()) Log.info (sm.getstring ("Standar            DService.initialize.initialized "));        Return        } initialized = true; if (oname==null) {try {//hack-server should be deprecated...//get the container in service here is Engin                E (standardengine) Container Engine=this.getcontainer ();                Domain=engine.getname ();                Oname=new ObjectName (domain + ": type=service,servicename=" +name);                This.controller=oname;                                Registry.getregistry (null, NULL). RegisterComponent (this, oname, null);                executor[] executors = findexecutors ();                for (int i = 0; i < executors.length; i++) {ObjectName Executorobjectname =         New ObjectName (domain + ": type=executor,name=" + executors[i].getname ());                Registry.getregistry (null, NULL). RegisterComponent (Executors[i], executorobjectname, NULL); }} catch (Exception e) {log.error (sm.getstring ("Standardservice.regi            ster.failed ", domain), e);  }} if (Server==null) {//Register with the server//HACK:                        Serverfactory should be removed ...        Serverfactory.getserver (). AddService (this); }//Initialize our defined connectors//default Connector is connector[http/1.1-8080], connector[ajp/1.3-800    9] These two types of synchronized (connectors) {for (int i = 0; i < connectors.length; i++) {try {                Invokes the initialization action of the subassembly Connectors[i].initialize (); } catch (Exception e) {String message = SM.GEtstring ("standardService.connector.initFailed", Connectors[i]);                    Log.error (message, E); if (Boolean.getboolean ("Org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) throw new Lifecycleexce                ption (message); }            }        }    }

Note that when initializing, the service does not involve the initialization of the life cycle component, but simply does the necessary action by its own method, and then directly triggers the initialization of the connector.

public void Initialize ()        throws Lifecycleexception    {        this.initialized = true;        ......        Initializa adapter//initializes connector member variables adapter and Protocolhandler, which are described in the following two classes        adapter = new Coyoteadapter (this);        Protocolhandler.setadapter (adapter);        Make sure Parsebodymethodsset have a default        if (null = = Parsebodymethodsset)            setparsebodymethods ( Getparsebodymethods ());//Reflection Call, this reflection tool is worth a good study        of Introspectionutils.setproperty (Protocolhandler, "Jkhome",                                       system.getproperty ("Catalina.base"));        Initialization of try {    //subcomponents, Http11protocol and Jkcoyotehandler            protocolhandler.init ();        } catch (Exception e) {            throw new Lifecycleexception                (sm.getstring                 ("coyoteconnector.protocolhandlerinitializationfailed", e));    }

Focus on the Http11protocol init method, Http11protocol is only connector internal structure, and does not implement the lifecycle interface:

public void Init () throws Exception {//endpoint class, this class is Jioendpoin, is a very important class, with the implementation of bio and NIO, and later on Endpoint.setname        (GetName ());//chandle is also another very important class Http11connectionhandler, which is Http11protocol's inner class Endpoint.sethandler (CHandler); Verify the validity of the configured socket factory try {if (issslenabled ()) {SS Limplementation = Sslimplementation.getinstance (sslimplementationname);//Here we finally see a familiar concept, socket! is just a serv Ersocket Factory, it is obvious to produce serversocket socketfactory = Sslimplementation.getserversocketfactory ();//eh?                Here the factory address is told to endpoint, can be a bold guess, the creation of ServerSocket may be completed in endpoint.            Endpoint.setserversocketfactory (socketfactory); } else if (socketfactoryname! = null) {socketfactory = (serversocketfactory) class.forname (Socketfactoryna                Me). newinstance ();            Endpoint.setserversocketfactory (socketfactory); }} catch (Exception ex) {Log.error(Sm.getstring ("Http11protocol.socketfactory.initerror"), ex);        Throw ex;        }//But when debug, the above socketfactory is always null, do not know where socketfactoryname is obtained from.            if (socketfactory!=null) {iterator<string> atte = Attributes.keyset (). Iterator ();                while (Atte.hasnext ()) {String key = Atte.next ();                Object V=attributes.get (key);            Socketfactory.setattribute (key, V);        }}//endpoint Initialization action try {endpoint.init ();            } catch (Exception ex) {Log.error (sm.getstring ("Http11protocol.endpoint.initerror"), ex);        Throw ex;    } if (log.isinfoenabled ()) Log.info (sm.getstring ("Http11protocol.init", GetName ())); }

Step by step, we are about to find our familiar socket, first look at the Jioendpoint class, the class implements a simple server model, a listener thread is responsible for receiving the client socket, and create a worker thread for each connection to handle the socket, This is not actually a connection thread, but rather a wired pool to control. Look at the initialization method of the Jioendpoint class:

public void Init () throws Exception {//Here the initialization action, finally not so obscure, a lot of familiar concepts if (initialized) return;        Initialize thread count defaults for acceptor//initializes the number of acceptor, and the default is 1,acceptor is responsible for receiving connections from clients.        if (Acceptorthreadcount = = 0) {acceptorthreadcount = 1; }//Here we do not provide serversocketfactory, so use the default factory if (serversocketfactory = = null) {serversocketfactory = Serve        Rsocketfactory.getdefault (); if (ServerSocket = = null) {try {///is finally initialized ServerSocket, Port classic 8080,backlog is the maximum number of waiting queues for the connection Queue Server//A moment must be only Can handle a client connection, the remaining connections are all put in the waiting queue at the same time, if full, then the connection if (address = = null) {ServerSocket = Serversoc                Ketfactory.createsocket (port, backlog);                } else {serversocket = Serversocketfactory.createsocket (port, backlog, address);                }} catch (Bindexception orig) {String msg;           if (address = = NULL)         msg = Orig.getmessage () + "&LT;NULL&GT;:" + port;                else msg = orig.getmessage () + "" + address.tostring () + ":" + port;                Bindexception be = new Bindexception (msg);                Be.initcause (orig);            throw be;                }}//if (servertimeout >= 0)//serversocket.setsotimeout (servertimeout);            initialized = true; }

Finally here the initialization action is completed. Summarize the drawing of a flowchart:


This does not involve the container initialization of the service, yes container is not initialized, but the annoying point is that there is an Init method in the engine or context. And these methods are called at start. The START process is then analyzed in the next section.




Life cycle management initialization action for Tomcat series analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.