It is a two-step process.
a. Remove the field
b. Create a filed with same name with different type
Follow below step-by-step procedure to modify type of a field.
Step 1: Get ClassPool instance.
ClassPool classPool = ClassPool.getDefault();
Step 2: Get CtClass instance.
CtClass pointClass = classPool.get("com.sample.app.model.Point");
Step 3: Remove the field from CtClass instance.
CtField toBeDeleted = pointClass.getField("x");
pointClass.removeField(toBeDeleted);
Step 4: Create field with same with different data type.
CtField xField = new CtField(CtClass.doubleType, "x", pointClass);
xField.setModifiers(Modifier.PUBLIC);
Step 5: Add new field to the class.
pointClass.addField(xField);
Step 6: Publish modified byte code
pointClass.toClass();
Find the below working application.
Point.java
package com.sample.app.model; public class Point { public int x; public int y; }
App.java
package com.sample.app;
import java.lang.reflect.Field;
import com.sample.app.model.Point;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.Modifier;
public class App {
public static boolean set(Object object, String fieldName, Object fieldValue) {
Class<?> clazz = object.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, fieldValue);
return true;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return false;
}
@SuppressWarnings("unchecked")
public static <V> V get(Object object, String fieldName) {
Class<?> clazz = object.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return (V) field.get(object);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return null;
}
public static void main(String args[]) throws Exception {
ClassPool classPool = ClassPool.getDefault();
CtClass pointClass = classPool.get("com.sample.app.model.Point");
CtField toBeDeleted = pointClass.getField("x");
pointClass.removeField(toBeDeleted);
CtField xField = new CtField(CtClass.doubleType, "x", pointClass);
xField.setModifiers(Modifier.PUBLIC);
pointClass.addField(xField);
// Publish modified byte code
pointClass.toClass();
pointClass.writeFile("/Users/Shared/javassist");
Point point = new Point();
set(point, "x", 1.2345);
Object value = get(point, "x");
System.out.println("Value of x is " + value);
}
}
Run App.java, you will see below message in console.
Value of x is 1.2345
You can observe that Point.class file is created at /Users/Shared/javassist.
$tree /Users/Shared/javassist
/Users/Shared/javassist
└── com
└── sample
└── app
└── model
└── Point.class
4 directories, 1 file
Open Point.class in any java decompiler to see the source code.
No comments:
Post a Comment