How does Tomcat avoid classnotfoundexception

Source: Internet
Author: User
In tomcat, why thread. currentthread (). setcontextclassloader (catalinaloader) immediately after the class loader is created )? This is mainly to avoid loading failure when the class is loaded later. The following is a typical example of how to use urlclassloader to load the specified jar package and parse the resulting loading failure.
First, define an interface that provides services and package it into testinterface. jar.
Public interface testinterface {
Public String display ();
}


Create a class named testclassloader to implement testinterface. the testinterface interface in the jar package. The package path is com. this class contains a display method, which is compiled and packaged into test. jar package, which is stored in the Directory D.
Public class testclassloader implements testinterface {
Public String display (){
Return "I can load this class and execute the method .";
}
}


Finally, we use urlclassloader to load and run the display method of the testclassloader class. Create a test class as follows:
Public class test {
Public static void main (string [] ARGs ){
Try {
URL url = new URL ("file: D:/test. Jar ");
Urlclassloader myclassloader = new urlclassloader (new URL [] {URL });
Class myclass = myclassloader. loadclass ("com. Test. testclassloader ");
Testinterface testclassloader = (testinterface) myclass. newinstance ();
System. Out. println (testclassloader. Display ());
} Catch (exception e ){
E. printstacktrace ();
}
}
}
In the main method of the test class, urlclassloader is first used to specify to load test. jar, and then. test. the testclassloader class is loaded to the memory, and a testclassloader instance is generated using the newinstance method. Then, the display method can be called. Run this test class to output the I can load this class and execute the method. Statement as expected. It seems that everything comes so naturally, when you are eager to write your own testinterface. when the jar package is transplanted to a web application, the reality is heartless, throwing Java. lang. classnotfoundexception: COM. test. testinterface exception. The error message is the rough statement in the Code. Maybe you want to know that I have added this class. Why can't you find this class? To understand why such an error is reported, You need to clarify the following points:
① In Java, we use a fully-matched class name to identify a class, that is, the package name and class name. In JVM, a class is uniquely identified by a fully-matched class name and the instance ID of a class loader. That is to say, the same virtual machine can have two classes with the same package name and class name. As long as they are loaded by two different class loaders, the class instances in their respective class loaders are also different, and cannot convert each other.
② When the class loader loads a class, it generally references, inherits, and extends other classes in the class, the Class Loader also finds these reference classes on the parent class loader layer by layer, and finally finds itself. If none of them can be found, an error of this type will be reported. That is to say, the system will only look up the reference class, but will not look down from the subclass loader.
③ Each running thread has a member contextclassloader, which is used to dynamically load other classes at runtime. When no class loaded by the class loader is explicitly declared (for example, a new class is directly added in the Program), the class loaded by the current Thread class loader by default, that is, when a thread runs to a new class that needs to be loaded, it is loaded with its own class loader. The default contextclassloader is systemclassloader. Generally, Java programs can use classes in JVM, $ java_home/JRE/lib/EXT/, and $ classpath/during execution. For the working principle of the current thread loader, see Figure 3-1-6-1. With the execution of the thread, class1 is directly loaded by contextclassloader; then the thread creates a user-defined class loader myclassloader to load class2, so class2 is loaded by myclassloader; finally, the thread is loaded through thread. currentthread (). setcontextclassloader (myclassloader) sets the current Thread class loader to myclassloader, and class3 is loaded by myclassloader.
 
Figure 3-1-6-1 Current Thread class loader


After learning about the above three points, analyze the errors that cannot find the class thrown during the previous loading:
(1) When the test class runs in the command line, it runs properly because the current Thread class loader is systemclassloader during the running, and the testinterface interface class is naturally loaded by it, the default parent class loader of urlclassloader is also systemclassloader. It is learned by the parent-parent delegation mechanism that testclassloader is loaded by systemclassloader. Then, interfaces and classes are loaded by the same class loader, naturally, you can find classes and interfaces and convert them.
(2) When the test class is moved to a web project, if the code is moved to the servlet, an error will be reported directly and cannot be run. At runtime, the current Thread class loader is the Web application Class Loader webappclassloader, and webappclassloader is different from the general class loader. It does not follow the parent-parent delegation model and will first try to load the class by itself, the testinterface class is loaded by webappclassloader because it cannot be loaded by itself. Similarly, the parent class loader of urlclassloader is systemclassloader, which is responsible for loading the testclassloader class. Okay, the problem is that two different class loaders Load two classes respectively, and webappclassloader is the descendant class loader of systemclassloader. Because the testclassloader class extends the testinterface interface, therefore, when the urlclassloader loads testclassloader, The testinterface class in webappclassloader cannot be found, that is, Java is thrown. lang. classnotfoundexception: COM. test. testinterface exception.
There are two solutions to the preceding errors:
① Because the two classes are loaded by two class loaders and the class cannot be found, the simplest solution is to unify the two classes by a class loader, load testclassloader. use the current Thread class loader to load jar files. You only need to change the code slightly,
Urlclassloader myclassloader = new urlclassloader (
New URL [] {URL}, thread. currentthread (). getcontextclassloader ());
The emphasis is on the bold part, that is, when the urlclassloader object is created, the current class loader is passed in as the parent class loader, and the current Thread class loader of the Web application is webappclassloader. When testclassloader is loaded. when jar is used, it is preferentially handed over to webappclassloader for loading. This ensures that both classes are in the same class loader and no class exception is reported.
② If urlclassloader is not set as the parent class loader, its default parent class loader is systemclassloader, then testclassloader. jar will be loaded by systemclassloader. In order to find the testinterface class in systemclassloader, The testinterface class must be loaded by the class loader above the parent class loader of systemclassloader, figure 3-1-6-1 shows that only two class loaders meet the conditions-bootstrapclassloader and extensionclassloader. As bootstrapclassloader acts as the ancestor class, it is responsible for loading the Java core class and generally does not allow it to load the user class. Therefore, we turn to extensionclassloader, which is responsible for loading the Java extension class, $ java_home/JRE/lib/EXT directory. jar is copied to this directory, which ensures that the reference class of the class loaded by urlclassloader can be found in extensionclassloader. The problem is also solved.


After so much discussion, we will return to the thread in Tomcat. currentthread (). setcontextclassloader (catalinaloader), the typical classloader errors discussed above also exist in Tomcat, so Tomcat is solved by setting the thread context class loader. In tomcat, the class loader has three conditions: 1. Tomcat 7 is loaded by the commonloader by default. 2. The parent class loader of commonloader is systemloader. 3. The current thread loader is systemloader. In 3-1-6-2, first check the default situation. contextclassloader is assigned as systemloader, and systemloader cannot see the classes loaded by commonloader. That is, if the class is referenced during the process, an error is returned. Next, let's take a look at the second transformation and assign contextclassloader to commonloader. If $ catalina_base/lib or $ catalina_home/lib is used during Tomcat startup, no error will be reported, it can see all loaded classes of systemloader and its parent class loader. Simply put, the solution is to set commonloader as the thread context class loader.
 
Figure 3-1-6-2 Tomcat Class Loader
To avoid class loading errors, we should set the thread context class loader as soon as possible, so we will immediately set the class as soon as initialization is started in Tomcat, that is, the init method of the bootstrap class passes the thread. currentthread (). setcontextclassloader (catalinaloader) settings, where catalinaloader and commonloader are the same object. This thread is loaded by the commonloader class loader by default.

How does Tomcat avoid classnotfoundexception

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.