Field rename
dechamps Jan 12, 2005 5:14 AMHello,
I'm trying to rename in a file C.class a Field LEAD with GOLD.
Modern alchemy !
When the field is a byte, it seems ok (Trace1) but if it's a byte[] instantiation of class C fails (Trace2).
What's is wrong? What a I have to do to sastisfy clinit that deals with arrays?
Thanks for any idea.
Dominique Dechamps
PS: FYI,the english translation of my name Dechamps is "Of Fields". Seriously!
And of course my next step will be to change byte in BigDecimal ;-)
//// The class to modify
public class C {
public final static byte LEAD=1;
//public final static byte[] LEAD={1};
}
//// The class that modify C class
import java.util.*;
import javassist.*;
import javassist.bytecode.*;
import java.lang.reflect.*;
public class FieldRename {
private static ClassPool pool = null;
private static ConstPool constPool=null;
private static CtClass clazz = null;
private static CtField doc =null;
public static void sequence1()throws NotFoundException,CannotCompileException,java.lang.Exception{//java.io.IOException,java.lang.ClassNotFoundException,java.lang.InstantiationException,java.lang.IllegalAccessException{
// Step 1
String className="C";
pool = ClassPool.getDefault();
clazz = pool.get(className);
constPool=new ConstPool(className);
renameField("LEAD","GOLD");
clazz.writeFile();
// Step 2
System.out.println("Step 2 try to instantiate "+className);
Class c=Class.forName(className);
Object o=c.newInstance();
System.out.println("Step 2 object sucessfully instantiated");
Class d=o.getClass();
Field[] f=d.getDeclaredFields();
for (int i=0;i<f.length;i++){System.out.println("Field found= "+f.toString());}
}
public static void renameField(String oldFieldName,String newFieldName)throws javassist.CannotCompileException{
ClassFile cf=clazz.getClassFile();
List l=cf.getFields();
FieldInfo fi=null;
for(int i=0;i<l.size();i++){
fi=(FieldInfo)l.get(i);
if (fi.getName().equals(oldFieldName)){
ConstPool cp=fi.getConstPool();
System.out.println("before="+oldFieldName);
cp.print();
fi.setName(newFieldName);
l.set(i,fi);
fi=(FieldInfo)l.get(i);
System.out.println("after="+fi.getName());
cp.print();
}
}
System.out.println(oldFieldName+" should be replaced with expected "+newFieldName+" is "+fi.getName());
}
public static void main(String[] args) throws Exception {
try{sequence1();}
catch (Exception e){
e.printStackTrace();
System.exit(0);
}
}
}
//// Trace 1 when LEAD is a byte
before=LEAD
1 Method #3, name&type #14
Class #15
3 Class #16
4 UTF8 "LEAD"
5 UTF8 "B"
6 UTF8 "ConstantValue"
7 Integer 1
8 UTF8 ""
9 UTF8 "()V"
10 UTF8 "Code"
11 UTF8 "LineNumberTable"
12 UTF8 "SourceFile"
13 UTF8 "C.java"
14 NameAndType #8, type #9
15 UTF8 "C"
16 UTF8 "java/lang/Object"
after=GOLD
1 Method #3, name&type #14
2 Class #15
3 Class #16
4 UTF8 "LEAD"
5 UTF8 "B"
6 UTF8 "ConstantValue"
7 Integer 1
8 UTF8 ""
9 UTF8 "()V"
10 UTF8 "Code"
11 UTF8 "LineNumberTable"
12 UTF8 "SourceFile"
13 UTF8 "C.java"
14 NameAndType #8, type #9
15 UTF8 "C"
16 UTF8 "java/lang/Object"
17 UTF8 "GOLD"
LEAD should be replaced with expected GOLD is GOLD
Step 2 try to instantiate C
Step 2 object sucessfully instantiated
Field found= public static final byte C.GOLD
//// Trace 2 when Plum is a byte[]
before=LEAD
1 Method #4, name&type #14
2 Field #3, name&type #15
3 Class #16
4 Class #17
5 UTF8 "LEAD"
6 UTF8 "[B"
7 UTF8 ""
8 UTF8 "()V"
9 UTF8 "Code"
10 UTF8 "LineNumberTable"
11 UTF8 ""
12 UTF8 "SourceFile"
13 UTF8 "C.java"
14 NameAndType #7, type #8
15 NameAndType #5, type #6
16 UTF8 "C"
17 UTF8 "java/lang/Object"
after=GOLD
1 Method #4, name&type #14
2 Field #3, name&type #15
3 Class #16
4 Class #17
5 UTF8 "LEAD"
6 UTF8 "[B"
7 UTF8 ""
8 UTF8 "()V"
9 UTF8 "Code"
10 UTF8 "LineNumberTable"
11 UTF8 ""
12 UTF8 "SourceFile"
13 UTF8 "C.java"
14 NameAndType #7, type #8
15 NameAndType #5, type #6
16 UTF8 "C"
17 UTF8 "java/lang/Object"
18 UTF8 "GOLD"
LEAD should be replaced with expected GOLD is GOLD
Step 2 try to instantiate C
Exception in thread "main" java.lang.NoSuchFieldError: LEAD
at C.(C.java:4)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at FieldRename.sequence1(FieldRename.java:21)
at FieldRename.main(FieldRename.java:52)