Http://waterdh.iteye.com/blog/520399
This article mainly discusses the feasibility of hot deployment of partial modules in Java applications based on the characteristics of classloader and problems encountered in the actual product environment.
We know that some Web applications provide the ability to automatically detect and load webapps, but most of the time, it is equivalent to restarting webapps, and data stored in the memory will also be lost, it cannot flexibly meet the needs. Although the osgi framework also provides hot module deployment, the application is limited to the osgi framework for hot deployment, which sometimes outweighs the loss. Therefore, we want to customize classloader based on actual needs and flexibly specify which classes are reloaded and which classes are not needed.
Let's get down to the truth and implement our practices. Here we will briefly introduce the classloader mechanism of Java:
We can see that the classloader hierarchy in the virtual machine is loaded by the classloader of the outermost layer to the class specified by the fully qualified name. If the load fails, it is delegated to the parent classloader of the classloader, to root classloader.
Java code
- Protected synchronized class <?> Loadclass (string name, Boolean resolve)
- Throws classnotfoundexception
- {
- // 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 = findbootstrapclass0 (name );
- }
- } Catch (classnotfoundexception e ){
- // If still not found, then invoke findclass in order
- // To find the class.
- C = findclass (name );
- }
- }
- If (RESOLVE ){
- Resolveclass (C );
- }
- Return C;
- }
Here, our custom classloader can load classes under the specified package by reloading the loadclass method, and all the other classes are loaded by the parent classloader. The defineclass method of classloader is used here, so that our classloader can load class files at any specified position.
Java code
- Public class myclassloader extends classloader {
- Public static concurrenthashmap <string, class <?> Classes = new concurrenthashmap <string, class <?> ();
- Public static mqclassloader instance = new myclassloader ();
- // Construct a custom classloader and specify the parent classloader
- Public myclassloader (){
- Super (thread. currentthread (). getcontextclassloader ());
- }
- Public class <?> Load (string name, byte [] data, Boolean resolve ){
- Class <?> Klass = defineclass (name, Data, 0, Data. Length );
- If (RESOLVE)
- Resolveclass (Klass );
- Classes. Put (name, Klass );
- Return Klass;
- }
- Public class <?> Loadclass (string name, Boolean resolve) throws classnotfoundexception {
- Object value = classes. Get (name); // check the cache
- If (value! = NULL & value! = Invalid ){
- Class <?> Klass = (class <?>) Value;
- If (RESOLVE)
- Resolveclass (Klass );
- Return Klass;
- } Else {// The cache does not exist
- Byte [] DATA = read (findclassfile (name); // read class files
- If (Data = NULL)
- Return super. loadclass (name, resolve); // submit it to the parent classloader to load the class file
- Else {
- Try {
- Lock. Lock ();
- Object cc = classes. Get (name); // check the cache
- If (CC! = NULL ){
- Return (class <?>) CC;
- } Else
- Return instance. Load (name, Data, resolve); // load your own class file
- } Finally {
- Lock. Unlock ();
- }
- }
- }
- }
- }
The code above describes the loading logic of the custom classloader. findclassfile () is the class file method that you need to find the class file from where you define it.
The defineclass method can be flexibly used for Distributed Dynamic computing. hadoop mapreduce should use this method to ensure the transmission and operation of processing classes between Server clusters.
Java code
- /**
- * Reinitialize to implement the class specified by the overload.
- */
- Public static void reset (){
- Instance = new myclassloader ();
- Classes. Clear ();
- }
In fact, each reset will generate a new classloader instance, which will be recycled only after all the classes loaded by this instance are recycled. Here we will release all the resets, no memory overflow problem has been found after testing.
Call the methods of these classes:
Java code
- Public static void invoke (string method, object [] OBJ, class <?> [] Parametertypes ){
- Try {
- Object CLS = myclassloader. instance. loadclass ("class full qualified name", true). newinstance ();
- Cls. getclass (). getmethod (method, parametertypes). Invoke (CLS, OBJ );
- } Catch (exception e ){
- Logger. Error ("reloadable error" + method, e );
- }
- }
It can only be called through reflection. Due to the security mechanism of classloader, classes loaded by the parent classloader and classes loaded by the sub-classloader cannot be converted to each other.
It should be emphasized that all variables after the overloaded class is reinitialized, so some important data variables must be managed by the parent classloader.
This method has some disadvantages. The core logic is combined to separate the variables, which affects the structure of the application.
At present, this method should be used in a message service, mainly to avoid restarting the service due to some minor changes. Restarting the message service is very troublesome for large systems, it's hard to say whether it's worth it. Let's take a deeper look at java.
Http://www.iteye.com/topic/1123646
Http://www.iteye.com/topic/711162