Java ClassLoader-tomcat class loader

Source: Internet
Author: User

In the previous section, the mechanism of the system ClassLoader and the class loader is described, and the way the ClassLoader is customized. Next take Tomcat6 as an example to see how Tomat uses the self-customizing ClassLoader. (This introduction is based on tomcat6.0.41, different versions may differ!) )

Tomcat class loader as described on the web

Search the online "Tomcat class loader" will find a lot of articles, here I steal a lazy, ^_^ the online description of the Tomcat class loader to say it again.

  • Commonclassloader: The loaded class directory is specified by the Common.loader in {tomcat}/conf/catalina.properties, with Systemclassloader as parent ( Currently the default definition is Common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib /*.jar)
  • Catalinaclassloader: Loaded class directory through {tomcat}/conf/ Server.loader specified in Catalina.properties, commonclassloader as parent, if Server.loader is configured to be empty, serverclassloader Same as Commonclassloader (default Server.loader configuration is empty)
  • Sharedclassloader: Loaded class directory through {tomcat}/conf/ Share.loader specified in Catalina.properties, commonclassloader as parent, if Server.loader is configured to be empty, catalinaclassloader Same as Commonclassloader (default Share.loader configuration is empty)
  • WebappClassLoader: A WebappClassLoader instance of each context that is responsible for loading the/web-inf/lib and/web-inf/classes directories of the context, The separation between the context is done by different webappclassloader. Since the class definition is immutable once it is loaded, implementing the reload functionality of the Tomcat context is actually done by creating a new webappclassloader, so the reload approach is actually expensive, and it is important to note that The perm area of the JVM memory is only eaten, so the discarded WebappClassLoader-loaded classes are not freed by the JVM, so Tomcat's reload function, if the application-defined analogy is more, Reload a few times outofpermspace abnormal.
  • Jasperloader: One Jasperloader instance per JSP, similar to WebappClassLoader practice, JSP support modification takes effect by discarding the old Jasperloader, building a new jasperloader to do it, Similarly, there is a case of a slight permspace memory leak

The above on each classloader the role of the introduction, but please do not confuse the reader, said above all the class loader is just the name of the class loader, not the class load class name. The above figure is to see the description of the online data drawn, but the actual source of the structure of the difference is quite large. (No research is due to Tomcat version). The following is a detailed description of the next Tomcat source class loader organization structure.

Structure analysis of class loader in Tomcat source code

  The first thing to note is the situation under Tomcat's default configuration. Then look at the class initialization at Tomcat startup, which is the class initialization method for the Bootstrap class:

  private void Initclassloaders () {        try {            commonloader = Createclassloader ("common", null);            if (Commonloader = = null) {                //no config file, default to this loader-we might is 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);        }    }

 As you can see, the parent class loader that created Commonloader simultaneous is null. Tracking down will find that Commonloader's parent ClassLoader is indeed null. A friend might think that Tomcat must also rely on the JDK core library when booting, and the parent is null how to delegate the class to the parent to load the core library. Here you should not forget the LoadClass method of the ClassLoader class:

try {                    if (parent! = null) {                        c = parent.loadclass (name, false);                    } else {                        c = findbootstrapclassornull (name) ///No parent ClassLoader when using bootstrap class loader                    }                } catch (ClassNotFoundException e) {                    //classnotfoundexception thrown if Class not found                    //from the Non-null parent class loader                }

  Through the above Initclassloaders method we can also see the Catalinaloader and Sharedloader of the parent class loader are Commonloader, with the above diagram of the class loader structure in line with. However, the creation of Commonloader, Catalinaloader, and Sharedloader is dependent on the configuration of conf/catalina.properties in the Tomcat installation directory. The default configuration is:

    • Common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar
    • Server.loader=
    • Shared.loader=

Since the configuration of Server.loader and Shared.loader is empty, the Commonloader, Catalinaloader, and Sharedloader are all pointing to the same ClassLoader instance. Look at the code as follows: (limited to space only part of the code)

Private ClassLoader Createclassloader (string name, ClassLoader parent)        throws Exception {        String value = Catalinaproperties.getproperty (name + ". Loader");        if ((value = = null) | | (Value.equals ("")))            return parent;

And they point to an instance of that class loader class? Trace to the end we found the following code:

Standardclassloader classLoader = null;        if (parent = = NULL)            ClassLoader = new Standardclassloader (array);        else            ClassLoader = new Standardclassloader (array, parent);        return (ClassLoader);

Is the example of Standardclassloader, the following standardclassloader for the source of the explanation.

Then look at the creation process of WebappClassLoader, WebappClassLoader is instantiated in the Createclassloader method in the Webapploader class by reflection. Below is the source code:

    Private WebappClassLoader Createclassloader ()        throws Exception {        Class clazz = Class.forName (Loaderclass);// loaderclass= "Org.apache.catalina.loader.WebappClassLoader"        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;    }

You can see that his parent was obtained by calling Container.getparentlassloader () (if you are unfamiliar with the structure of Tomcat, see this article) trace to the end we found that it called the Containerbase method:

    Public ClassLoader Getparentclassloader () {        if (parentclassloader! = null)            return (parentclassloader);        if (parent! = NULL) {            return (Parent.getparentclassloader ());        }        Return (Classloader.getsystemclassloader ());    }

By default configuration debug can know the last is the return of the Systemclassloader, that is, WebappClassLoader's parent class loader is systemclassloader that is the last article said app ClassLoader.

(Because jasperloader I have not done analysis, first not to explain it)

Analysis of the implementation mode of Tomcat class loader

As mentioned above, Commonloader, Catalinaloader and Sharedloader are all examples of standardclassloader, to take a look at the Standardclassloader source code implementation:

public class Standardclassloader    extends URLClassLoader    implements Standardclassloadermbean {public Standardclassloader (URL repositories[]) {        super (repositories);    }    Public Standardclassloader (URL repositories[], ClassLoader parent) {        Super (repositories, parent);}    }

Have you ever felt your accident ah, right is so simple, this is the simplest way to achieve the same as I said in the previous article. (The previous article has been interpreted, here no longer explain)

Let's look at WebappClassLoader again. His implementation class is Org.apache.catalina.loader.WebappClassLoader, which is also inherited from URLClassLoader, but it overrides the LoadClass method and Findclass method. There are more than 3,000 lines of this class that don't put all the code out there.

Public Class loadclass (String name, Boolean resolve) throws ClassNotFoundException {if (log.isdebugenabled (        )) Log.debug ("LoadClass (" + name + "," + Resolve + ")");        Class clazz = null; Log access to Stopped ClassLoader if (!started) {try {throw new Illegalstateexceptio            N ();            } catch (IllegalStateException e) {log.info (sm.getstring ("webappclassloader.stopped", name), E);        }}//(0) Check if WebappClassLoader has already load this resource clazz = FINDLOADEDCLASS0 (name);            if (clazz! = null) {if (log.isdebugenabled ()) Log.debug ("Returning class from cache");            if (resolve) resolveclass (clazz);        return (Clazz);        }//(0.1) Check if ClassLoader has already been load Clazz = Findloadedclass (name);  if (clazz! = null) {if (log.isdebugenabled ()) Log.debug ("Returning class from cache");          if (resolve) resolveclass (clazz);        return (Clazz); }//(0.2) Check the system ClassLoader first, so the class definition under Web-inf/lib and web-inf/classes or {Tomcat}/libs cannot overwrite the definition that can be found at the bottom of the JVM (for example, you cannot define JAVA.LANG.I            Nteger overrides the underlying implementation of the try {clazz = System.loadclass (name);                if (clazz! = null) {if (resolve) resolveclass (clazz);            return (Clazz); }} catch (ClassNotFoundException e) {//Ignore}//(0.5) Permission to access this Clas            s when using a SecurityManager if (SecurityManager! = null) {int i = Name.lastindexof ('. ');                if (I >= 0) {try {securitymanager.checkpackageaccess (name.substring (0,i));                        } catch (SecurityException se) {String error = "Security violation, attempt to use" +                    "Restricted Class:" + name;   Log.info (Error, SE);                 throw new ClassNotFoundException (Error, SE); }}}//This is a very strange definition, the JVM's class loading mechanism suggests that the parent go to Load,load to load (see the previous article), whereas the Servelet specification is the opposite, and the Tomcat implementation does A compromise, by the user to decide (context of the delegate definition), the default use of the Servlet specification recommendation, that is delegate=false boolean delegateload = Delegate | |        Filter (name);                (1) First the parent to try to load, as stated above, unless the delegate is set, otherwise this does not execute if (delegateload) {if (log.isdebugenabled ())            Log.debug ("Delegating to Parent Classloader1" + parent);                        ClassLoader loader = parent;            if (loader = = NULL) loader = System;                try {clazz = Loader.loadclass (name); if (clazz! = null) {if (log.isdebugenabled ()) Log.debug ("Loading class from P                    Arent ");                    if (resolve) resolveclass (clazz);                return (Clazz); }} catch (ClassNotFoundException e) {;        }}//(2) to the Web-inf/lib and web-inf/classes directories to search, the details can be looked at Findclass, you will find the default is to search Web-inf/classes search Web-inf/lib        if (log.isdebugenabled ()) log.debug ("Searching local repositories");            try {clazz = Findclass (name); if (clazz! = null) {if (log.isdebugenabled ()) Log.debug ("Loading class from local rep                Ository ");                if (resolve) resolveclass (clazz);            return (Clazz);        }} catch (ClassNotFoundException e) {; }//(3) The parent then attempts to load the if (!delegateload) {if (log.isdebugenabled ()) Log.debug (            "Delegating to Parent ClassLoader at end:" + parent);            ClassLoader loader = parent;            if (loader = = NULL) loader = System;                try {clazz = Loader.loadclass (name); if (clazz! = null) {                    if (log.isdebugenabled ()) Log.debug ("Loading class from parent");                    if (resolve) resolveclass (clazz);                return (Clazz);            }} catch (ClassNotFoundException e) {;    }} throw new ClassNotFoundException (name); }

  

Related Article

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.