Tomcat starts from the main method of Bootstrap. In the main method, three things are mainly done. You can call the init method to initialize yourself and call the catalinadaemon object.
The setawait method of sets its await attribute to true, and finally calls its own start method.
First look at the init method:
Public void Init () throws exception {// set Catalina path setcatalinahome (); setcatalinabase (); // initialize three class loaders initclassloaders (); thread. currentthread (). setcontextclassloader (catalinaloader); // load Catalina. common. loader and server. the class specified by loader. When server. loader is empty, // catalinaloader and commonloader point to the same object. If not empty, commonloader is the parent class of catalinaloader. Securityclassload. securityclassload (catalinaloader); // load our startup class and call its process () method if (log. isdebugenabled () log. debug ("loading startup class"); Class <?> Startupclass = catalinaloader. loadclass ("org. apache. catalina. startup. catalina "); object startupinstance = startupclass. newinstance (); // set the shared extensions Class Loader if (log. isdebugenabled () log. debug ("setting startup class properties"); string methodname = "setparentclassloader"; Class <?> Paramtypes [] = new class [1]; paramtypes [0] = Class. forname ("Java. lang. classloader "); object paramvalues [] = new object [1]; paramvalues [0] = sharedloader; Method method = startupinstance. getclass (). getmethod (methodname, paramtypes); method. invoke (startupinstance, paramvalues); catalinadaemon = startupinstance ;}
The main content here is to call initclassloaders (); initialize three class loaders: commonloader, catalinaloader, and sharedloader, which are bootstrap
Member variable. Use the securityclassload. securityclassload (catalinaloader) code to load the common. loader in the conf/Catalina. properties file,
Server. loader, shared. loade three attributes specify the jar package and class. Securityclassload finds and loads related classes by replacing a series of environment variables.
The last code initializes the Catalina object and sets its parent loader as sharedloader. Some questions here will be discussed later.
Let's take a look at the initclassloaders () method:
Initclassloaders source code: Private void initclassloaders () {try {commonloader = createclassloader ("common", null); // 1, create commonloader Class Loader if (commonloader = NULL) {// No config file, default to this loader-we might be in a 'single 'Env. commonloader = This. getclass (). getclassloader ();} catalinaloader = createclassloader ("server", commonloader); // 2, sharedloader = createclassloader ("shared", commonloader); // 3 ,} catch (throwable t) {handlethrowable (t); log. error ("Class Loader creation threw exception", T); system. exit (1 );}}
The first step is to initialize a commonloader object through the common keyword.
Go to the createclassloader method:
private ClassLoader createClassLoader(String name, ClassLoader parent) throws Exception { String value = CatalinaProperties.getProperty(name + ".loader"); if ((value == null) || (value.equals(""))) return parent; value = replace(value); ........ ClassLoader classLoader = ClassLoaderFactory.createClassLoader (repositories, parent); ........ return classLoader; }
It should be clear here that catalinaproperties. getproperty (name + ". loader") is the method to get the attributes in the configuration file. Value = Replace (value) replaces the environment variable
After a series of transformations, get the URLs of some class paths and finally pass these URLs to the classloaderfactory. createclassloader method. Both commonclassloader and other class loaders
Is obtained through this method, they are a standardclassloader instance. Standardclassloader simply inherits from urlclassloader and implements
Standardclassloadermbean interface to implement JMX monitoring. Therefore, we can consider these three class loaders as urlclassloader objects,
Createclassloader (repositories, parent) is actually calling the urlclassloader constructor to pass in the URL set of the class path and the parent loader. If
Conf/Catalina. properties configuration file, server. loader, and shared. loade are empty by default. From the createclassloader method, you can know if it is determined.
Commonloader = catalinaloader = sharedloader.
Let's talk about the intention of setting these three class loaders first, and use the source code to prove it later. Commonloader is used to set it as the parent loader of catalinaloader and sharedloader.
Catalinaloader is used to load the classes required by Tomcat programs. Sharedloader is used to load the classes shared by programs in the webapp directory and is used by webappclassloader
(The Class Loader of your web program) is set as the parent class (from here we can know how the classes of web programs are isolated from each other, but some jar packages can be shared. Because the class loader is loading
When the class is used, the parent loader is loaded first. If the parent loader cannot be found, it is loaded by itself. Here, both sharedloader and webappclassloader have different loading paths. All
Webappclassloader inherits from sharedloader, so they share the sharedloader loading path ).
Let's take a look at securityclassload. securityclassload (catalinaloader ):
public static void securityClassLoad(ClassLoader loader) throws Exception { if( System.getSecurityManager() == null ){ return; } loadCorePackage(loader); loadCoyotePackage(loader); loadLoaderPackage(loader); loadRealmPackage(loader); loadServletsPackage(loader); loadSessionPackage(loader); loadUtilPackage(loader); loadValvesPackage(loader); loadJavaxPackage(loader); loadConnectorPackage(loader); loadTomcatPackage(loader); }
You can see in each method that it loads specified classes. Note that these class names are specified. If you put your own jar package in it, then its loading is not completed by catalinaloader.
The last step is to initialize the catalinadaemon object. From the last code, we can see that catalinadaemon is assigned an instance of org. Apache. Catalina. startup. Catalina,
The setparentclassloader method is called through reflection. The parameter is catalinaloader.
What is the purpose of setting the parent loader? The following is the source code of this method.
public void setParentClassLoader(ClassLoader parentClassLoader) { this.parentClassLoader = parentClassLoader; }
The method is very simple. It seems that this is not the problem. Let's take a look at another method of Catalina:
public ClassLoader getParentClassLoader() { if (parentClassLoader != null) { return (parentClassLoader); } return ClassLoader.getSystemClassLoader(); }
In fact, the parentclassloader attribute does not mean to load the parent class loader of the Catalina Class Loader. It is just a common attribute.
Let's see where getparentclassloader is called. There is a method in standardserver:
@Override public ClassLoader getParentClassLoader() { if (parentClassLoader != null) return (parentClassLoader); if (catalina != null) { return (catalina.getParentClassLoader()); } return (ClassLoader.getSystemClassLoader()); }
Then his sub-component standardservice:
@Override public ClassLoader getParentClassLoader() { if (parentClassLoader != null) return (parentClassLoader); if (server != null) { return (server.getParentClassLoader()); } return (ClassLoader.getSystemClassLoader()); }
The corresponding method has a setparentclassloader method.
The Engin container also has this method. Finally, webapploader has the following method:
private WebappClassLoader createClassLoader() throws Exception { Class<?> clazz = Class.forName(loaderClass); WebappClassLoader classLoader = null; if (parentClassLoader == null) { parentClassLoader = container.getParentClassLoader(); } Class<?>[] argTypes = { ClassLoader.class }; Object[] args = { parentClassLoader }; Constructor<?> constr = clazz.getConstructor(argTypes); classLoader = (WebappClassLoader) constr.newInstance(args); return classLoader; }
In this method, the org. Apache. Catalina. loader. webappclassloader constructor is called. The parentclassloader attribute of the container is the most classloader
Parent class loader. Here, we can draw a conclusion from the server, service, Engin, and iner, all of which are trying to set parentclassloader values, while parentclassloader
Will be used as the webappclassloader's parent class loader. That is to say, parentclassloader is for webappclassloader, and each level is trying to modify it. ·
Now we have finished the init method of Bootstrap. The next step is to introduce the role of the setawait (true) method. The await attribute of Catalina is set to true through reflection. After Catalina is started successfully
The await method of its member variable server is called by checking this value:
public void start() { ........ if (await) { await(); stop(); } } public void await() { getServer().await(); }
The member variable server of Catalina is a standardserver object. by calling the await method of this object, it will keep monitoring this configuration in the server. xml configuration file:
<Server port = "8005" shutdown = "shutdown">, the command sent from the defined port.
Finally, let's look at the start method:
public void start() throws Exception { if( catalinaDaemon==null ) init(); Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null); method.invoke(catalinaDaemon, (Object [])null);}
Start finally calls the start method of catalinadaemon (that is, Catalina) through reflection. (The multiple locations shown here are the catalinadaemon method called through reflection,
Because catalinadaemon is a Catalina object that is referenced by an object, it can only call the methods of the object. To call the Catalina method, you can only use reflection .)
Summary: The main task of Bootstrap is to initialize commonloader, catalinaloader, sharedloader, and load the required classes through catalinaloader,
Initialize the catalinadaemon object and call its start method.
Question: Bin/Bootstrap. jar and LIB/Catalina. Jar both have Bootstrap. The script calls the main method in Bootstrap. Jar. After Bootstrap starts three class loaders,
The classes under the org. Apache. Catalina. startup package are not loaded when the classes are loaded. That is to say, although both jar packages contain Bootstrap classes, the system classloaders only load the classes.
Bootstrap in Bin/Bootstrap. jar. All the classes in other lib directories are loaded by the three class loaders in Bootstrap. I don't know why.
Tomcat7 source code-Bootstrap task