Spring Loaded Code Hot Update Practice and Principle Analysis | JD Cloud Technical Team

1 Introduction

Pain scenarios for developers in coding efficiency and rapid iteration include:

  1. After modifying the code, the application needs to be restarted frequently, resulting in low development efficiency;

  2. During real-time debugging, the results of code modification cannot be seen immediately;

  3. In large-scale projects, the time cost of restarting is relatively high.

In response to these problems, this article will discuss in depth how to use Spring Loaded hot update technology to improve development efficiency and reduce compilation and restart time. Analyze the hot update principle of Spring Loaded, as well as the operations and precautions required in the actual application process.

2. Framework introduction

Spring Loaded is a JVM agent for reloading class file changes whilst a JVM is running. It transforms classes at loadtime to make them amenable to later reloading. Unlike 'hot code replace' which only allows simple changes once a JVM is running (e.g. changes to method bodies), Spring Loaded allows you to add/modify/delete methods/fields/constructors. The annotations on types/methods/fields/constructors can also be modified and it is possible to add/remove/change values in enum types.

Spring Loaded is a JVM agent that reloads changes to class files while the JVM is running. It transforms classes on load so they can be reloaded later. Unlike "hot code replacement" which only allows simple changes (such as changing method bodies) while the JVM is running, Spring Loaded allows you to add/modify/remove methods/fields/constructors. Annotations on types/methods/fields/constructors can also be modified, and values ​​in enum types can be added/removed/changed.

3. How to use

3.1 Download the Agent plug-in

https://repo1.maven.org/maven2/org/springframework/springloaded/1.2.8.RELEASE/springloaded-1.2.8.RELEASE.jar

3.2 Introducing the Agent plug-in

Add the following parameters to the jvm startup command

-javaagent:/Users/you/runtime/springloaded-1.2.8.RELEASE.jar -noverify

3.3 Modify and recompile

Execute the Build->Recompile command after modifying the code, you can see that after the class reloaded is completed, the running logic of the program has changed

4. Principle analysis

4.1 Code compilation analysis

First look at a piece of source code, which is an RpcService class, which defines the target field, targetStatic static field and say method, and now we compile it.

public class RpcService {
    private String target = "rpc";
    private static String targetStatic = "rpc static";
    public String say() {
        return "RpcService say hello SpringLoaded" + target;
    }
}

After SpringLoaded compiles the class, some tracking record fields are added, and method interception judgment is added.

public static ReloadableType r$type = TypeRegistry.getReloadableType(0, 1);

public transient ISMgr r$fields;

public static final SSMgr r$sfields;

public String hello() {
    if (r$type.changed(0) == 1) {
        return r$type.fetchLatest()).say(this);
    }
    String targetNew = TypeRegistry.instanceFieldInterceptionRequired(1, "target") ? (String)r$get(this, "target") : this.target;
    return "RpcService say hello SpringLoaded" + targetNew;
}

We can use functions such as getDeclaredField and getDeclaredMethod to obtain class members and method information at runtime when the code is running. At this time, we can see that the enhanced class has the following fields and methods.

In the compiled code, we can see that the RpcService class contains some new fields and methods, which are added by the Spring Loaded framework.

• r$type is a static variable whose type is ReloadableType. This field is used to indicate the overloadable type of the current class, which contains the latest bytecode and other related information of the current class.

  • The r$get and r$set methods are used to obtain the value of the instance field, and handle the interception and replacement of the field.
  • The ___clinit___ method is the method used to execute the static initialization block of the class.
  • The init () method is the method used to handle the constructor of the class.
  • A code fragment is added in the say() method to determine whether the class has changed, and if so, call the say() method in the latest overloadable type to obtain the result. Otherwise, continue to execute the original method body. In the method body, a code fragment is also added to determine whether the local variable needs to be intercepted. If so, use the r$get() method to obtain the value of the non-static variable traget, and replace the original variable value with it.

4.2 Analysis of running process

1. When the application starts, Spring Loaded looks for all classes in the target class path, and loads these classes using a custom class loader in ClassPreProcessor, and saves them in TypeRegistry after redefinition for caching, change comparison and dependency maintain.

2. Register a file change listener FileChangeListener. When a class file is modified, Spring Loaded will detect the change and reload the class file.

3. When a class is reloaded, Spring Loaded will try to compare the signature and inheritance relationship of the class. If the new class definition is compatible with the previous class definition, Spring Loaded will update the object reference in the application to point to new class definition.

5. Summary

Spring-loaded uses Java's Instrumentation API to specify the Agent when the JVM starts, enabling it to intercept before the target class is loaded, and parse the bytecode of the target class into an abstract syntax tree (AST) through the ASM library, and then perform AST Revise. The modified content includes adding, deleting, replacing methods, modifying method bodies, adding fields, etc., finally replacing the target class, changing its logic, and realizing hot update of the code.

6. Extended content

  • Jrebel can also implement a similar hot update function, and it is more efficient and stable. jrebel official website
  • Spring-boot-devtools can also improve development speed, but its solution is more like a hot restart. Principle of Spring Boot Devtools Restarter
  • How to implement a hot update function by yourself? The ideas are similar, and the implementations have their own advantages. How to implement a hot load by yourself? How to define your own class loader?

Author: JD Retail Cheng Xiao

Source: JD Cloud Developer Community

Graduates of the National People’s University stole the information of all students in the school to build a beauty scoring website, and have been criminally detained. The new Windows version of QQ based on the NT architecture is officially released. The United States will restrict China’s use of Amazon, Microsoft and other cloud services that provide training AI models . Open source projects announced to stop function development LeaferJS , the highest-paid technical position in 2023, released: Visual Studio Code 1.80, an open source and powerful 2D graphics library , supports terminal image functions . The number of Threads registrations has exceeded 30 million. "Change" deepin adopts Asahi Linux to adapt to Apple M1 database ranking in July: Oracle surges, opening up the score again
{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/u/4090830/blog/10086508