如何删除Javassist中先前添加的代码块?

如何删除Javassist中先前添加的代码块?,java,javassist,Java,Javassist,有没有办法删除Javassist中先前添加的代码块 我正在做一个项目,通过Javassist修改.class文件。除此之外,它还向构造函数中添加了一些代码。我希望这个过程能够在同一个.class文件上反复运行,而不会产生任何副作用。然而目前,在每次运行之后,相同的代码会再次添加到构造函数中 有什么方法可以防止这种情况发生吗?如果您知道要删除的代码,您可以使用Javassist轻松地执行此操作: 在下一个示例中,这将删除包含任何“Exception”类的方法“printStackTrace”的所有

有没有办法删除Javassist中先前添加的代码块

我正在做一个项目,通过Javassist修改.class文件。除此之外,它还向构造函数中添加了一些代码。我希望这个过程能够在同一个.class文件上反复运行,而不会产生任何副作用。然而目前,在每次运行之后,相同的代码会再次添加到构造函数中


有什么方法可以防止这种情况发生吗?

如果您知道要删除的代码,您可以使用Javassist轻松地执行此操作:

在下一个示例中,这将删除包含任何“Exception”类的方法“printStackTrace”的所有行,所有神奇之处都发生在
instrument
replace
方法中

 ... 
 ClassPool cp = ClassPool.getDefault();
 try{
     CtClass ct = cp.getCtClass("com.cm.main.ConcretClass");
     CtMethod m = ct.getDeclaredMethod("testException");
     m.instrument(new ExprEditor() {
            public void edit(MethodCall m) throws CannotCompileException {
                String regexPattern = ".*Exception";
                if (m.getClassName().matches(regexPattern) && m.getMethodName().matches("printStackTrace")) {
                    m.replace(";");
                }
            }

            ;
        });
    } catch (CannotCompileException e) {
        e.printStackTrace();
    } catch (NotFoundException e) {
        e.printStackTrace();
    } catch (BadBytecode badBytecode) {
        badBytecode.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
... 
混凝土类

public class ConcretClass{

public String getName() {
    return this.name + "-Extra";
}

public void testException(){
    try {
        FileOutputStream file = new FileOutputStream("C:\\Temp\\downloads");
        file.close();
    } catch (FileNotFoundException e2) {
        e2.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
   }
 }

在为注入机制的实现而使用自定义类加载器加载类之前,不确定何时修改类?但似乎您以某种方式重用了修改后的版本。为什么不跟踪javassist修改过的类,如果该类位于已修改类的列表中,则跳过修改?与javassist解决方案相比,它更像是一种黑客行为,但它应该可以工作。是一个后期编译过程,修改.class文件并将修改后的类写入同一位置,非常类似于的绑定编译器。我想你的建议是目前最好的选择,即跟踪修改过的类,不再修改它们。我认为你最好的选择是标记已经注入注释的构造函数,如果它们已经有注释,则跳过它们。注释将使用AnnotationsAttribute通过javassist操作注入。如果你愿意,我可以用这个解决方案发布一个详细的答案。谢谢@pabrantes,这也是一个很好的建议。但为了简单起见,我将坚持跳过以前插装的类作为一个整体。我以不同的方式对大多数超类及其子类进行处理,如果改变继承层次结构,我的库将崩溃。但是我看不出一种方法,如果不使用javac编译这两个代码,那么javac将抹去我所有的注入代码。您如何跟踪插入指令的类?您仍然可以使用注释思想将类标记为all,而不是保留一个包含列表或其他内容的单独文本文件,至少在插入指令后,该类将能够自行应答。关于层次结构问题,有人也可以通过检测来改变它,但我认为这不是一个你必须担心的问题。