对于一个项目,我们需要一种方法来运行用户脚本,这些脚本可以带有附加类的附加JAR文件。
当我想写几个测试以确保正常的脚本不会留下任何悬空时,我有什么选择?
我特别需要知道:附加的JAR中的所有类都是“卸载”吗?
注意:我不是在寻找适用于所有Java版本的100%超级防水解决方案,从1.0到7.现在,我只需要比“我不知道”更好。
答案 0 :(得分:3)
我不会尝试对此进行单元测试。相反,我将使用-XX:-TraceClassUnloading运行JVM,并查看有问题的类是否显示在跟踪输出中。
答案 1 :(得分:3)
可能最好的选择是确保加载的jar由特定的类加载器加载,然后丢弃该类加载器(在丢弃所有对象之后)。
就单元测试卸载而言,如果使用此选项,则需要扩展测试框架和自定义类加载器以获得“按需创建类加载器”标志。然后在标志打开的情况下加载类一次,丢弃类加载器,并尝试在标志关闭的情况下再次加载类。如果该类确实无法访问,则第二次尝试应该抛出一个未找到类的异常。然后,如果它们属于异常,则将单元测试包装为pass,如果在第二次加载尝试后成功击中该行,则会失败。
如果您使用的不仅仅是纯Java工具,那么可能需要考虑OSGi容器。大多数已建立的OSGi容器实现都明确地测试了类卸载。
答案 2 :(得分:2)
看起来你要测试的是软管脚本没有classloader leak。
为此,我要为WeakReference
创建ClassLoader
用于加载该JAR,然后运行该脚本,然后调用System.gc()
,之后调用assertNull(reference.get())
< / p>
答案 3 :(得分:1)
这完全取决于您允许脚本运行的方式。他们是否可以访问应用程序其余部分的类?
在Java中泄漏内存的典型方法是使用静态引用。静态引用仅在包含它的类的ClassLoader中是静态的。因此,如果您使用ClassLoader加载您的用户脚本,您自己管理(并且您应该这样做),那么只要您的类加载器本身就可以将GC内部的引用(静态或非静态)合法化。
他们可以解决这个问题的唯一方法是将一个对象的引用添加到你的一个对象中。所以你必须非常小心你公开的API。另一种方法是,如果他们在另一个ClassLoader的类中对其类进行静态引用。
我没有看到完全自动化测试的方法。但我想你可以用任何像样的探查器跟踪课程卸载。