有時候我們有這樣一個需求:將動態生成的內容進行編譯
比如說用戶在客戶端浏覽器輸入一段代碼傳到服務器,服務器拿到這段代碼進行編譯。
動態編譯的兩種做法:
(1)通過Runtime調用javac,啟動新的進程去操作它。
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("javac -cp c:/myjava/ HelloWorld.java");
(2)通過JavaCompiler動態編譯
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int result = compiler.run(null,null,null,sourceFile);
參數介紹:
第一個參數:為Java編譯器提供參數
第二個參數:得到Java編譯器的輸出信息
第三個參數:接收Java編譯器的錯誤信息
第四個參數:是一個可變數組String[],能傳入一個或多個Java文件
返回值:0表示編譯成功,非0表示編譯失敗
下面寫一個demo供參考
首先我們在d盤根目錄下建立一個myjava文件夾,在myjava文件夾中新建一個java類,名字叫HelloWorld.java
1 package com.coscon.compiler; 2 3 import javax.tools.JavaCompiler; 4 import javax.tools.ToolProvider; 5 6 public class JavaCompilerTest { 7 public static void main(String[] args) { 8 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 9 int result = compiler.run(null, null, null, "d:/myjava/HelloWorld.java"); 10 System.out.println(result==0?"編譯成功":"編譯失敗"); 11 } 12 }
控制台打印編譯成功,同時在myjava文件夾中出現.class文件。
如果我們需要動態編譯一個字符串,比如說在上面這個Java類中有一個String str = "public class Demo2{public static void main(String[] args){System.out.print(\"編譯字符串\")}}";
我們可以通過io流將上述字符串存入到一個臨時文件中,後綴名為.java,在調用JavaCompiler的run方法進行動態編譯。
動態編譯好類之後,有時候我們需要動態地去運行這些編譯好的類。
這邊也對應兩種方法:
(1)通過Runtime調用java,啟動新的進程去操作它。
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("java -cp c:/myjava/ HelloWorld");
直接運行的話控制台無法獲取打印信息。
InputStream in = process.getInputStream();
BufferedReader reader = new BufferedReader(new inputStreamReader(in));
string info = "";
while((info=reader.readLine())!=null){
System.out.println(info);
}
這樣就實現了兩個進程間的交互。
(2)通過反射運行編譯好的類
URL[] urls = new URL[]{new URL("file:/"+"d:/myjava/")};
URLClassLoader loader = new URLClassLoader(urls);
Class c = loader.loaderClass("HelloWorld");
//調用加載類的mian方法
Method m = c.getMethod("main",String[].class);
m.invoke(null,(Object)new String[]{});//調用靜態方法,可以傳null,第二個參數一定要強轉。