今天看啥  ›  专栏  ›  Matrix42

Java动态性之:动态编译(DynamicCompile)

Matrix42  · 掘金  ·  · 2018-01-20 10:17

Java 动态性之: 动态编译 (DynamicCompile)

in Java lang read (0)

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();
        }
    }
}
TAGGED IN



原文地址:访问原文地址
快照地址: 访问文章快照