1. 程式人生 > >java 動態編譯&load

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 的型別

注:程式碼中的註釋部分是特別需要注意的地方,本人由於目錄沒配好浪費了很多時間,

宣告:借用“像少年啦飛馳“這位同學的文章,在此謝過
特此發誓:只為傳承,絕無他用!