What is Javassist
This is Javassist official website Description on:
Javassist (Java programming assistant) makes Java bytecode operation simple. It is a class library for editing bytecode in Java; It enables Java programs to define a new class at run time and modify it when the JVM loads the class file. Unlike other similar bytecode editors, javassist provides two levels of APIs: source level and bytecode level. If users use source level APIs, they can edit class files without understanding the Java bytecode specification. The entire API is designed using only the vocabulary of the Java language. You can even specify the inserted bytecode in the form of source text; Javassist compiles it on the fly. On the other hand, bytecode level APIs allow users to edit class files directly like other editors.
The GitHub address of Javassist is: https://github.com/jboss-javassist/javassist
How to use
Generate new Java classes using Javassist
Here is an example to show the usage of Javassist:
This example uses IDEA as a development tool, creates a new Java project, creates a lib directory under the project root directory, and copies javassist. Java in the Lib directory Jar file and right-click - > Add as library to import the jar package. For the download of the jar package, you can click here .
Create a new class com. In IDEA test. javassist. Test and add the following code:
package com.test.javassist; import javassist.*; import java.lang.reflect.Method; public class Test { public static void main(String[] args) throws Exception { ClassPool pool = ClassPool.getDefault(); // Create a Person class CtClass clz = pool.makeClass("com.test.javassist.Person"); // Create a string type member variable named name CtField field = new CtField(pool.get("java.lang.String"), "name", clz); // Set the name member variable as a private property field.setModifiers(Modifier.PRIVATE); // Add the name member variable to the Person class clz.addField(field); // Provide setter and getter methods for the member variable name for the Person class clz.addMethod(CtNewMethod.setter("setName", field)); clz.addMethod(CtNewMethod.getter("getName", field)); // Add a parameterless constructor for the Person class CtConstructor defaultConstructor = new CtConstructor(new CtClass[]{}, clz); defaultConstructor.setBody("{name = \"\";}"); clz.addConstructor(defaultConstructor); // Add a constructor with parameters to the Person class CtConstructor paramsConstructor = new CtConstructor(new CtClass[]{pool.get("java.lang.String")}, clz); // $0 means this, $1, $2 Representation method parameters paramsConstructor.setBody("{$0.name = $1;}"); clz.addConstructor(paramsConstructor); // Create a sayHello method for the Person class CtMethod sayHello = new CtMethod(CtClass.voidType, "sayHello", new CtClass[]{}, clz); sayHello.setModifiers(Modifier.PUBLIC); sayHello.setBody("System.out.println(\"hello, this is \" + $0.name);"); clz.addMethod(sayHello); // Write the Person class to the file. If there is no parameter, it will be written to the root directory of the current project clz.writeFile(); } }
After running the above code, a person will be generated in the current directory Class file, open it with IDEA, and you can see the following source code:
The following uses reflection to verify the correctness of the Person class generated by the above code:
// Testing the Person class with reflection Class<?> aClass = Class.forName("com.test.javassist.Person"); Object personObj = aClass.newInstance(); Method setNameMethod = personObj.getClass().getDeclaredMethod("setName", String.class); setNameMethod.invoke(personObj,"zhangsan"); personObj.getClass().getDeclaredMethod("sayHello").invoke(personObj);
After executing the above code, you can see the console output as follows:
This indicates that the Person class generated earlier using Javassist is correct.
Using Javassist to modify existing Java classes
Above, we created a Person class dynamically using Javassist. If you want to modify an existing Java class, you can use the following methods. Next, take the above Person class as an example and print a line of log in the sayHello method. The code implementation is as follows:
ClassPool pool = ClassPool.getDefault(); // Get the Person class CtClass ctClass = pool.getCtClass("com.test.javassist.Person"); // Get the sayHello method of the Person class CtMethod sayHello = ctClass.getDeclaredMethod("sayHello"); // Insert a line of code at the beginning of the method sayHello.insertBefore("System.out.println(\"this log is inserted before call sayHello()\");"); // Write the file after modification, so as to check whether the modification is successful ctClass.writeFile();
After executing the above code, we can find that a new com. Com has been automatically generated in the project root directory test. javassist. Person. Class file. The decompiled source code is as follows:
You can see that Javassist successfully modified the bytecode of the Person class.
Use of Javassist in Android
Javassist can directly manipulate bytecode, so it can be used for full buried point (non perceived buried point), hot repair, etc. in Android. Subsequent blog posts will record javassist's application in android in detail.