2014-09-20 59 views
0

我已经编写了一个插件,它可以获取类文件列表(从编译Java项目产生)并运行与这些类相关的测试用例。我使用类加载器来加载类,并使用JUnitCore()来运行测试用例。下面的代码工作正常,并且在运行输入类时没有问题。ClassLoader加载以前版本的类 - Java

Class<?> clazz = Class.forName(className);  
Request request = Request.aClass(clazz); 
Result result = new JUnitCore().run(request); 

但是,在我的程序中,上面的代码应该运行上千次的类似类。为简单起见,假设我们只有一个类,第一步编译类,然后如果没有编译器错误它被复制到插件的bin目录中,然后调用我的程序并检查它是否通过所有测试用例。

在下一次迭代中,原始源代码会自动更改,然后编译它,如果没有编译器错误,则复制并再次运行测试用例。这个过程可以运行上千次以获得期望的结果。 [在某些情况下甚至是几小时]

但是,问题在于类加载器使用编译器类的第一个版本,并且在下一次迭代中它不加载新版本并仍使用前一个版本。我发现如果我在每次迭代中添加一个Thread.sleep(1000)之前复制指令,那么它可以找到正确的版本。

首先,为什么我需要暂停之前复制不是复制后?我希望文件在类加载器要加载它们之前的复制期间没有最终完成,并且类加载器使用以前的版本。但是,正如我在复制之前添加暂停时所说的那样,它可以正常工作,并在复制后添加暂停时使用以前的版本。

二,在我的程序中使用睡眠不是好主意。我的插件在最好的情况下可能需要几个小时才能找到想要的结果,如果我想在每次迭代中添加睡眠,那么需要几天才能得到结果。因此,我更喜欢没有睡眠的解决方案。请让我知道是否有人知道如何在没有Thread.sleep的情况下复制上述问题。

+0

ClassLoader实际上并不使用类的“previos”版本,它在第一次加载时使用类的第一个版本。如果班级被加载,它将不会被新的替换。你必须做一些小小的魔法才能加载新版本。这些问题已经被问到,使用搜索。 – 2014-09-20 11:49:59

+0

[Create new ClassLoader to reload Class](http://stackoverflow.com/questions/9819318/create-new-classloader-to-reload-class) – Joe 2014-09-20 11:55:08

+0

当我添加一个睡眠,然后它使用正确的版本。 – user3601784 2014-09-20 11:56:02

回答

0

我找到了解决方案。事实上,在程序改变后,我首先刷新项目然后复制文件。但是,问题在于JDT在复制之前不会重新编译和重建索引。所以我需要等待重建完成,然后再复制。这就是为什么一个Thread.sleep复制之前可以解决问题。 但是,更好的解决方案是在刷新项目时使用下面的指令。

try { 
     project.refreshLocal(IResource.DEPTH_INFINITE, null); 

     IJobManager jobManager = Job.getJobManager(); 
     jobManager.join(ResourcesPlugin.FAMILY_AUTO_BUILD, null); 
    } catch (CoreException | OperationCanceledException | InterruptedException e) { 
      e.printStackTrace(); 
    } 

以上几行解决了这个问题。

相关问题