In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly explains "Java class dynamic loading and hot replacement how to use", the article explains the content is simple and clear, easy to learn and understand, the following please follow the editor's ideas slowly in-depth, together to study and learn "Java class dynamic loading and hot replacement how to use" it!
Preface
Recently, I encountered two problems related to loading and unloading the Java class:
1) is a judgment question about Java: after a class is loaded for the first time, it will stay in JVM for a long time until JVM exits. Is this statement correct?
2) in an integrated platform developed, a variety of tools with similar interfaces need to be integrated, and the tools may be added, and there will be tailoring for deployment in different environments (for example, applications that provide services, can not provide specific procurement tools), how can it be better implemented?
For the second point above, we use Java plug-in development. Both of the above problems are related to Java's class loading and hot replacement mechanism.
1. Java classloader and parent delegation model 1.1 Java classloader
The class loader, as its name implies, is used to implement class loading operations. Each class loader has a separate class namespace, that is, each class loaded by the class loader is in its own class namespace. If you want to compare whether two classes are "equal", the two classes must first be loaded in the same class namespace, that is, by the same class loader (that is, for any class, the uniqueness of the class itself must be determined by both the class itself and the class loader that loads it). Classes that are not loaded by the same class loader are not equal.
In Java, there are mainly the following class loaders:
Next, a brief introduction to the above types of loaders:
Launch class loader (Bootstrap Class Loader): this class is developed using C++ (the only one of all class loaders that uses C++) to load the jar and tools.jar in the / lib directory or the class specified with the-Xbootclasspath parameter.
Extended class loader (Extension ClassLoader): defined as misc.Launcher$ExtClassLoader, which is used to load the / lib/ext directory or to use classes specified by java.ext.dir.
Application class loader (Application ClassLoader): defined as misc.Launcher$AppClassLoader, used to load all classes under the user classpath (classpath), which is generally the default class loader for the application.
User-defined class loader (User Class Loader): user-defined class loader is generally not necessary. Later, we will specifically introduce this type of class loader.
1.2 Parental delegation model
The parent delegation model is a kind of loader pattern introduced from Java1.2. In Java, the class loading operation is completed through the loadClass () method in java.lang.ClassLoader. Let's first take a look at the implementation of this method (fished out directly from the Java source 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) {long t0 = System.nanoTime () 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. Long T1 = System.nanoTime (); c = findClass (name); / / this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime (). AddTime (T1-T0); sun.misc.PerfCounter.getFindClassTime (). AddElapsedTimeFrom (T1); sun.misc.PerfCounter.getFindClasses (). Increment () }} if (resolve) {resolveClass (c);} return c;}}
Combined with the comments above, let's explain the content of the parent delegation model:
1) after receiving a class load request, first determine whether the class has been loaded, and if it has already been loaded, return directly
2) if the parent class loader is not yet loaded, get the parent class loader first. If the parent class loader can be obtained, call the parent class's loadClass () method to load the class. If the parent class loader cannot be obtained, call the initiator loader to load the class.
3) determine whether the class is loaded by the parent class loader or the startup class loader, return if it has been loaded, and try to load the class yourself if it is not loaded successfully.
The above description illustrates the implementation of the loadClass () method, and we further explain the above steps:
Because the class loader first transfers the parent class loader to load, from the implementation of the loadClass () method, we know that the parent class loader will try to adjust its parent class loader until the class loader is started, so the loading of any class will eventually be delegated to the startup class loader to load first.
As described earlier, startup class loaders, extension class loaders, and application class loaders all have their own scope of loading classes. For example, the startup class loader only loads the JDK core library, so not all the parent class loaders can load successfully. The parent class loader cannot be loaded (such as the above code, ClassNotFoundException is thrown), and it will be loaded by itself at this time.
Finally, let's make a long talk and then make a summary:
Parent delegation model: if a class loader receives a class load request, it will first delegate the load request to the parent class loader to complete, as is the case with the class loader at each level. finally, all load requests are transferred to the root startup class loader to complete, and if the parent class loader cannot complete the load request (that is, the class cannot be found within the scope of its own loading), the subclass loader will try to load itself.
The advantage of this parental delegation model is that all classes are loaded by the top-level class loader as far as possible, which ensures the uniqueness of the loaded class. If each class is randomly loaded by a different class loader, the implementation relationship of the class can not be guaranteed, which is of great significance to ensure the stable operation of the Java program.
2. Dynamic loading and unloading of Java classes 2.1 unloading of Java classes
In Java, each class has a corresponding Class Loader. Similarly, each instance object has a corresponding class. JVM unloads this class when the following three conditions are met:
1) all instance objects of this class are not reachable
2) the Class object of this class is not reachable
3) the Class Loader of this class is unreachable
So what is the direct relationship between the Class Loader of the above sample object, Class object, and class?
In the internal implementation of the classloader, a Java collection is used to hold references to the loaded class. A Class object always refers to its classloader, and you can get its classloader by calling the getClassLoader () method of the Class object. Therefore, there is a two-way reference relationship between the Class instance and the loader that loads it.
An instance of a class always refers to the Class object that represents the class. The getClass () method is defined in the Object class, which returns a reference to the Class object that represents the class to which the object belongs. In addition, all Java classes have a static property class that references the Class object that represents the class.
The class loaders that come with the Java virtual machine (the three kinds of loaders described earlier) will always exist during the JVM operation, and these class loaders will always reference the Class objects of the classes they load, so these Class objects are always accessible. Therefore, classes loaded by the class loader that comes with the Java virtual machine will never be unloaded during the life cycle of the virtual machine.
So, are we completely unable to dynamically modify the classes we use while the Java program is running? The answer is no! According to the above analysis, the class loaded by the Java virtual machine's own class loader can not be unloaded, we can customize the class loader to load the Java program, and the Java class loaded by the custom class loader can be unloaded.
2.2 Custom class loader
As mentioned earlier, the parent delegation model for class loading is the recommended model, implemented in loadClass, and is not a required model. We can load the Java class we need directly through a custom class loader without delegating to the parent class loader.
As shown in the figure above, we have a custom class loader MyClassLoader to load the class MyClass, and the above three types of references exist in JVM (the above figure ignores the references of these three types of objects to other objects). If we set the three reference variables on the left to null, then the loaded MyClass will be unloaded at this point.
2.3 problems with dynamic unloading
Dynamic unloading can only be done with the help of JVM's garbage collection function, but we know that JVM's garbage collection is triggered only when the heap memory footprint is high. Even if we call System.gc (), we don't immediately perform a garbage collection operation, but just tell JVM that we need to perform a garbage collection, and when it comes to garbage collection depends on JVM's own garbage collection strategy.
But we don't need to be pessimistic, and even if dynamic unloading is not so reliable, there is hope for hot replacement of dynamic Java classes.
3. Hot replacement of Java class
The hot replacement method of the Java class is introduced through the code below (the code is crude, mainly to illustrate the problem):
Such as the following code:
First define a custom class loader:
Package zmj;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;public class FileClassLoader extends ClassLoader {private String fileName; public void setFileName (String fileName) {this.fileName = fileName;} public Class loadClass (String name) throws ClassNotFoundException {if (name.startsWith ("java")) {return getSystemClassLoader () .loadClass (name);} Class cls = null File classF = new File (fileName); try {cls = instantiateClass (name, new FileInputStream (classF), classF.length ());} catch (IOException e) {e.printStackTrace ();} return cls;} private Class instantiateClass (String name, InputStream fin, long len) throws IOException {byte [] raw = new byte [(int) len]; fin.read (raw) Fin.close (); return defineClass (name, raw, 0, raw.length);}}
When it comes to loadClass above, first determine whether the class name (the fully qualified name that contains package) starts with java, and if it starts with java, use the class loader that comes with JVM to load.
Then define a simple dynamically loaded class:
Package zmj;public class SayHello {public void say () {System.out.println ("hello ping...");}}
During execution, the print content is dynamically modified to test the hot loading of the class.
Then define a calling class:
Package zmj;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Main {public static void main (String [] args) throws InterruptedException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {while (true) {FileClassLoader fileClassLoader = new FileClassLoader (); fileClassLoader.setFileName ("D:/workspace/idea/test/class-loader-test/target/classes/zmj/SayHello.class"); Object obj = null Obj = fileClassLoader.loadClass ("zmj.SayHello"). NewInstance (); Method m = obj.getClass (). GetMethod ("say", new Class [] {}); m.invoke (obj, new Object [] {}); Thread.sleep (2000);}
When we run the above Main program, we dynamically modify the execution (in SayHello, from hello zmj... Change it to hello ping...), and the final display is as follows:
Hello zmj...
Hello zmj...
Hello zmj...
Hello ping...
Hello ping...
Hello ping...
Thank you for reading, the above is the content of "dynamic loading and hot replacement of classes in Java". After the study of this article, I believe you have a deeper understanding of how to use dynamic loading and hot replacement of classes in Java, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.