一般情況下對java源文件的編譯均是在代碼完成后使用javac編譯的,不管是使用 IDE還是直接使用命令行。這里要說(shuō)的情況是比較特別的,就是在代碼內動(dòng)態(tài)的編譯一些代碼。比如你想通過(guò)在某個(gè)目錄下通過(guò)放置一些源代碼的方式來(lái)實(shí)現對程序功能的動(dòng)態(tài)擴展,那么你的程序就需要具有一種對源代碼的編譯、加載、運行的能力,可能就需要本文介紹的3種方法。方法1:通過(guò)調用本機的javac命令來(lái)編譯。在java程序中調用javac命令可以通過(guò)調用Runtime類(lèi)的exec或是ProcessBuilder類(lèi)的start方法來(lái)完成,這兩個(gè)類(lèi)的功能基本相同,用法也比較相似,這里的例子我們就用ProcessBuilder來(lái)演示。如果是JDK1.5之前的版本請使用Runtime類(lèi)完成相同的功能。開(kāi)始之前先來(lái)點(diǎn)準備工作,將下面的類(lèi)放到 c:\mytest\src\ 目錄下,這個(gè)類(lèi)我們不會(huì )在IDE中編譯,而是由我們程序完成其編譯。保存時(shí)使用UTF-8格式??梢灾苯釉诟郊邢螺d這個(gè)類(lèi)。Java代碼 [img]http://devbbs.doit.com.cn/attachments/images/302-icon_copy.gif[/img]public class HelloWorld { public void sayHello(String in) { System.out.println("動(dòng)態(tài)編譯成功"); System.out.println("使用編譯方式:" + in); } } public class HelloWorld { public void sayHello(String in) { System.out.println("動(dòng)態(tài)編譯成功"); System.out.println("使用編譯方式:" + in); }}準備工作完成,下面就看一下我們程序的代碼,這里只列出主要代碼Java代碼 [img]http://devbbs.doit.com.cn/attachments/images/302-icon_copy.gif[/img]public class JavacCompile { private static String filePath = "c:\\mytest\\src\\HelloWorld.java"; private static String binDir = "c:\\mytest\\bin"; public static void main(String[] args) { File binOutDir = new File(binDir); if (!binOutDir.exists()) { binOutDir.mkdirs(); } // 設置javac的編譯參數,使用-encoding指定編碼方式,-d并指定編譯生成class文件目錄 ProcessBuilder pb = new ProcessBuilder("javac","-encoding", "UTF-8","-d", binDir, filePath); try { // 開(kāi)始調用javac命令編譯 final Process proc = pb.start(); // 處理進(jìn)程的輸出,避免掛死 new Thread(new Runnable() { public void run() { processStream(proc.getInputStream()); processStream(proc.getErrorStream()); } }).start(); // 等待編譯完成 proc.waitFor(); // 加載編譯好的類(lèi),并調用相應的方法 new LoaderClassByDir(binDir).execSayHello("javac"); } catch (Exception ex) { Logger.getLogger(JavacCompile.class.getName()).log(Level.SEVERE, null, ex); } } private static void processStream(InputStream stderr) { ... } } public class JavacCompile { private static String filePath = "c:\\mytest\\src\\HelloWorld.java"; private static String binDir = "c:\\mytest\\bin"; public static void main(String[] args) { File binOutDir = new File(binDir); if (!binOutDir.exists()) { binOutDir.mkdirs(); } // 設置javac的編譯參數,使用-encoding指定編碼方式,-d并指定編譯生成class文件目錄 ProcessBuilder pb = new ProcessBuilder("javac","-encoding", "UTF-8","-d", binDir, filePath); try { // 開(kāi)始調用javac命令編譯 final Process proc = pb.start(); // 處理進(jìn)程的輸出,避免掛死 new Thread(new Runnable() { public void run() { processStream(proc.getInputStream()); processStream(proc.getErrorStream()); } }).start(); // 等待編譯完成 proc.waitFor(); // 加載編譯好的類(lèi),并調用相應的方法 new LoaderClassByDir(binDir).execSayHello("javac"); } catch (Exception ex) { Logger.getLogger(JavacCompile.class.getName()).log(Level.SEVERE, null, ex); } } private static void processStream(InputStream stderr) { ... }}LoaderClassByDir類(lèi)的代碼會(huì )保含在后面的上傳的文件中,因為這里主要介紹完成程序中對java源文件的編譯,對于類(lèi)的加載和運行不多做描述,可以參考LoaderClassByDir類(lèi)中的簡(jiǎn)單實(shí)現。方法2:使用Sun的tools.jar包時(shí)的com.sun.tools.javac.Main類(lèi)完成對代碼的編譯。注意這個(gè)類(lèi)的是在tools.jar包里,tools.jar不是標準的Java庫,在使用時(shí)必須要設置這個(gè)jar的路徑,使用IDE時(shí)需要顯示的引入到編譯路徑中,不然會(huì )找不到。我們使用此類(lèi)改寫(xiě)上面的編譯類(lèi)如下:Java代碼 [img]http://devbbs.doit.com.cn/attachments/images/302-icon_copy.gif[/img]public class JavacCompile { private static String filePath = "c:\\mytest\\src\\HelloWorld.java"; private static String binDir = "c:\\mytest\\bin"; public static void main(String[] args) { File binOutDir = new File(binDir); if (!binOutDir.exists()) { binOutDir.mkdirs(); } // 將編譯參數通過(guò)數組傳遞到編譯方法中,該函數的方法和javac的參數完成一致 Main.compile(new String[]{"-encoding", "UTF-8","-d", binDir, filePath}); try { // 加載編譯好的類(lèi),并調用相應的方法 new LoaderClassByDir(binDir).execSayHello("sun tools"); } catch (Exception ex) { Logger.getLogger(JavacCompile.class.getName()).log(Level.SEVERE, null, ex); } } } public class JavacCompile { private static String filePath = "c:\\mytest\\src\\HelloWorld.java"; private static String binDir = "c:\\mytest\\bin"; public static void main(String[] args) { File binOutDir = new File(binDir); if (!binOutDir.exists()) { binOutDir.mkdirs(); } // 將編譯參數通過(guò)數組傳遞到編譯方法中,該函數的方法和javac的參數完成一致 Main.compile(new String[]{"-encoding", "UTF-8","-d", binDir, filePath}); try { // 加載編譯好的類(lèi),并調用相應的方法 new LoaderClassByDir(binDir).execSayHello("sun tools"); } catch (Exception ex) { Logger.getLogger(JavacCompile.class.getName()).log(Level.SEVERE, null, ex); } }}使用這個(gè)類(lèi)后,同樣的功能代碼變得更加簡(jiǎn)潔。方法3:使用javax.tools包從上面可以看到方法2的缺點(diǎn)就是tools.jar需要我們自行導入。而在Java SE6中為我們提供了標準的包來(lái)操作Java編譯器,這就是javax.tools包。使用這個(gè)包,我們可以不用將jar文件路徑添加到 classpath中了。 使用這個(gè)類(lèi)的方法和上面的類(lèi)很相似,我只需要將Java代碼 [img]http://devbbs.doit.com.cn/attachments/images/302-icon_copy.gif[/img]Main.compile(new String[]{"-encoding", "UTF-8","-d", binDir, filePath}); Main.compile(new String[]{"-encoding", "UTF-8","-d", binDir, filePath});替換成:Java代碼 [img]http://devbbs.doit.com.cn/attachments/images/302-icon_copy.gif[/img]// 將編譯參數通過(guò)數組傳遞到編譯方法中,該函數的方法和javac的參數完成一致 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); compiler.run(null, null, null, "-encoding", "UTF-8","-d", binDir, filePath); // 將編譯參數通過(guò)數組傳遞到編譯方法中,該函數的方法和javac的參數完成一致 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); compiler.run(null, null, null, "-encoding", "UTF-8","-d", binDir, filePath);就可以完成相應的編譯功能,這里簡(jiǎn)介一下run的使用方法:注意:使用上傳文件中的代碼做測試時(shí),為避免上次編譯的影響記得手動(dòng)刪除C:\mytest\bin下的類(lèi)文件
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請
點(diǎn)擊舉報。