Classloader for Tomcat source code analysis
All articles in this series are Tomcat 7.0 code analysis.
1. Basic classloader knowledge 1.1. Parent-Child principal Model
We know that in the Java System, the default Loading Method of the Class Loader is to use the parent-child delegate method to load the class, that is, first try to use the parent class loader to load the class, if this class is not found, we can see that this is a recursive loading process. The core code is roughly as follows:
Java code
- Protected class <?> Loadclass (string name, Boolean resolve)
- Throws classnotfoundexception
- {
- Synchronized (getclassloadinglock (name )){
- // First, check if the class has already been loaded
- Class C = findloadedclass (name );
- If (C = NULL ){
- ......
- Try {
- If (parent! = NULL ){
- C = parent. loadclass (name, false );
- } Else {
- C = findbootstrapclassornull (name );
- }
- } Catch (classnotfoundexception e ){
- // Classnotfoundexception thrown if class not found
- // From the non-null parent class loader
- }
- If (C = NULL ){
- // If still not found, then invoke findclass in order
- // To find the class.
- ...
- C = findclass (name );
- ......
- }
- }
- ......
- Return C;
- }
- }
Many classloader inheritance classes use this loading method by default. urlclassloader is widely used. 1.2. runtime model of the Class Loader:
When a JVM is started, at least three classloader will be started:
1. Bootstrap Class Loader
Load the core Java packages and place them in the <java_home>/lib directory. This part is part of the JVM and is usually completed using native code.
2. Extensions Class Loader
Load the Java extension package, that is, the Package located under <java_home>/lib/EXT. Note that, some JVMs use the same loader as the bootstrap class loader, while Sun separates the two. Its implementation class is Sun. misc. launcher $ extclassloader.
3. System Class Loader
The default Implementation of Sun is Sun. Misc. launcher $ extclassloader.
The parent-child relationship between the three is: the bootstrap class loader is the parent class loader of the extensions Class Loader, And the extensions class loader is the parent class loader of the system class loader.
2. Tomcat classloader Model
Shows how to load the hierarchical model of classloader of Tomcat 7.0:
This model is somewhat different from the previous Tomcat 5.5, because in addition to the common class loader, there are Catalina class loaders and shared class loaders, this can only lead to more configurations and concepts, which are no longer used, although configuration can be performed.
1. common Class Loader: loads class files and jar packages and their resource files under $ catalina_home/lib and $ catalina_base/lib. These files will be shared by all web applications, it will also be used when Tomcat is running. It is configured in Catalina. in properties, if no configuration is available, the system class loader is used by default. Configuration example: Common. loader =$ {Catalina. home}/lib, $ {Catalina. home}/lib /*. jar2. app Class Loader: Class Loader for Web applications, resource files under Web applications, and jar packages in the class file box, which comply with Java Web standards, they are located under the/WEB-INF/classes and/WEB-INF/lib folder of the Web application. 3. Implementation of the Class Loader
The Tomcat class loader has three class implementations: standardclassloader, webappclassloader, and jasperloader. These three class loaders are subclasses of urlclassloader. The difference is that standardclassloader does not customize the urlclassloader method, that is, it also uses the delegate method to load classes. The loadclass () method is overwritten.
1. The standardclassloader Class Loader creates an instance of the common class loader.
2. webappclassloader creates a Class Loader instance for each application. We do not recommend that you use the Parent-Child principal model when loading the web application class, but must ensure that the class is Java. * And javax. * packages starting with the bootstrap loader must be loaded by the system class loader.
The core code is as follows:
Java code
- Public class loadclass (string name, Boolean resolve)
- Throws classnotfoundexception {
- ......
- // (0) Check our previusly loaded local class Cache
- Clazz = findloadedclass0 (name );
- If (clazz! = NULL ){
- If (log. isdebugenabled ())
- Log. debug ("returning class from cache ");
- If (RESOLVE)
- Resolveclass (clazz );
- Return (clazz );
- }
- // (0.1) Check our previusly loaded class Cache
- Clazz = findloadedclass (name );
- If (clazz! = NULL ){
- If (log. isdebugenabled ())
- Log. debug ("returning class from cache ");
- If (RESOLVE)
- Resolveclass (clazz );
- Return (clazz );
- }
- // (0.2) Try loading the class with the system class loader, to prevent
- // The webapp from overriding j2se classes
- // Ensure that packages starting with Java. * And javax. * must be loaded by the system class loader.
- Try {
- Clazz = system. loadclass (name );
- If (clazz! = NULL ){
- If (RESOLVE)
- Resolveclass (clazz );
- Return (clazz );
- }
- } Catch (classnotfoundexception e ){
- // Ignore
- }
- ......
- Boolean delegateload = delegate | filter (name );
- // (1) delegate to our parent if requested
- // Whether the delegate method is used when mbeans are loaded
- 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 parent ");
- If (RESOLVE)
- Resolveclass (clazz );
- Return (clazz );
- }
- } Catch (classnotfoundexception e ){
- ;
- }
- }
- // (2) Search Local repositories
- // Load locally without entrusting the parent Loader
- If (log. isdebugenabled ())
- Log. debug ("Searching Local repositories ");
- Try {
- Clazz = findclass (name );
- If (clazz! = NULL ){
- If (log. isdebugenabled ())
- Log. debug ("loading class from local repository ");
- If (RESOLVE)
- Resolveclass (clazz );
- Return (clazz );
- }
- } Catch (classnotfoundexception e ){
- ;
- }
- // Finally load with the parent Loader
- 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 );
- }
We can see that it is not a simple parent-child delegation method to load classes.
3. jasperloader is a Class Loader created to load the servlet compiled by JSP. it overwrites the loadclass () method, except for over-loading Org. apache. JSP..
The core code is as follows:
Java code
- Public class loadclass (final string name, Boolean resolve)
- Throws classnotfoundexception {
- Class clazz = NULL;
- // (0) Check our previusly loaded class Cache
- Clazz = findloadedclass (name );
- If (clazz! = NULL ){
- If (RESOLVE)
- Resolveclass (clazz );
- Return (clazz );
- }
- // (. 5) permission to access this class when using a securitymanager
- ......
- If (! Name. startswith (constants. jsp_package_name )){
- // Class is not in org. Apache. jsp, therefore, have our
- // Parent load it
- Clazz = parent. loadclass (name );
- If (RESOLVE)
- Resolveclass (clazz );
- Return clazz;
- }
- // All files starting with org. Apache. jsp. * are loaded by the class loader.
- Return findclass (name );
- }
I will talk about it today.