2009-12-25 52 views
0

我知道我錯過了一些基本的東西。我試圖動態編譯一個類,然後在更改後重新加載它。以下代碼有效。但是,當我調用它兩次(更改.java後一次),類定義不會更新。我錯過了什麼?爲什麼我的課沒有重新加載?

File file = new File("/eraseme/Eraseme.java"); 
File[] files = new File[] {file}; 
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();   
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); 
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(files); 
CompilationTask task = compiler.getTask(null, fileManager, null, null,null,compilationUnits); 
boolean madeIt = task.call(); // works 

File classFile = new File("/eraseme/Eraseme.class"); 
URL url = classFile.toURL(); 
URL[] urls = new URL[] { url }; 
ClassLoader cl = new URLClassLoader(urls);  
Class cls = cl.loadClass("Eraseme"); 
TestApi test = (TestApi) cls.newInstance(); 
System.out.println(test.getVersion()); 
+0

的類加載器實際上沒有被莫名其妙地使用。即使我沒有爲.class輸入正確的文件名,它仍然會運行。 – 2009-12-25 18:53:19

回答

2

你缺少的是,傳遞給URLClassLoader的網址應該是被搜索到的目錄。發生了什麼事是,你要構造實際上並沒有找到.class文件,但未能找到類,並回落至具有父類加載器加載類的URLClassLoader

具體來說,嘗試修改代碼的第二位是:

File classFile = new File("/eraseme"); 
URL url = classFile.toURL(); 
URL[] urls = new URL[] { url }; 
ClassLoader cl = new URLClassLoader(urls);  
Class cls = cl.loadClass("Eraseme"); // will try to load /eraseme/Eraseme.class 
TestApi test = (TestApi) cls.newInstance(); 
System.out.println(test.getVersion()); 

請注意,如果你的類是所謂的(與包)com.mycompany.erasestuff.EraseMe,那麼類加載器會看在文件中/eraseme/com/mycompany/erasestuff/EraseMe.class

注意,當你這樣做,你不希望系統類加載器能加載EraseMe類。系統類加載器將優先,並且您的URLClassloader不會加載任何內容。 (可惜的是,當你到一個類加載器說:「加載這個類」,它第一檢查它的父類加載器是否可以加載類,那麼它會嘗試加載它本身。如果系統類加載器可以加載這個類,你我將永遠不會得到一個不同的版本)

+0

謝謝丹尼爾。仍然卡住:即使刪除類文件(始終在第一次運行時生成)也不會改變結果。我使用的是無包名(默認包),我已經改變了使用文件(「/ eraseme」),而這也正是該類是...還在更新不會改變。 – 2009-12-25 19:04:20

+0

什麼是您的系統類路徑?系統類路徑是否包含「/ eraseme」? – 2009-12-25 19:38:04

+0

啊...好點。我已經將它包含在Eclipse項目中。我已經從項目中刪除了該路徑,並且修復了這些代碼,代碼完美無缺。感謝您的幫助! – 2009-12-25 19:41:22

相關問題