【发布时间】:2014-09-21 20:37:08
【问题描述】:
我编写了一个插件,它获取类文件列表(由编译 Java 项目产生)作为输入,并运行与这些类相关的测试用例。我使用类加载器来加载类,并使用 JUnitCore() 来运行测试用例。下面的代码运行良好,输入类运行时没有问题。
Class<?> clazz = Class.forName(className);
Request request = Request.aClass(clazz);
Result result = new JUnitCore().run(request);
然而,在我的程序中,上面的代码应该为类似的类运行数千次。为简单起见,假设我们只有一个类,第一步是编译该类,然后如果没有编译器错误将其复制到插件的 bin 目录,然后调用我的程序并检查它通过了所有测试用例。
在下一次迭代中,原始源代码会自动更改,然后编译,如果没有编译器错误,则复制并再次运行测试用例。这个过程可以运行数千次以获得所需的结果。 [在某些情况下甚至几个小时]
但是,问题在于类加载器使用了编译器类的第一个版本,并且在下一次迭代中它不会加载新版本并仍然使用之前的版本。我发现如果我在每次迭代中的 copy 指令之前添加一个 Thread.sleep(1000) ,那么它可以找到正确的版本。
首先,为什么我需要在复制之前而不是复制之后暂停?我希望在类加载器想要加载它们之前,文件在复制期间可能没有最终确定,并且类加载器使用以前的版本。但是,正如我所说,当我在复制之前添加暂停时,它可以正常工作,并且当我在复制之后添加暂停时它使用以前的版本。
其次,在我的程序中使用睡眠不是一个好主意。在最好的情况下,我的插件可能会工作几个小时才能找到所需的结果,如果我想在每次迭代中添加一个睡眠,那么需要几天的时间才能得到结果。因此,我更喜欢没有睡眠的解决方案。如果有人知道如何在没有 Thread.sleep 的情况下复制上述问题,请告诉我。
【问题讨论】:
-
ClassLoader 实际上不使用“previos”版本的类,它使用第一个版本的类,当它第一次加载时。如果类被加载,它不会被新的替换。你必须做一点魔法才能加载新版本。并且已经提出过此类问题,请使用搜索。
-
当我添加睡眠时,它会使用正确的版本。
-
如果它与 Thread.sleep() 一起工作,那么您必须提供您的代码示例,以便人们可以看到它并调试以理解。仅使用您编写的文本并没有真正的帮助。
标签: java classloader testcase