Look at the essence through the phenomenon: Java class dynamic loading and hot replacement

Hua Weiyun 2021-01-20 21:45:37
look essence phenomenon java class


Abstract : This article mainly introduces class loader 、 User defined class loader and class loading and unloading, etc , It also introduces with examples Java Hot substitution of class .

lately , Met two and Java Class loading and unloading related issues :

1) It's a story about Java The judgment question of : After a class is loaded for the first time , Stay for a long time JVM, until JVM sign out . The idea that , Is it right ?

2) In an integrated platform developed , Need to integrate multiple tools with similar interfaces , And there may be new tools , At the same time, there will be tailoring in different environments ( For example, the application of external services , Can't provide specific purchasing tools ), How to better realize ?

For the first 2 spot , We use Java Plug in development and implementation . The two questions above , And all Java Class loading is related to the hot replacement mechanism .

1. Java Class loader and parental delegation model for

1.1 Java Class loader

Class loader , seeing the name of a thing one thinks of its function , Is used to implement the class loading operation . Each class loader has a separate class namespace , That is, every class loaded by the class loader , All in their own class namespace , If To compare whether two classes are “ equal ”, First, the two classes must be in the same class namespace , That is, loaded by the same class loader ( That is, for any class , Must be determined by the class itself and the class loader that loads it JVM Uniqueness in ), Classes that are not loaded by the same class loader , Not equal .

stay Java in , There are mainly the following class loaders :

chart 1.1 Java Class loader

below , Briefly introduce the above types of loaders :

  • Start class loader (Bootstrap Class Loader): This class uses C++ Development ( In all class loaders , Only use C++ Class loader developed ), Used to load <JAVA_HOME>/lib Directory jar and tools.jar Or use -Xbootclasspath The class specified by the parameter .
  • Extend the classloader (Extension Class Loader): Defined as misc.Launcher$ExtClassLoader, Used to load <JAVA_HOME>/lib/ext Directory or use java.ext.dir Specified class .
  • Application class loader (Application Class Loader): Defined as misc.Launcher$AppClassLoader, Used to load the user class path (classpath) All of the following classes , In general , This class is the default class loader for applications .
  • User defined class loader (User Class Loader): User defined class loader , In general, there is no need to , Later, we will introduce this type of class loader .

1.2 Parent delegation model

Parent delegation model , It's from Java1.2 A kind of loader mode introduced at the beginning , stay Java in , Class is loaded through java.lang.ClassLoader Medium loadClass() Method to complete , Let's first look at the implementation of this method ( Directly from Java From the 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;
}
}

Let's combine the notes above , To explain the content of the parental delegation model :

1) After receiving a class load request , First, judge whether the class is loaded , If it's loaded , Then return directly ;

2) If not already loaded , First get the parent class loader , If you can get the parent class loader , Then call the loadClass() Method to load the class , If the parent loader cannot be obtained , Call the launcher loader to load the class ;

3) Determine whether the class is loaded by the parent class loader or the startup class loader , If the load is complete, return , If not loaded successfully , Try to load the class yourself .

The description above , Illustrates the loadClass() Method implementation , Let's further explain the above steps :

  • Because the class loader first calls the parent class loader to load , from loadClass() Method implementation , We know that the parent loader will try to tune its own parent loader , Until you start the class loader , therefore , Loading any class , Will eventually delegate to the boot loader to load first ;
  • In front of the introduction , Start class loader 、 Extend the classloader 、 Application class loader , Each class has its own scope of loading , For example, starting a class loader only loads JDK Core library , Therefore, not all parent class loaders can be loaded successfully , Parent loader failed to load ( It's like the code above , Throw it out ClassNotFoundException), It will be loaded by itself .

Finally, let's talk about it , To sum up :

Parent delegation model : If a class loader receives a class load request , Will first delegate the load request to the parent loader to complete , The class loader at each level is like this , Finally, all the loading requests are transmitted to the root boot loader to complete , If the parent loader cannot complete the load request ( That is, the class can't be found in the scope loaded by yourself ), The subclass loader will try to load itself .

One advantage of this parental delegation model is : Namely All classes are loaded by the top-level class loader as much as possible , Ensures the uniqueness of the loaded class , If each class is randomly loaded by a different class loader , The implementation relationship of the class cannot be guaranteed , For the guarantee Java The stable operation of the program is of great significance .

2. Java Class dynamic loading and unloading

2.1 Java Class

stay Java in , Each class has a corresponding Class Loader, alike , Each instance object also has its own class , When the following three conditions are satisfied ,JVM Will unload this class :

1) All instance objects of this class are unreachable

2) Of the class Class Object is not reachable

