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

Pay attention to wechat public number, the latest technology dry goods real-time push