0%

Java-动态编译

动态编译


动态编译的应用场景

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

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

动态编译的两种做法

  1. 通过Runtime调用javac,启动新的进程去操作

    1
    2
    Runtime run = Runtime.getRuntime();
    Process process = run.exe("javac -cp d:/myjava/a.java");
  2. 通过JavaComplier动态编译

1
2
3
4
5
6
7
8
9
10
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int result = compiler.run(null,null,null,"/home/zephon/桌面/a.java");
System.out.println(result==0?"编译成功":"编译失败");

//对于字符串,可通过IO流操作,将字符串存储成一个临时文件,然后调用动态编译方法
String str = "public class a{\n" +
"\tpublic static void main(String[] args){\n" +
"\t\tSystem.out.println(\"hello\");\n" +
"\t}\n" +
"}";

动态运行编译好的类

  1. 通过Runtime.getRuntime()启动新的进程运行

    1
    2
    Runtime run = Runtime.getRuntime();
    Process pro = run.exec("java -cp ./temp temp/com/Hello")
  2. 通过反射运行编译好的类

    1
    2
    3
    4
    5
    6
    7
    URL[] urls = new URL[]{new URL("file:")};
    System.out.println(urls[0]);
    URLClassLoader loader = new URLClassLoader(urls);
    Class c = loader.loadClass("Hello");
    //调用加载类的main方法
    Method m = c.getMethod("main",String[].class);
    m.invoke(null,(Object)new String[]{"aa","bb"});

动态编译代码字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 1.创建需要动态编译的代码字符串
String nr = "\r\n"; //回车
String source = "package temp.com; " + nr +
" public class Hello{" + nr +
" public static void main (String[] args){" + nr +
" System.out.println(\"HelloWorld! 1\");" + nr +
" }" + nr +
" }";
// 2.将欲动态编译的代码写入文件中 1.创建临时目录 2.写入临时文件目录
File dir = new File(System.getProperty("user.dir") + "/temp"); //临时目录
// 如果 \temp 不存在 就创建
if (!dir.exists()) {
dir.mkdir();
}
FileWriter writer = new FileWriter(new File(dir,"Hello.java"));
writer.write(source);
writer.flush();
writer.close();

// 3.取得当前系统的编译器
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
// 4.获取一个文件管理器
StandardJavaFileManager javaFileManager = javaCompiler.getStandardFileManager(null, null, null);
// 5.文件管理器根与文件连接起来
Iterable it = javaFileManager.getJavaFileObjects(new File(dir,"Hello.java"));
// 6.创建编译任务
JavaCompiler.CompilationTask task = javaCompiler.getTask(null, javaFileManager, null, Arrays.asList("-d", "./temp"), null, it);
// 7.执行编译
task.call();
javaFileManager.close();

// 8.运行程序
Runtime run = Runtime.getRuntime();
Process process = run.exec("java -cp ./temp temp/com/Hello");
InputStream in = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String info = "";
while ((info = reader.readLine()) != null) {
System.out.println(info);
}

脚本引擎执行javascrpit代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//获得脚本引擎对象
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine engine = sem.getEngineByName("nashorn");


//定义变量,会存储到引擎上下文中
engine.put("msg","hello world");
String str ="var user = {name:'张三',age:20};";

//执行脚本
engine.eval(str);
System.out.println(engine.get("msg"));

//定义函数
engine.eval("function add(a,b){var sum = a+b;return sum;}");
//执行函数
Invocable jsInvoke = (Invocable)engine;
Object result = jsInvoke.invokeFunction("add",new Object[]{2,4});
System.out.println(result);