3) Of the class Class Loader Unreachable

that , The above example object 、Class Objects and classes Class Loader What is the direct relationship ?

In the internal implementation of the class loader , Use one Java Collection to hold references to the loaded classes . And one Class Object always references its classloader , call Class Object's getClassLoader() Method , You can get its classloader . therefore ,Class Between the instance and the loader that loads it is Two way reference relationship .

An instance of a class always refers to Class object . stay Object Class getClass() Method , This method returns Class References to objects . Besides , be-all Java Class has a static property class, It refers to the Class object .

Java Class loader of virtual machine ( The three types of loaders described above ) stay JVM In operation , There will always be , These class loaders will always refer to the class they are loading Class object , So these Class The object is always accessible . therefore , from Java Classes loaded by the virtual machine's own class loader , In the life cycle of a virtual machine , Will never be unloaded .

that , Can't we be at all Java During the operation of the program , Dynamically modify the classes we use ? The answer is No ! Based on the above analysis , adopt Java The class loaded by the class loader of the virtual machine cannot be unloaded , We can customize the class loader to load Java Program , Loaded through a custom class loader Java class , It can be uninstalled .

2.2 Custom class loaders

As described earlier , Class loaded parent delegation model , It's a recommendation model , stay loadClass Implemented in , It's not a model that has to be used . We can customize the class loader , Load directly what we need Java class , Instead of delegating to the parent loader .

chart 2.1 Custom class loaders

As shown in the figure above , We have custom class loaders MyClassLoader, Used to load classes MyClass, It's in JVM in , There are three types of references ( The above figure ignores the references of these three types of objects to other objects ). If we take the three reference variables on the left , All set to null, So at this time , Already loaded MyClass Will be unloaded .

2.3 Problems with dynamic unloading

Dynamic offloading requires the help of JVM The garbage collection function of can do , But we know that ,JVM The garbage collection of , Only when heap memory usage is high , Will trigger . Even if we call System.gc(), It doesn't immediately perform garbage collection , And just tell JVM Need to perform garbage collection , As for when to recycle , It depends JVM Your own garbage collection strategy .

But we don't need to be pessimistic , Even if dynamic offloading is not so robust , But to achieve dynamic Java Class hot swapping is still promising .

3. Java Hot substitution of class

Let's introduce it through the code Java Class ( The code is simple , Mainly to illustrate the problem ):

Like 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);
}
}

It's up there loadClass when , Judge the class first name( contain package Full name of ) Whether or not to java Start , If it is java Start , Then use JVM The built-in class loader loads .

Then define a simple dynamic loading class :

package zmj;
public class SayHello {
public void say() {
System.out.println("hello ping...");
}
}

In the process of execution , Will dynamically modify the printed content , Hot loading of test classes .

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 it Main During the procedure , We dynamically modify the execution content (SayHello in , from hello zmj... Change to hello ping...), The final presentation is as follows :

hello zmj...
hello zmj...
hello zmj...
hello ping...
hello ping...
hello ping...

4. summary

This article mainly introduces class loader 、 User defined class loader and class loading and unloading, etc , It also introduces with examples Java Hot replacement implementation of class .

Actually , Recently in a development project , You need to tailor features , Just want to use pf4j To do plug-in development , Learn about some class loading mechanisms , Sort it out .

Main reference 《 thorough Java virtual machine :JVM Advanced features and best practices 》.

This article is shared from Huawei cloud community 《Java Class dynamic loading and hot replacement 》, Original author :maijun .

 

Click to follow , The first time to learn about Huawei's new cloud technology ~

版权声明
本文为[Hua Weiyun]所创,转载请带上原文链接,感谢
https://javamana.com/2021/01/20210120214451140B.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云