com.jaredlin.sample.Animal.java
public class Animal {
private String name;
public String getName() {
return name;
}
public Animal setName(String name) {
this.name = name;
return this;
}
public void run() {
System.out.println("My name is "+name+",I'm running");
}
@Override
public String toString() {
return this.name;
}
}
使用jclasslib bytecode viewer 查看class文件
addField
public static void addField(){
ClassPool pool = ClassPool.getDefault();
try {
CtClass ctClass = pool.get("com.jaredlin.sample.Animal");
Utils.rename(ctClass,"AddField");
CtClass type = ClassPool.getDefault().get("java.lang.String");
CtField f = new CtField(type,"weight",ctClass);
CtField.Initializer init = CtField.Initializer.constant("3kg");
ctClass.addField(f,init);
ctClass.writeFile();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void addField2() {
ClassPool pool = ClassPool.getDefault();
try {
CtClass ctClass = pool.get("com.jaredlin.sample.Animal");
CtField ctField = CtField.make("private String weight=\"3kg\";",ctClass);
ctClass.addField(ctField);
ctClass.setName("AddField2");
ctClass.writeFile();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
修改getName返回結(jié)果為Tiger
修改前getName方法對應(yīng)的java源碼
return name;
對應(yīng)的Bytecode
其中 #2 表示獲取到 Constant Pool 中的第二項 (Bytecode中的方法getfield必須獲取的是CONSTANT_Fieldref_info) , 每行前面的紅色數(shù)字表示當(dāng)前這一行byte的起始位置 (后面修改的時候要用到 , 后面要修改的byte的index是3) .
為了使得getName方法的Bytecode改動量最小 , 需要新增一個field值為 "Tiger" 并直接替換為#2的位置 , 代碼如下 (新增tiger , 查看ConstantPool確認(rèn)tiger的序號 , 添加修改方法 ):
public static void changeReturn() {
ClassPool pool = ClassPool.getDefault();
try {
CtClass ctClass = pool.getAndRename("com.jaredlin.sample.Animal","ChangeReturn");
Utils.addStringField(ctClass,"tiger","Tiger");
//修改方法開始 (修改方法需要新增的field在ConstantPool中的序號后執(zhí)行)
CtMethod method = ctClass.getDeclaredMethod("getName");
CodeAttribute codeAttribute = method.getMethodInfo().getCodeAttribute();
CodeIterator iterator = codeAttribute.iterator();
iterator.writeByte(57, 3);//tiger在ConstantPool中的序號
//修改方法結(jié)束
ctClass.writeFile();
} catch (Exception e) {
e.printStackTrace();
}
}
參考 : http://www.cnblogs.com/sunfie/p/5154246.html