java 動態編譯&load
有時候我們需要把一些外部資源(比如第三方jar,自己動態生成的java檔案)編譯並載入到classloader,這時我們就需要JavaCompiler 個類,jdk是從1.6開始支援此功能
網上有很多類似列子,搜尋“動態編譯”可以找到,我這裡只列出一種實現方法(按原理分好像有三種可參考:http://www.cnblogs.com/flyoung2008/archive/2011/11/14/2249017.html)
public class TestClient {
public static void main(String[] args) throws Exception {
String c ="package webservice;\n" +
"public class Hello{\n" +
"\n" +
" public static void main(String[] args) {\n" +
" System.out.println(\"初始化成功了!\");\n" +
" }\n" +
"}\n";
/**
* 先把檔案寫入磁碟
*/
String src = "/src" ;
String bin = "/bin";
File srcdir = new File(System.getProperty("user.dir") + src+"/webservice"); //java目錄
File classdir = new File(System.getProperty("user.dir") + bin+"/webservice"); //.class目錄
// 如果 \temp 不存在 就建立
if (!srcdir.exists()) {
srcdir.mkdir();
}
FileWriter writer = new FileWriter(new File(srcdir,"Hello.java"));
writer.write(c);
writer.flush();
writer.close();
/**
* 從磁碟中載入類並編譯
*/
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager javaFileManager = javaCompiler.getStandardFileManager(null, null, null);
Iterable it = javaFileManager.getJavaFileObjects(new File(srcdir,"Hello.java"));
JavaCompiler.CompilationTask task = javaCompiler.getTask(null, javaFileManager, null, null, null, it);
Boolean call = task.call();
javaFileManager.close();
System.out.println(call);
/**
* 生成URLClassLoader 載入.class檔案
*路徑為.class檔案的上級目錄
* 生成的.classs檔案包名要與loadClass(className)中className一致
* url前面要加上file://,不能直接寫檔案路徑
*/
URL url[] = new URL[]{new URL("file://D:/user/828470/workspace2/TestForJava/src")};
URLClassLoader loader = new URLClassLoader(url);
loader.loadClass("webservice.Hello").getDeclaredMethod("main",String[].class).invoke(null,new String[]{null});
Class.forName("webservice.Hello").getDeclaredMethod("main",String[].class).invoke(null,new String[]{null});
}
}
getTask()方法 jdk描述
JavaCompiler.CompilationTask getTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Iterable<String> options,
Iterable<String> classes,
Iterable<? extends JavaFileObject> compilationUnits)
使用給定元件和引數建立編譯任務的 future。該編譯可能沒有完成,正如 CompilationTask 介面中所述。
如果提供了檔案管理器,則它必須能夠處理 StandardLocation 中定義的所有位置。
引數:
out - 用於來自編譯器的其他輸出的 Writer;如果為 null,則使用 System.err
fileManager - 檔案管理器;如果為 null,則使用編譯器的標準檔案管理器
diagnosticListener - 診斷偵聽器;如果為 null,則使用編譯器的預設方法報告診斷資訊
options - 編譯器選項;null 表示沒有選項
classes - 類名稱(用於註釋處理),null 表示沒有類名稱
compilationUnits - 要編譯的編譯單元;null 表示沒有編譯單元
返回:
表示編譯的物件
丟擲:
RuntimeException - 如果在使用者提供的元件中發生不可恢復的錯誤。cause 為使用者程式碼中的錯誤。
IllegalArgumentException - 如果給定的任一編譯單元具有不同於 source 的型別
注:程式碼中的註釋部分是特別需要注意的地方,本人由於目錄沒配好浪費了很多時間,
宣告:借用“像少年啦飛馳“這位同學的文章,在此謝過
特此發誓:只為傳承,絕無他用!