Javassist:重新创建一个类-先删除,还是先解冻()再修改?
我使用Javassist创建一个类。在测试套件中,当第二个测试尝试创建同一个类时,它在Javassist:重新创建一个类-先删除,还是先解冻()再修改?,java,classloader,javassist,bytecode-manipulation,Java,Classloader,Javassist,Bytecode Manipulation,我使用Javassist创建一个类。在测试套件中,当第二个测试尝试创建同一个类时,它在pool.makeClass(…)失败,因为该类已被冻结(即已通过toClass()创建) 克服这个问题的方法是什么?理想情况下,第一个测试应该以某种方式删除类-可能从类加载器卸载-但正如我所读到的,卸载操作不可靠 因此,解决方法可能是在创建代码的类中检查它是否存在,如果存在,defrost()it,删除所有成员等,然后重新创建它 还有其他想法吗 或者是否有可靠的方法通过Javassist删除该类?您无法从类加
pool.makeClass(…)
失败,因为该类已被冻结(即已通过toClass()
创建)
克服这个问题的方法是什么?理想情况下,第一个测试应该以某种方式删除类-可能从类加载器卸载-但正如我所读到的,卸载操作不可靠
因此,解决方法可能是在创建代码的类中检查它是否存在,如果存在,defrost()
it,删除所有成员等,然后重新创建它
还有其他想法吗
或者是否有可靠的方法通过Javassist删除该类?您无法从
类加载器
卸载单个类。如果某个类及其类加载器
无法访问,则可能会卸载该类,但由于每个类都引用其加载器,这意味着该加载器加载的所有类都必须无法访问也是
但是您可以使用不同的
类加载器(重新)创建该类然后。如果在测试用例中执行的代码在堆中没有留下任何引用,则测试后可能会收集类加载器及其类。我遇到同样的问题,我通过这种方式解决了它,可能无法应用于您的测试用例:
使CtClass成为类的私有静态变量
创建一个方法,检查是否已生成CtClass。
如果未生成CtClass,则调用生成它的方法,否则返回该CtClass
让你所有的测试都使用新方法
因此,如果您有N个测试,只有第一个会尝试构建CtClass,其余的会有静态CtClass变量。从类加载器
卸载并不不可靠-这是不可能的。如果类及其类加载器
变得不可访问,则可能会卸载该类,但因为每个类都引用其加载器t意味着此加载程序加载的所有类也必须无法访问。但是您可以使用不同的ClassLoader
(重新)创建该类。在形式上,它是一个具有相同名称(可能是相同字节码)的不同类那么。这似乎就是答案……如果你这么说,我会接受。好的,但是如果第二个类加载器中加载的类引用了第一个类加载器的另一个类,那么我们是否也应该将所有引用类型添加到第二个类加载器中?@ППа:这取决于几个因素。由类加载器定义的类可能有reference如果C1将相关的类加载请求委托给C2,则将这些类解析为另一个ClassLoader
C2定义的运行时类型。如果C2是C1的父加载程序,则这是标准行为。但这意味着C2中的这些类保持不变,C2保持可访问,并且在EC1正在使用中。因此,如果您想同时修改多个相关类,则必须在新的类加载器中重新定义所有相关类。如果新类的实例打算在需要超类或接口类型的地方替换旧类,则必须将该特定基类型或接口解析为同一运行时t键入以允许插入替换。