- Overview
- What is dynamic programming
- reflection
- Dynamic compilation
- Call the JavaScript engine
- Generate bytecode dynamically
- What problems does dynamic programming solve?
- How to use in Java
- How to use Javassit
- Dynamically generate a class
- Add constructor and method dynamically
- Dynamically modify the method body
- What principle
- to sum up
Overview
What is dynamic programming? What problem does dynamic programming solve? How to use it in Java? What is the principle? How to improve? (Need us to explore together, because we are also relatively dishes, generally do not go deeper than this level).
What is dynamic programming
Dynamic programming is relative to static programming. What we usually discuss more isStatic programming language, Such as Java, andDynamic programming language, Such as JavaScript. What is the obvious difference between the two? Simply put, in static programming, type checking isCompile timeDone, and type checking in dynamic programming is atRuntimeCompleted. The so-called dynamic programming is a technology that bypasses the compilation process to operate at runtime. There are several ways in Java:
reflection
This one who is engaged in Java should be relatively familiar, the principle is to obtain the type information at runtime and then do the corresponding operation.
Dynamic compilation
Dynamic compilation is from Java 6 Started to support, mainly through a JavaCompiler Interface to complete. In this way, we can directly compile an existing java file, or dynamically generate Java code in memory and dynamically compile and execute it.
Call the JavaScript engine
Java 6 Joined Script(JSR223) support. This is a scripting framework that provides methods for scripting languages to access Java internals. You can find the script engine at runtime, and then call this engine to execute the script. This scripting API allows you to provide Java support for scripting languages.
Generate bytecode dynamically
This technique works by manipulating Java bytecode in JVM Generate a new class or dynamically add elements to the already loaded class.
What problems does dynamic programming solve?
The introduction of dynamic features in static languages is mainly to solve the pain points of some usage scenarios. In fact, it can be done completely using static programming, but the price paid is relatively high, without the elegance of dynamic programming. For example, dependency injection frameworkSpringUsing reflection, whileDagger2 It uses the code generation method (APT).
E.g
1: In those scenarios where dependencies need to be dynamically confirmed:
2: Scenarios where code needs to be inserted dynamically at runtime, such as the implementation of dynamic proxies.
3: Scenario to realize related functions through configuration file
How to use in Java
Here we mainly talk about passingGenerate bytecode dynamicallyWay, other ways can find information by themselves.
There are two popular tools for manipulating java bytecode, one isASM,one isJavassit 。
ASM : Direct operation of bytecode instructions, high execution efficiency, if the user masters the Java bytecode file format and instructions, the user’s requirements are relatively high.
Javassit Provides a more advanced API, the execution efficiency is relatively poor, but does not need to master the knowledge of bytecode instructions, the user requirements are lower.
At the application level, general use recommendations are preferredJavassitIf found Javassit If it becomes the efficiency bottleneck of the entire application, you can reconsider ASM Of course, if you are developing a basic class library, or basic platform, you can still use it directly ASM Well, I believe that the ability of developers engaged in this work should be relatively high.
A picture of a foreign blog, showing the relationship of tools for processing Java bytecode.
Next, how to use Javassit To manipulate bytecode
How to use Javassit
JavassistIt is an open source class library for analyzing, editing and creating Java bytecode. It was created by Shigeru Chiba (Chiba Zi) of the Department of Mathematics and Computer Science at Tokyo Institute of Technology. It has joined the open source JBoss application server project and implements a dynamic AOP framework for JBoss by using Javassist for bytecode operations. javassist is a sub-project of jboss, its main advantage is that it is simple and fast. Directly use the form of java coding, without the need to understand the virtual machine instructions, you can dynamically change the structure of the class, or dynamically generate the class.
JavassistThe most important is ClassPool , CtClass , CtMethod as well as CtField These categories.
ClassPool: A based on HashMap Realized CtClass Object container, where the key is the class name and the value is the class CtClass Object. default ClassPool Use and bottom JVM The same class path, so in some cases, you may need to ClassPool Add classpath or class bytes.
CtClass: Represents a class, these CtClass Object can ClassPool obtain.
CtMethods: Represents the method in the class.
CtFields : Represents a field in the class.
Dynamically generate a class
The following code will generate an implementation Cloneable Interface class GenerateClass
public void DynGenerateClass() < ClassPool pool = ClassPool.getDefault(); CtClass ct = pool.makeClass("top.ss007.GenerateClass");//Create class ct.setInterfaces(new CtClass[].makeInterface("java.lang.Cloneable")>);//Let the class implement the Cloneable interface try < CtField f= new CtField(CtClass.intType,"id",ct);//Get a field of type int and name id f.setModifiers(AccessFlag.PUBLIC);//Set the field to public ct.addField(f);//Set the field to the class //Add constructor CtConstructor constructor=CtNewConstructor.make("public GeneratedClass(int pId)",ct); ct.addConstructor(constructor); //Add method CtMethod helloM=CtNewMethod.make("public void hello(String des)< System.out.println(des);>",ct); ct.addMethod(helloM); ct.writeFile();//Save the generated .class file to disk //The following code is the verification code Field[] fields = ct.toClass().getFields(); System.out.println("Attribute Name:" + fields[0].getName() + "Attribute type:" + fields[0].getType()); > catch (CannotCompileException e) < e.printStackTrace(); > catch (IOException e) < e.printStackTrace(); > catch (NotFoundException e) < e.printStackTrace(); > >
The above code will dynamically generate a .class file, we use decompilation tools, for exampleBytecode Viewer, View the generated bytecode file GenerateClass.class ,As shown below.
Add constructor and method dynamically
There are many ways to add a constructor, we use CtNewConstructor.make , He is a static method, which has a overloaded version is more convenient, as shown below. The first parameter issource text The method body of the type, the second is the class object.
CtConstructor constructor=CtNewConstructor.make("public GeneratedClass(int pId) ",ct); ct.addConstructor(constructor);
After this code is executed, the following java code will be generated, and the code snippet uses the decompilation tool JD-GUI Generated, you can see that the parameter name of the constructor has been modified to paramInt 。
public GeneratedClass(int paramInt) < this.id = paramInt; >
There are also many ways to add functions, we use CtNewMethod.make This relatively simple form
CtMethod helloM=CtNewMethod.make("public void hello(String des)< System.out.println(des);>",ct); ct.addMethod(helloM);
After this code is executed, the following java code will be generated:
public void hello(String paramString) < System.out.println(paramString); >
Dynamically modify the method body
Dynamically modifying the content of a method is the focus of our attention, for example in AOP For programming, we will use this technique to dynamically insert code into a method.
For example, we have the following class
public class Point < private int x; private int y; public Point()<> public Point(int x, int y) < this.x = x; this.y = y; > public void move(int dx, int dy) < this.x += dx; this.y += dy; > >
We have to dynamically live in memory move() Insert some code before and after the method body
public void modifyMethod() < ClassPool pool=ClassPool.getDefault(); try < CtClass ct=pool.getCtClass("top.ss007.Point"); CtMethod m=ct.getDeclaredMethod("move"); m.insertBefore("< System.out.print(\"dx:\"+$1); System.out.println(\"dy:\"+$2);>"); m.insertAfter(""); ct.writeFile(); //Call method via reflection to view the result Class pc=ct.toClass(); Method move= pc.getMethod("move",new Class[].class,int.class>); Constructor con=pc.getConstructor(new Class[].class,int.class>); move.invoke(con.newInstance(1,2),1,2); > . >
Use the decompilation tool to view the modified move Method results:
public void move(int dx, int dy) < System.out.print("dx:" + dx);System.out.println("dy:" + dy); this.x += dx; this.y += dy; Object localObject = null;//Method return value System.out.println(this.x);System.out.println(this.y); >
It can be seen that the corresponding code is indeed added to the generated bytecode file.
The output of the function is:
Javassit also has many functions, such as calling methods in methods, exception catching, type coercion, annotation related operations, etc., and it also provides bytecode level API ( Bytecode level API )。
What principle
reflection: Because the type is loaded into the virtual machine during Java execution, inRuntimeWe can get all types of information dynamically. Type information can only be obtained but not repaired.
Dynamic compilation and dynamic generation of bytecode: The two methods are relatively similar, and the principle is to use the design principle of Java. There is a virtual machine to execute bytecode, which gives us the operating space to change the bytecode here.
to sum up
Knowledge about dynamic programming is not particularly used in the usual application layer, mostly used in building frameworks. E.g Spring The framework is built using reflection, and the dynamic agents used for AOP programming mostly use byte code generation methods, such as JBoss , Spring middle AOP section. It is also good to understand this part of the knowledge in the future when you encounter related problems.Developer。