Javassist: javassist.CannotCompileException: by java.lang.ClassFormatError: Duplicate method name&signature in class file
Javassist: javassist.CannotCompileException: by java.lang.ClassFormatError: Duplicate method name&signature in class file
我正在使用 javassist 更改方法体。当在应用程序中定义方法时,我可以这样做。但是,当我想更改应用程序使用的 jar 文件中定义的方法时,出现以下 运行 时间错误:
javassist.CannotCompileException: by java.lang.ClassFormatError: Duplicate method name&signature in class file pk1/StringBuilder.
以下代码用于更改方法体。我正在使用日食 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;
}
我发现了问题。在第一个 运行 中,程序运行良好,并为 StringBuilder 创建了一个新的 class 文件。但是,在接下来的 运行 秒中,Eclipse 不会覆盖此 class,我得到上面的 运行 时间错误。如果我手动删除这个 class 文件,那么程序可以正常工作下一个 运行.
我从应用程序创建了一个 jar 文件,运行 它在命令行中运行良好。因此,问题在于 Eclipse 无法覆盖创建的 class 文件。
我相信我找到了原因。
假设 foobar.jar
包含 class pk1.StringBuilder
以下有效
java -cp javassist-3.7.ga.jar:foobar.jar:. JassistTiming
java -cp javassist-3.7.ga.jar:foobar.jar:. JassistTiming
检测的classStringBuilder.class
存储在子目录pk1
中,调用检测的方法
以下也有效
java -cp javassist-3.7.ga.jar:.:foobar.jar JassistTiming
但第二次执行失败,因为 class StringBuilder.class
现在首先在子目录 pk1
中找到,该子目录是已经检测过的 class,因此该方法public void buildString$impl()
已存在于此 class。
我正在使用 javassist 更改方法体。当在应用程序中定义方法时,我可以这样做。但是,当我想更改应用程序使用的 jar 文件中定义的方法时,出现以下 运行 时间错误:
javassist.CannotCompileException: by java.lang.ClassFormatError: Duplicate method name&signature in class file pk1/StringBuilder.
以下代码用于更改方法体。我正在使用日食 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;
}
我发现了问题。在第一个 运行 中,程序运行良好,并为 StringBuilder 创建了一个新的 class 文件。但是,在接下来的 运行 秒中,Eclipse 不会覆盖此 class,我得到上面的 运行 时间错误。如果我手动删除这个 class 文件,那么程序可以正常工作下一个 运行.
我从应用程序创建了一个 jar 文件,运行 它在命令行中运行良好。因此,问题在于 Eclipse 无法覆盖创建的 class 文件。
我相信我找到了原因。
假设 foobar.jar
包含 class pk1.StringBuilder
以下有效
java -cp javassist-3.7.ga.jar:foobar.jar:. JassistTiming
java -cp javassist-3.7.ga.jar:foobar.jar:. JassistTiming
检测的classStringBuilder.class
存储在子目录pk1
中,调用检测的方法
以下也有效
java -cp javassist-3.7.ga.jar:.:foobar.jar JassistTiming
但第二次执行失败,因为 class StringBuilder.class
现在首先在子目录 pk1
中找到,该子目录是已经检测过的 class,因此该方法public void buildString$impl()
已存在于此 class。