Do we need a custom classloader?One reason: if we customize classloader, we can control the JVM loading action.
The above mentioned class ID is composed of package + classname. For all classes that implement the java. Io. serializable interface, the version of these classes is managed by the serialversionuid (RMI, JNDI, and security have such an ID ). It is represented by a 64-bit Hash (composed of classname, filed, and method ). Technically, if the hash values of classname, field, and mehtodd are the same, they are considered to be the same version.
Suppose there is a situation where we want to write a Java execution engine (for example, using an RMI to publish a server program and execute the client interface, the engine must implement the interface for the task specific to the existing client (taskintf here ). Once a task is submitted to the execution engine, the server loads all the code to be executed. Assume that different terminals submit different codes. But all of them are the same package name, and the same class name. Can the server identify the execution request submitted by the client? Now there is a problem: If one execution program on the server executes two clients to submit the same version of code, how can the client get the expected execution results? Don't think this is simple. Let's create an Rmi first. See what the results will look like. The answer is in the code in this article (I also want to know at this time). The local file is like.
Figure 2 Program directory structure (Code included in this article ).Under the samepath directory, there are two version. version. Class. They have the same package name and class name. The only difference is that. The method in the V1 directory is:
Public void FX (){
Log ("This =" + This + "; version. FX (1 ).");
}
The method in the V2 directory is: Public void FX (){
Log ("This =" + This + "; version. FX (2 ).");
} Run the following command: Set classpath =.; % current_root %/V1; % current_root %/V2.
% Java_home %/bin/Java test result is as follows:
Figure 3.Set the classpath directory to V1.
Switch to set classpath =.; % current_root %/V2; % current_root %/V1
% Java_home %/bin/Java Test
The result is as follows:
Figure 4.Set the classpath directory to V2.
Obviously, the order can be found from classpath in the above example. If we use version. version of V1 and V2. Delete all calls. Compress them into a myextension. jar package and put it in the Java. Ext. dirs directory .. In this caseExtclassloaderInstead of appclassloader.
The result is as follows:
Figure 5.AppClassLoader
AndExtClassLoader
Note that sun. Misc. launcher $ extclassloader @ a9c85c is loaded with extclassloader.
Next, let's look at another example. InDifferentversionsThe example in the directory contains an execution engine such as RMI serverimpl. The client implements the common. taskintf interface. The two clients. taskimpl are as follows:
Static {
Log ("client. taskimpl. Class. getclassloader
(V1): "+ taskimpl. Class. getclassloader ());
}
Public void execute (){
Log ("This =" + This + "; execute (1 )");
}
The other is:
Static {
Log ("client. taskimpl. Class. getclassloader
(V1): "+ taskimpl. Class. getclassloader ());
}
Public void execute (){
Log ("This =" + This + "; execute (2 )");
}
Execute this way (the order is random. Put % current_root %/Client2 in front here ):
Classpath = % current_root %/common; % current_root %/server;
% Current_root %/Client2; % current_root %/Client1
% Java_home %/bin/Java Server. Server
Start server first ..
Submit the two clients to the server for execution (even if the client1.bat and client2.bat server monitoring screens are 6 in the execution program .)
Figure 6. execution engine server console
Let's look at the two figures below (Figure 7 and figure 8), which reflect the execution of the client.
Figure 7. execution engine client 1 Console
Figure 8. execution engine client 2 Console
Looking at the above three execution results, we found that since the server was started with appclassloader, it was loaded to Client2 in any case (because the classpath order of Client2 is relatively high ),
Here Client1 is very depressing. It runs execute (1) on its own and sends it to the server through RMI for execution. It becomes execute (2 )..
It is worth noting that after Client1 and Client2 are respectively sent to the server for execution, the server displays the following records:
Client. taskimpl. Class. getclassloader (V2): Sun. Misc. lancuher @ appclassloader @ XXXX zhiz is executed only once. This = client. taskimpl @ XXXXX execute (2); executed twice
As mentioned above, for a classloader, the same page + classname can only define one class, and different classloader can define different classes even when loading the same page. classname
Here, I found that it is not easy to solve the problem raised above. :(.
How can this problem be solved? The answer is --- use the custom classloader ..
If you are not in a hurry, read the code in the differentversionspush directory first)
Obviously, it is necessary to write custom classloader.
Figure 7. execution engine client 1 Console
Figure 8. execution engine client 2 Console
Looking at the above three execution results, we found that since the server was started with appclassloader, it was loaded to Client2 in any case (because the classpath order of Client2 is relatively high ),
Here Client1 is very depressing. It runs execute (1) on its own and sends it to the server through RMI for execution. It becomes execute (2 )..
It is worth noting that after Client1 and Client2 are respectively sent to the server for execution, the server displays the following records:
Client. taskimpl. Class. getclassloader (V2): Sun. Misc. lancuher @ appclassloader @ XXXX zhiz is executed only once. This = client. taskimpl @ XXXXX execute (2); executed twice
As mentioned above, for a classloader, the same page + classname can only define one class, and different classloader can define different classes even when loading the same page. classname
Here, I found that it is not easy to solve the problem raised above. :(.
How can this problem be solved? The answer is --- use the custom classloader ..
If you are not in a hurry, read the code in the differentversionspush directory first)
Obviously, it is necessary to write custom classloader.
Figure 8. execution engine client 2 Console
Looking at the above three execution results, we found that since the server was started with appclassloader, it was loaded to Client2 in any case (because the classpath order of Client2 is relatively high ),
Here Client1 is very depressing. It runs execute (1) on its own and sends it to the server through RMI for execution. It becomes execute (2 )..
It is worth noting that after Client1 and Client2 are respectively sent to the server for execution, the server displays the following records:
Client. taskimpl. Class. getclassloader (V2): Sun. Misc. lancuher @ appclassloader @ XXXX zhiz is executed only once. This = client. taskimpl @ XXXXX execute (2); executed twice
As mentioned above, for a classloader, the same page + classname can only define one class, and different classloader can define different classes even when loading the same page. classname
Here, I found that it is not easy to solve the problem raised above. :(.
How can this problem be solved? The answer is --- use the custom classloader ..
If you are not in a hurry, read the code in the differentversionspush directory first)
Obviously, it is necessary to write custom classloader.