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