2014-09-20 58 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(); 
    } 

以上幾行解決了這個問題。

相關問題