0

I have written a plugin which gets as input a list of class files (resulting from compiling a Java project) and run test cases related to these classes. I use class loader to load classes, and use JUnitCore() to run test cases. The below code works fine and there is no problem when it runs for input classes.

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

However, in my program the above code should be run thousand of time for the similar classes. For simplicity assume we have only one class, as first step the class is compiled and then if there is not compiler error it is copied to bin directory of the plugin and then my program is called on that and check it passes all test cases.

In next iteration the original source code is changed automatically and then it is compiled and if there is no compiler error, is copied and run again test cases. This process can be run thousand of time to get the desired result. [In some cases even hours]

However, the problem is that the classloader uses the first version of the compiler class, and in the next iteration it does not load the new version and still use the previous one. I found that if I add a Thread.sleep(1000) before copy instruction in each iteration then it can find the correct version.

First, why I need a pause before copy and not after the copy? I expect maybe the file are not finalized during the copy before classloader wants to load them, and classloader uses the previous version. However, as I said when I add pause before copy then it works fine and it uses the previous version when I add pause after copy.

Second, Using sleep in my program is not good idea. My plugin in the best case might work for hours to find the desired result, and if I want to add a sleep in each iteration then it takes days to have results. Therefore, I prefer a solution without sleep. Please let me know if any one knows how can I copy with the above problem without Thread.sleep.

user3601784
  • 377
  • 1
  • 9
  • ClassLoader actually doesn't use "previos" version of class, it uses first version of class, when it was loaded first time. If class was loaded it will not be replaced with new one. You have to do a little magic to load new version. And such questions were already asked, use search. – Mykola Evpak Sep 20 '14 at 11:49
  • possible duplicate of [Create new ClassLoader to reload Class](http://stackoverflow.com/questions/9819318/create-new-classloader-to-reload-class) – Joe Sep 20 '14 at 11:55
  • When I add a sleep then it uses the correct version. – user3601784 Sep 20 '14 at 11:56
  • If it works with Thread.sleep() then you have to provide your code samples so that people may see it and debug to understand. Using only text you wrote is not really helpfull. – Mykola Evpak Sep 20 '14 at 12:04

1 Answers1

0

I found the solution. In fact, after the program is changed, I first refresh the project and then copy files. However, the problem is that the JDT does not recompile and rebuild indices before copy. So I need to wait to rebuild is finished, and then do copy. It is the reason why a Thread.sleep before copy can solve the problem. However, a better solution is to use below instructions during refreshing the project.

 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();
    }

Above lines solve the problem.

user3601784
  • 377
  • 1
  • 9