我正在使用javassist来更改方法体。在应用程序中定义方法时,我可以这样做。但是,当我想更改应用程序使用的jar文件中定义的方法时,我得到以下运行时错误:
javassist.CannotCompileException: by java.lang.ClassFormatError: Duplicate method name&signature in class file pk1/StringBuilder.
以下代码用于更改方法正文。我正在使用eclipse IDE。调用 clas.toClass(); 时会发生错误。
public class JassistTiming {
public static void main(String[] arg) {
//first parameter is name of class, and the second one is name of method
String[] argv = {"pk1.StringBuilder","buildString"};
// start by getting the class file and method
CtClass clas = ClassPool.getDefault().get(argv[0]);
// add timing interceptor to the class
addTiming(clas, argv[1]);
clas.writeFile();
System.out.println("Added timing to method " + argv[0] + "." + argv[1]);
clas.toClass(); //Run time error happens here
}
private static void addTiming(CtClass clas, String mname) throws NotFoundException, CannotCompileException {
CtMethod mold = clas.getDeclaredMethod(mname);
String nname = mname+"$impl";
mold.setName(nname);
CtMethod mnew = CtNewMethod.copy(mold, mname, clas, null);
String type = mold.getReturnType().getName();
StringBuffer body = new StringBuffer();
body.append("{\nlong start = System.currentTimeMillis();\n");
if (!"void".equals(type)) {
body.append(type + " result = ");
}
body.append(nname + "($$);\n");
body.append("System.out.println(\"Call to method " + mname +
" took \" +\n (System.currentTimeMillis()-start) + " +
"\" ms.\");\n");
if (!"void".equals(type)) {
body.append("return result;\n");
}
body.append("}");
mnew.setBody(body.toString());
clas.addMethod(mnew);
}
}
更新:StringBuilder的代码:
public class StringBuilder {
public String buildString(int length) {
String result = "";
for (int i = 0; i < length; i++) {
result += (char)(i%26 + 'a');
}
return result;
}
答案 0 :(得分:0)
我发现了问题。在第一次运行中,程序运行正常,并创建了 StringBuilder 的新类文件。但是,在下一次运行中,Eclipse不会覆盖此类,并且我得到上述运行时错误。如果我手动删除这个类文件,那么该程序适用于下一次运行。
我从应用程序创建一个jar文件并在命令行中运行它,它工作正常。因此,问题在于Eclipse无法覆盖创建的类文件。
答案 1 :(得分:0)
我相信我找到了原因。
假设foobar.jar
包含班级pk1.StringBuilder
以下工作
java -cp javassist-3.7.ga.jar:foobar.jar:. JassistTiming
java -cp javassist-3.7.ga.jar:foobar.jar:. JassistTiming
检测类StringBuilder.class
存储在子目录pk1
中,并调用检测方法。
以下工作也是如此
java -cp javassist-3.7.ga.jar:.:foobar.jar JassistTiming
但第二次执行失败,因为类StringBuilder.class
现在首先在子目录pk1
中找到,这是已经检测过的类,因此方法public void buildString$impl()
已经存在于此类中