动态编译

跟風遠走 提交于 2020-02-13 02:18:05

动态编译

1. 应用场景

​ 可以编写一个在线评测系统,浏览器端写Java代码,上传到服务器进行编译和运行

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

2. 两种做法

​ (1) 通过JavaCompiler动态编译

​ (2) 通过Runtime调用javac,启动新的进程去操作

​ 下面对方法一进行讲解

​ 假设有一个已经写好的.java文件存放在c:/myjava/

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

​ 执行过后在c:/myjava/中可以发现多出了一个HelloWorld.class文件,说明编译成功

​ 这个例子就说明了,用户在浏览器端进行输入,然后在服务器端通过String字符串等编写一个临时 文件,再通过该方法进行编译,不过在实际操作过程中,需要注意安全的处理

3. 通过Runtime.getRunTime()运行编译好的类

​ 假设程序已经编译成功,需要启动新的进程动运行

Runtime run = Runtime.getRuntime();
Process process = run.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);
}

4. 通过反射运行编译好的类

​ 在这里尤其要注意通过反射调用main()函数的问题,一定要记得转型为(Object)new String[]{},否则将会发生参数个数不匹配的问题

try {
    URL[] urls = new URL[] {new URL("file:/" + "c:/myjava/")};
    URLClassLoader loader = new URLClassLoader(urls);
    Class c = loader.loadClass("HelloWorld");
    //调用加载类的main方法
    Method m = c.getMethod("main", String[].class);
    m.invoke(null, (Object)new String[]{});
    //m.invoke(null, new String[]{"a","b"});
    //上面代码会被编译成:m.invoke(null,"a","b"),这样就发生参数个数不匹配的问题
    //因此,必须加上(Object)进行转型,避免这个问题
} catch (Exception e) {
    e.printStackTrace();
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!