Why is there such a thing? On the one hand, it is needed by the AOP framework, and on the other hand, it increases the difficulty of software reverse engineering
The technology of dynamically generating classes is generally divided into two categories at present, one is realized by operating bytecode framework such as cglib/ Javassist, and the other is JNI method, which calls dll/so library and restores dynamically in memory. Both methods can implement hidden classes
See an example of Javassist dynamically generating classes
package com.vvvtimes; import java.lang.reflect.Modifier; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtField; import javassist.CtMethod; import javassist.CtNewMethod; public class DynamicGenerateClass { public static void main(String[] args) throws Exception { // ClassPool: container for CtClass objects ClassPool pool = ClassPool.getDefault(); // Generate a new public class Employee.java through ClassPool CtClass ctClass = pool.makeClass("com.vvvtimes.bean.Employee"); // add fields // First add the field private String ename CtField enameField = new CtField(pool.getCtClass("java.lang.String"), "ename", ctClass); enameField.setModifiers(Modifier.PRIVATE); ctClass.addField(enameField); // Next, add the field privtae int eage CtField eageField = new CtField(pool.getCtClass("int"), "eage", ctClass); eageField.setModifiers(Modifier.PRIVATE); ctClass.addField(eageField); // Next, add the field privtae int eage CtField esexField = new CtField(pool.getCtClass("int"), "esex", ctClass); esexField.setModifiers(Modifier.PRIVATE); ctClass.addField(esexField); // Add getter and setter methods for fields ename and eno ctClass.addMethod(CtNewMethod.getter("getEname", enameField)); ctClass.addMethod(CtNewMethod.setter("setEname", enameField)); ctClass.addMethod(CtNewMethod.getter("getEage", eageField)); ctClass.addMethod(CtNewMethod.setter("setEage", eageField)); ctClass.addMethod(CtNewMethod.getter("getSex", esexField)); ctClass.addMethod(CtNewMethod.setter("setSex", esexField)); // add constructor CtConstructor ctConstructor = new CtConstructor(new CtClass[] {}, ctClass); // set the function body for the constructor StringBuffer buffer = new StringBuffer(); buffer.append("{\n").append("ename=\"gsls200808\";\n").append("eage=25;\n").append("esex=1;\n}"); ctConstructor.setBody(buffer.toString()); // add the constructor to the new class ctClass.addConstructor(ctConstructor); // add custom method CtMethod ctMethod = new CtMethod(CtClass.voidType, "printInfo", new CtClass[] {}, ctClass); // set the modifier for the custom method ctMethod.setModifiers(Modifier.PUBLIC); // Set the function body for the custom method StringBuffer buffer2 = new StringBuffer(); buffer2.append("{\n").append("System.out.println(\"begin!\");\n") .append("System.out.println(\"name=\"+ename);\n").append("System.out.println(\"age=\"+eage);\n") .append("System.out.println(\"sex=\"+esex);\n").append("System.out.println(\"end!\");\n").append("}"); ctMethod.setBody(buffer2.toString()); ctClass.addMethod(ctMethod); // In order to verify the effect, the following uses reflection to execute the method printInfo Class<?> clazz = ctClass.toClass(); Object obj = clazz.newInstance(); obj.getClass().getMethod("printInfo", new Class[] {}).invoke(obj, new Object[] {}); } }
Third-party jars that need to be referenced: javassist-3.20.0-GA.jar
operation result
begin! name=gsls200808 age=25 sex=1 end!
The meaning of the code is equivalent to creating a class named com.vvvtimes.bean.Employee in memory, and calling the printInfo method for output through reflection.
The content of this class is roughly as follows, but we are dynamically generated above
package com.vvvtimes.bean; import java.io.PrintStream; public class Employee { private String ename = "gsls200808"; private int eage = 25; private int esex = 1; public String getEname() { return this.ename; } public void setEname(String paramString) { this.ename = paramString; } public int getEage() { return this.eage; } public void setEage(int paramInt) { this.eage = paramInt; } public int getSex() { return this.esex; } public void setSex(int paramInt) { this.esex = paramInt; } public void printInfo() { System.out.println("begin!"); System.out.println("name=" + this.ename); System.out.println("age=" + this.eage); System.out.println("sex=" + this.esex); System.out.println("end!"); } }
In a follow-up article we will talk about how to get the class in memory