Tomcat source code: ClassLoader design, tomcatclassloader

Source: Internet
Author: User

Tomcat source code: ClassLoader design, tomcatclassloader

Tomcat is a classic web server. Learning the source code of tomcat is of great help to us. Some time ago, I learned about the general process of tomcat's work, which is of great help to my new work. I just learned ClassLoader (the original intention of learning classloader is due to a bug in the company's products) and wrote a blog on classloaderp. For more understanding of ClassLoader, let's take a look at the ClassLoader Design of Tomcat 6.

In the past, I had a brief understanding of the tomcat Startup Process and tomcat request processing process to understand the various components and functions of tomcat. Both processes have the ClassLoader shadow, so today we are still starting from these two aspects to learn how Tomcat uses ClassLoader.

 

StandardClassLoader

The Bootstrap. main () method is simply used to execute four methods: init, setAwait, load, and start.

Init

public void init()        throws Exception    {        // Set Catalina path        setCatalinaHome();        setCatalinaBase();        initClassLoaders();        Thread.currentThread().setContextClassLoader(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;    }

In the init method, call the initClassLoader method to initialize Tomcat's ClassLoader module, and then use the newly-defined class loader to load catalinaLoader to load the org. apache. catalina. startup. Catalina class. Next, call the setParentClassLoader method in Catalina.

 

Let's take a look at what the ClassLoader module of Tomcat initialization looks like in initClassLoader:

private void initClassLoaders() {        try {            commonLoader = createClassLoader("common", null);            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);            sharedLoader = createClassLoader("shared", commonLoader);        } catch (Throwable t) {            log.error("Class loader creation threw exception", t);            System.exit(1);        }}

 

 

Three ClassLoader, commonLoader, catalinaLoader, and sharedLoader, are created here. In fact, there is a certain relationship between them:

private ClassLoader createClassLoader(String name, ClassLoader parent)        throws Exception {String value = CatalinaProperties.getProperty(name + ".loader");        if ((value == null) || (value.equals("")))            return parent;// some statementClassLoader classLoader = ClassLoaderFactory.createClassLoader            (locations, types, parent);   // some statement}

That is to say, the ClassLoader model after Initialization is:

The three classLoader objects at the top are provided by JDK. CommonLoader, catalinaLoader, and sharedLoader have a common name: StandardClassLoader.

BootstrapClassLoader is used to load some jar packages under the java_home/jre/lib directory (not all)

ExtClassLoader is used to load the jar package under the java_home/jre/lib/ext directory.

AppClassLoader is used to load the specified jar package in classpath.

In the catalina. properties file, the default loading paths of the three ClassLoader are pointed out.

common.loader=${catalina.home}/lib,${catalina.home}/lib/*.jarserver.loader=shared.loader=

This file is in the jar package and cannot be modified when tomcat is used. What should I do if I want to modify the default loading path?You can configure it in catalina. config.

For more information, see the implementation of the CatalinaProperties class.

 

As mentioned above, the main method of Bootstrap actually calls four methods: init, setAwait, start, load, except init, the other three methods are actually the setAwait, start, and load methods corresponding to the Catalina object.

From the implementation of the init method, we can know that in the Bootstrap class, except that the Catalina class is loaded by catalinaClassLoader, the other classes are loaded by ClassLoader provided by JDK. That is to say, according to the content learned in the previous section, the Catalina class cannot be directly called in the current Bootstrap class. However, we have to call the method in Catalina here. In the test above, we started another thread to solve this problem. Today, let's take a look at how Tomcat solves such application scenarios:

 

1) Call the setParentClassLoader method of Catalina in init

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);

2) Call the setAwait method of catalina in setAwait

public void setAwait(boolean await)        throws Exception {        Class paramTypes[] = new Class[1];        paramTypes[0] = Boolean.TYPE;        Object paramValues[] = new Object[1];        paramValues[0] = new Boolean(await);        Method method =             catalinaDaemon.getClass().getMethod("setAwait", paramTypes);        method.invoke(catalinaDaemon, paramValues);    }

3) start calls the start method of catalina.

public void start()        throws Exception {        if( catalinaDaemon==null ) init();        Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);        method.invoke(catalinaDaemon, (Object [])null);    }

4) load calls the load method of catalina

private void load(String[] arguments)        throws Exception {        // Call the load() method        String methodName = "load";        Object param[];        Class paramTypes[];        if (arguments==null || arguments.length==0) {            paramTypes = null;            param = null;        } else {            paramTypes = new Class[1];            paramTypes[0] = arguments.getClass();            param = new Object[1];            param[0] = arguments;        }        Method method =             catalinaDaemon.getClass().getMethod(methodName, paramTypes);        if (log.isDebugEnabled())            log.debug("Calling startup class " + method);        method.invoke(catalinaDaemon, param);    }

They are all processed using reflection.

Now,Different classLoaderThe method call before the class loaded by the loader has 2Solution:

Solution 1: Start another thread

Solution 2: Use reflection.

 

Catalina is loaded by catalinaClassLoader. During the Tomcat startup process, Tomcat components are loaded and initialized, And the entries of these processes are in Catalina. Therefore, some components in Tomcat should be loaded by catalinaClassLoader. This sentence may be full. However, I say this for a reason:

There is such a process in the init method: SecurityClassLoad.SecurityClassLoad(CatalinaLoader );

 

Let's take a look at the true nature of this process:

public static void securityClassLoad(ClassLoader loader)        throws Exception {        if( System.getSecurityManager() == null ){            return;        }                loadCorePackage(loader);        loadLoaderPackage(loader);        loadServletsPackage(loader);        loadSessionPackage(loader);        loadUtilPackage(loader);        loadJavaxPackage(loader);        loadCoyotePackage(loader);        loadHttp11Package(loader);        loadTomcatPackage(loader);}private final static void loadCorePackage(ClassLoader loader)        throws Exception {        String basePackage = "org.apache.catalina.";        loader.loadClass            (basePackage +             "core.ApplicationContextFacade$1");        loader.loadClass            (basePackage +             "core.ApplicationDispatcher$PrivilegedForward");        loader.loadClass            (basePackage +             "core.ApplicationDispatcher$PrivilegedInclude");        loader.loadClass            (basePackage +             "core.ContainerBase$PrivilegedAddChild");        loader.loadClass            (basePackage +             "core.StandardWrapper$1");        loader.loadClass            (basePackage +              "core.ApplicationHttpRequest$AttributeNamesEnumerator");    }

SecurityClassLoad (ClassLoader loader) uses the facade mode to load various classes. Only the implementation of loadCorePackage is listed here. The implementation of other methods is exactly the same as this. That's why I saidTomcatIn most cases, some components should be played by catalinaClassLoaderLoaded.

According to this method, we can also see that,To load the internal class, you must add$.

 

 

========================================================== ========================================================

WebappClassLoader

The above is actually the StandardClassLoader in Tomcat, and there is also a WebappClassLoader in Tomcat. According to the name, we can see that this ClassLoader is designed to load various Web applications. Each component of Tomcat corresponds to the Web Application, that is, StandardContext. Why? The ServletConext (Java EE standard API) we use in Web applications is implemented by ApplicationContext in Tomcat, and ApplicationContext is actually the delegate of StandardContext.

 

This Classloader is used to load classes in web applications. This class will be used in the future.

 

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.