1. Application scenarios of bytecode technology
AOP technology, Lombok to remove duplicate code plug-ins, dynamic modification of class files, etc
Two, byte technology advantages
Java bytecode enhancement refers to modifying Java bytecode after it has been generated to enhance its functionality in a manner similar to modifying the binaries of an application. Java bytecode enhancement is mainly to reduce redundant code, improve performance, etc.
The main steps to implement bytecode enhancement are:
- 1, modify the bytecode in memory to obtain the original bytecode, and then use some tools (such as ASM, Javaasist) to modify its byte[] array, get a new byte array.
- 2. Make the modified bytecode take effect
There are two ways:
- 1) Customize ClassLoader to load the modified bytecode;
- 2) Replace the original bytecode: when the JVM loads the user’s Class, it intercepts and returns the modified bytecode; Or at runtime, the Instrumentation. RedefineClasses method to replace the original bytecode
Common bytecode manipulation class library
1, BCEL
Byte Code Engineering Library(BCEL), part of the Apache Software Foundation’s Jakarta project. BCEL is a widely used framework for Java ClassWorking that lets you drill down into the details of library operations in the JVM assembly language. BCEL has a different approach to bytecode than Javassist, where BCEL operates at the level of actual JVM instructions (BCEL has rich JVM instruction set support) while JavAssist emphasizes work at the source level.
2, ASM
Java bytecode manipulation is a lightweight Java bytecode manipulation framework that directly relates to the underlying operations and instructions of the JVM
3, CGLB
Generation of class library, based on ASM implementation
4, javassist
Java bytecode is an open source library for analyzing, editing and creating Java bytecode. Worse performance than ASM, similar to CGLIb, but simple to use. Many open source frameworks use it.
4.1 Javassist advantage
- Less overhead than reflection, high performance.
- Javassist performs better than reflection and worse than ASM
Runtime manipulation of bytecode allows us to do the following:
- Dynamically generate new classes
- Dynamically changing the structure of a class (adding/removing/modifying new properties/methods)
The outermost API of Javassist is similar to the API in JAVA’s reflection package.
It mainly consists of CtClass, CtMethod, and CtField classes. To perform the same operations as java.lang.Class, java.lang.reflect.Method, and java.lang.reflect.method. Field in the JDK reflection API.
Method of operation
- Modify the body of an existing method (insert code into the body of an existing method)
- New Method Delete method
4.2 limitations of Javassist
JDK5.0 new syntax doesn’t support (including generics, enumerations), does not support the annotations changes, but it can be addressed by the underlying javassist classes, specific reference: javassist. The bytecode. The annotation
Array initialization is not supported, such as String[]{“1″,”2”}, unless only the array has capacity 1
Inner and anonymous classes are not supported
Continue and break expressions are not supported.
Some do not support inheritance relationships. For example,
class A {}
class B extends A {}
class C extends B {} Copy the code
4.3. Create classes using Javassist
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { Class<? > clazz = Class.forName("com.test.Test0005"); Object newInstance = clazz.newInstance(); Method method = clazz.getDeclaredMethod("sum", int.class, int.class); Object invoke = method.invoke(newInstance, 1, 1); } public void sum(int a, int b) { System.out.println("sum:" + a + b); }Copy the code
public static void main(String[] args) throws CannotCompileException, NotFoundException, IOException { ClassPool pool = ClassPool.getDefault(); CtClass userClass = pool.makeclass (" com.test.entity.user "); CtField idField = CtField. Make ("private Integer ID;" , userClass); NameField = CtField. Make ("private Integer name;" , userClass); // Add the attribute userclass.addField (idField); // Add the attribute userclass.addfield (nameField); Make ("public Integer getId() {return id; }", userClass); SetIdMethod = ctmethod. make("public void setId(Integer id) {this.id = id; }", userClass); // addMethod userclass.addmethod (getIdMethod); // addMethod userclass.addmethod (setIdMethod); CtConstructor CtConstructor = new CtConstructor(new CtClass[] {ctclass.intType, CtConstructor = new CtClass[] {ctclass.intType, CtConstructor = new CtClass[] {CtClass. pool.get("java.lang.String") }, userClass); // create Body ctconstructive.setBody (" {this.id = id; this.name = name; } "); userClass.addConstructor(ctConstructor); userClass.writeFile("F:/test"); // Write the constructed class to the F:\test directory}Copy the code
4.4 Use Javassist to modify class file information
public static void main(String[] args) throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, IOException { ClassPool pool = ClassPool.getDefault(); CtClass userClass = pool.get(" com.test.user "); CtMethod m = new CtMethod(ctclass.intType, "add", new CtClass[] {ctclass.intType, ctclass.intType}, userClass); // Method permissions m.modifier (Modifier.PUBLIC); {system.out.println (\"Test003\"); return $1+$2; } "); userClass.addMethod(m); userClass.writeFile("F:/test"); Class clazz = userclass.toclass (); // Write the constructed Class to F:\test. Object obj = clazz.newInstance(); Method = clazz.getDeclaredMethod("add", int. Class, int. Class); Object result = method.invoke(obj, 200, 300); System.out.println(result); }Copy the code
Personal blog Snail