1.动态编译

  • Java 6.0 引入了编译机制

  • 动态编译的应用场景:

    • 可以做一个浏览器端编写java代码,上传服务器编译和运行的在线评测系统

    • 服务器动态加载某些类文件进行编译

  • 动态编译的两种做法:

    • 通过Runtime调用javac,启动新的进程去操作(6.0之前,不是真正的动态编译)

      Runtime run = Runtime.getRuntime();

      Process process = run.exec("javac -cp d:/myjava/ Helloworld.java")

    • 通过JavaCompiler动态编译

  • 通过JavaCompiler动态编译

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

    int result = compiler.run(null, null, null, "f:/HelloWorld.java");

    Parameters:

    in "standard" input; use System.in if null

    out "standard" output; use System.out if null

    err "standard" error; use System.err if null

    arguments arguments to pass to the tool

栗子:

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int result = compiler.run(null, null, null, "f:/HelloWorld.java");
System.out.println(result==0?"编译成功":"编译失败");

2.动态运行编译好的类

  • 通过Runtime.getRuntime()运行启动新的进程运行
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int result = compiler.run(null, null, null, "f:/HelloWorld.java");
System.out.println(result==0?"编译成功":"编译失败");
Runtime run = Runtime.getRuntime();
Process process = run.exec("java -cp f: HelloWorld");

BufferedReader w = new BufferedReader(new InputStreamReader(process.getInputStream()));
System.out.println(w.readLine());
  • 通过反射运行编译好的类
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

public class DynamicCompile {

    public static void main(String[] args) throws IOException {

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        int result = compiler.run(null, null, null, "f:/HelloWorld.java");
        System.out.println(result==0?"编译成功":"编译失败");

        try {
            URL[] urls = new URL[]{new URL("file:/"+"f:/")};
            URLClassLoader loader = new URLClassLoader(urls);
            Class<?> c = loader.loadClass("HelloWorld");
            Method m = c.getMethod("main", String[].class);
            m.invoke(null, (Object)new String[]{});//静态方法不用谢调用的对象
            //加Object强制转换的原因
            //由于可变参数是JDK5.0之后才有 m.invoke(null, new String[]{"23","34"});
            //编译器会把它编译成m.invoke(null,"23","34");的格式,会发生参数不匹配的问题
            //带数组的参数都这样做
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}