The implementation principle of Tomcat thermal deployment

Source: Internet
Author: User

Tomcat Thermal deployment mechanism

For Java applications, a hot deployment is a Java class file that is updated at run time. Class loader plays an important role in implementing a hot deployment of Java-based application servers. Most Java-based application servers, including EJB servers and servlet containers, support hot deployment. The class loader cannot reload a class that has already been loaded, but you can load the class again into a running application as long as you are using a new class loader instance.

We know that most Web servers now support hot deployment, and for the implementation of the thermal deployment mechanism, the online speaking is not perfect, below we on the Tomcat implementation mechanism of the hot deployment, explain how it is implemented:

The Tomcat container implements a hot deployment using two mechanisms:

ClassLoader overrides the custom ClassLoader to load the corresponding JSP-compiled class into the JVM. The modified class is loaded into the JVM again by dynamically modifying the byte code in memory.

ClassLoader Implementing a JSP Reload

Tomcat has implemented a JSP load through Org.apache.jasper.servlet.JasperLoader, and here's a test: 1. Create a new Web project and write a JSP page that prints the page's Classloader,<%system.out.print (This.getclass (). getClassLoader ()) on the JSP page;%>.

2. Start the Web server, open the JSP page, we can see the background output, the JSP ClassLoader is an instance of Jasperloader.

3. Modify the JSP, save and refresh the JSP page, see the background output again, this ClassLoader instance is not just that, that is, Tomcat through a new ClassLoader loaded the JSP again.

4. In fact, for each JSP page Tomcat uses a separate classloader to load, each time after modifying the JSP, Tomcat will use a new classloader to load it.

about how to use a custom ClassLoader to load a class here do not say, I believe that the Internet can be found, JSP is a one-time consumption, each call to the container will create a new instance, which is used to throw the kind of, but for this way of implementation is difficult to use in other cases, As now many of our projects are using singleton, especially spring engineering, in which case it is unrealistic to use the new ClassLoader to load the modified class, and the Singleton class will produce multiple instances in memory, and this way cannot change the behavior of existing instances in the current memory, of course, Tomcat did not implement the reload of the class file in this way.

Modifying the byte code of a class in memory by proxy

The class file in Tomcat is loaded by Org.apache.catalina.loader. WebappClassLoader, and we can do a test that is similar to the JSP test, with the test steps not being said, just the results:

In the case of a hot deployment, for a class file loaded by the ClassLoader, its classloader is always the same webappclassloader, unless the container restarts, I believe that by doing this experiment you will no longer think that Tomcat is using a new ClassLoader to load the modified class, and for stateful instances, the properties and states previously owned by that instance will be saved and the next execution has the new class logic. This is the mystery of hot deployment (in fact, each instance only holds the state attribute of the instance, and we can see the state contained in the object by serializing the object, and the final logic exists in the class file).

The following class redefinition is implemented by: Java.lang.instrument, with reference to the relevant documentation.

Let's look at how to modify the class bytecode in memory by proxy:

