动态编译的应用场景:
可以做一个浏览器端编写java代码,上传服务器编译和运行的在线评测
系统。
服务器动态加载某些类文件进行编译。
动态编译的两种做法:
1、通过Runtime调用javac,启动新的进程去操作 。
2、通过JavaCompiler动态编译。
示例:
import java.io.*;
import java.lang.reflect.Method;
import java.net.*;
import javax.tools.*;
/*
测试Java动态编译
*/
public class 动态编译DynamicCompiler {
public static void main(String[] args) throws Exception {
//通过IO流操作,将字符串存储成一个临时文件(Hi.java),然后调用动态编译方法!
String str = "public class Hi {public static void main(String[] args){System.out.println(\"Hello\");}}";
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(
new BufferedOutputStream(
new FileOutputStream("Hi.java"))));
bw.write(str);
bw.flush();
bw.close();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int result = compiler.run(null, null, null, "Hi.java");
System.out.println(result==0?"编译成功":"编译失败");
//通过Runtime调用执行类
Runtime run = Runtime.getRuntime();
Process process = run.exec("java -cp C:/Users/kvnoe/Desktop/Jcase Hi");
InputStream in = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String info = "";
while((info=reader.readLine())!=null){
System.out.println(info);
}
//通过反射调用执行类
try {
URL[] urls = new URL[] {new URL("file:/"+"C:/Users/kvnoe/Desktop/Jcase/")};
URLClassLoader loader = new URLClassLoader(urls);
Class c = loader.loadClass("Hi");
//调用加载类的main方法
Method m = c.getMethod("main",String[].class);
m.invoke(null, (Object)new String[]{});
//由于可变参数是JDK5.0之后才有。
//m.invoke(null, (Object)new String[]{});会编译成:m.invoke(null,"aa","bb"),就发生了参数个数不匹配的问题。
//因此,必须要加上(Object)转型,避免这个问题。
//public static void main(String[] args)
} catch (Exception e) {
e.printStackTrace();
}
}
}