Search code examples
javaclassloadertestcase

ClassLoader loads previous version of classes - Java


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.


Solution

  • 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.