The following is a simple hot deployment Proxy implementation Class (the code is coarser and there is no judgment):

 Packageagent;ImportJava.lang.instrument.ClassFileTransformer;Importjava.lang.instrument.Instrumentation;ImportJava.util.Set;ImportJava.util.Timer;ImportJava.util.TreeSet; Public  classhotagent {protected  StaticSet<string> clsnames=NewTreeset<string>();  Public  Static  voidPremain (String Agentargs, Instrumentation Inst)throwsException {Classfiletransformer transformer=NewClasstransform (inst);        Inst.addtransformer (transformer); System.out.println ("Whether to support the redefinition of a class:" +inst.isredefineclassessupported ()); Timer Timer=NewTimer (); Timer.schedule (NewReloadtask (inst), 2000,2000); }} Packageagent;Importjava.lang.instrument.classfiletransformer;importjava.lang.instrument.illegalclassformatexception;Importjava.lang.instrument.Instrumentation;ImportJava.security.ProtectionDomain; Public  classClasstransform.ImplementsClassfiletransformer {PrivateInstrumentation Inst; protectedClasstransform (Instrumentation inst) { This. inst=Inst; }     /*** This method is called at redefineclasses or initial load, meaning it is called when class is loaded again, * and we can dynamically modify the class bytecode to implement functions like proxies, using ASM or Java     Sist, * If you are familiar with bytecode, you can modify the bytecode directly. */     Public  byte[] Transform (ClassLoader loader, String className, Class<?>classbeingredefined, Protectiondomain Protectiondomain,byte[] classfilebuffer)throwsillegalclassformatexception {byte[] transformed =NULL;        HotAgent.clsnames.add (ClassName); return  NULL; }} Packageagent;ImportJava.io.InputStream;Importjava.lang.instrument.ClassDefinition;Importjava.lang.instrument.Instrumentation;ImportJava.util.TimerTask; Public  classReloadtaskextendsTimerTask {PrivateInstrumentation Inst; protectedReloadtask (Instrumentation inst) { This. inst=Inst; } @Override Public  voidrun () {Try{classdefinition[] CD=NewClassdefinition[1]; Class[] Classes=inst.getallloadedclasses ();  for(Class cls:classes) {if(Cls.getclassloader () = =NULL||! Cls.getclassloader (). GetClass (). GetName (). Equals ("Sun.misc.launcher$appclassloader"))                    Continue; String name=cls.getname (). replaceall ("\ \", "/"); cd[0]=NewClassdefinition (Cls,loadclassbytes (cls,name+ ". Class")));           Inst.redefineclasses (CD); }       }Catch(Exception ex) {ex.printstacktrace (); }    }     Private  byte[] loadclassbytes (Class cls,string clsname)throwsexception{System.out.println (clsname+":"+CLS); InputStream is=Cls.getclassloader (). Getsystemclassloader (). getResourceAsStream (Clsname); if(is==NULL)return  NULL; byte[] bt=New  byte[Is.available ()];        Is.read (BT);        Is.close (); returnBT; }}

The above is the basic implementation code, requires the component is: 1. Hotagent (pre-load) 2. Classtransform (The byte code of class can be modified when loading class), this example is useless to 3. Reloadtask (class Timer loader, the above code is for reference only) 4. Meta-inf/manifest. MF content is: (Parameter one: support class redefinition; parameter two: pre-loaded Class)

Can-redefine-classes:true premain-class:agent. Hotagent

5. Package the above components into a jar file (the component is complete and the test class file is written below). 6. To create a new Java project, write a Java logic class, and write a test class that invokes the method of the logical class in the testing class, let's look at the test class code:

 PackageTest.redefine; Public  classBean1 { Public  voidtest1 () {System.out.println ("============================"); }} PackageTest.redefine; Public  classTest { Public  Static  voidMain (string[] args)throwsinterruptedexception {Bean1 C1=NewBean1 ();  while(true) {c1.test1 (); Thread.Sleep (5000); }    }}

To run the test class:

Java–javaagent:agent.jar Test.redefine.Test

In the test class, we used a dead loop and timed the method of invoking the logical class. We can modify the method in the Bean1 implementation, will be at different times to see different output results, about the technical details also have nothing to say, I believe we can understand.

Tomcat Hot Deployment Configuration

<HostAppBase= "WebApps"Autodeploy= "true"name= "localhost"Unpackwars= "true"Xmlnamespaceaware= "false"xmlvalidation= "false">      <ContextDocBase= "Cpcweb"Path= "/cpcweb"reloadable= "true"Source= "Org.<span class="Wp_keywordlink "><ahref= "Http://res.importnew.com/eclipse"title= "Eclipse importnew Home"Target= "_blank">Eclipse</a></span>. Jst.j2ee.server:CPCWeb "/></Host>

Autodeploy= "true"-automatic deployment Reloadable= "true"-auto load

The implementation principle of Tomcat hot deployment

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.