Strange dance mobile technology
Javassist is a library for working with Java bytecode. Java bytecode is stored in a class file in binary form. Each class file contains a Java class or interface.
Class files can be represented by the Javassist.ctClass class. The CtClass object is used to process class files. Here is a simple example of a Rectangle with two classes that are unrelated to each other. Let’s modify Rectangle to make its parent program Point.
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("com.democome.Rectangle");
cc.setSuperclass(pool.get("com.democome.Point"));
cc.writeFile();
Copy the code
Rectangle.java
public class Rectangle {
private int width;
private int height;
}
Copy the code
Point.java
public class Point {}Copy the code
After running, the decompiler can see that the inheritance relationship has changed:
The above code first gets a ClassPool. ClassPool is the container for CtClass. It reads the class file to construct the CtClass object and records it. To modify calSS, first get a CtClass object from the ClassPool via get().
ClassPool has a Hashtable to store ctClasses, and the key is the class name. The ClassPool get() method returns the class if it can find it, otherwise it creates a CtClass object and returns it in the Hashtable.
private Hashtable cflow = null;
The CtClass object modifies the class file and calls writeFile() to write the file. Javassist also provides a way to get the modified bytecode directly:
byte[] b = cc.toBytecode();
Copy the code
You can also load the class directly:
Class clazz = cc.toClass();
Copy the code
Define a class
Define a class that calls the makeClass() method of the ClassPool.
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass("Point");
Copy the code
The above code defines a class Point. You can create a method with CtNewMethod and add it to Point using the addMethod() method in CtClass.
cc.addMethod(CtNewMethod.make("public void hello(){System.out.print(\"hello\"); }", cc));
cc.writeFile();
Copy the code
If you want to create a new interface, you can use the makeInterface() method in ClassPool. AbstractMethod () in CtNewMethod can be used to create member methods in an interface.
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeInterface("Point");
cc.addMethod(CtNewMethod.abstractMethod(CtClass.voidType, "hello".null.null, cc));
cc.writeFile();
Copy the code
Freeze class
If a CtClass object is converted to a class file by writeFile(), toClass(), or toBytecode(), Javassist freezes the CtClass object. Further modifications to the CtClass object are not allowed. This is to warn developers when they try to modify loaded class files, because the JVM does not allow classes to be reloaded.
Frozen CTClasses can be thawed to allow class definitions to be modified. For example,
After thawing, it can be modified as follows:
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("com.democome.Rectangle");
cc.writeFile();
cc.defrost();
cc.setSuperclass(pool.get("com.democome.Point"));
Copy the code
If clasool. DoPruning is set to true, Javassist prune the data structures contained in the CtClass object when Javassist freezes the object. Clipped CtClass objects cannot be defrosted again. The default value of classpool. doPruning is false. To disallow pruning of a particular CtClass, you must call stopPruning() on that object first:
Class search path
Classpool.getdefault () returns the ClassPool in the same class search path as the JVM. If the program is running on a Web application server such as JBoss and Tomcat, ClassPool may not be able to find the user classes because such a Web application server uses multiple class loaders as well as system class loaders. In this case, the other classpath must be registered in the ClassPool.
pool.insertClassPath(new ClassClassPath(this.getClass()));
Copy the code
The above code registers the classpath of the class used to load the referenced object. You can use any Class object as a parameter instead of this.getClass(). Used to load the classpath of the Class represented by this Class.
You can also register a directory as a class search path. For example, the following code adds the directory /usr/local/javalib to the search path:
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath("/usr/local/javalib");
Copy the code
The search path can also be a URL:
ClassPool pool = ClassPool.getDefault();
ClassPath cp = new URLClassPath("www.javassist.org".80."/java/"."org.javassist.");
pool.insertClassPath(cp);
Copy the code
The above code will add “www.javassist.org:80/java/” to class search…
http://www.javassist.org:80/java/org/javassist/test/Main.class
Copy the code
You can also use ByteArrayClassPath to supply a byte array directly to the ClassPool object and construct a CtClass object from that array. Such as:
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("com.democome.Rectangle");
byte[] b = cc.toBytecode();
String name = "Rectangle";
cp.insertClassPath(new ByteArrayClassPath(name, b));
CtClass cc2 = cp.get(name);
Copy the code
If you don’t know the fully qualified name of the class, you can use makeClass() in your ClassPool:
ClassPool cp = ClassPool.getDefault();
InputStream ins = an input stream for reading a class file;
CtClass cc = cp.makeClass(ins);
Copy the code
Such as:
ClassPool cp = ClassPool.getDefault();
InputStream ins = new FileInputStream(
"/Users/yangpeng/Documents/workspace/javassist/Javassist/com/democome/Rectangle.class");
CtClass cc = cp.makeClass(ins);
System.out.println(cc.getName());
Copy the code
The print result is as follows:
com.democome.Rectangle
Copy the code