79 动态编译与动态运行
Posted scorpicat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了79 动态编译与动态运行相关的知识,希望对你有一定的参考价值。
动态编译与动态运行
在这样的场景中:我们设计了一个网页,允许用户在网页上输入java代码,提交后获得java代码的执行结果。这个功能,无需用户安装jre或是jdk,就能获得java编译运行的结果。这个功能,就要依赖动态编译与动态运行。
这样设计:用户输入代码,提交后,通过网络流传入到我们的服务器,我们将流接受,转为对应的java文件,然后调用编译器编译它,再调用类加载器或是Runtime执行它对应的class文件,最后我们将执行后的结果,通过流返回给用户,完成功能。
那么这个过程中的:调用编译器与调用类加载器的过程,就是动态编译与动态运行的过程。
如何在程序中动态编译?
我们通过ToolProvider类获取JavaCompiler编译器工具,就可以对指定的文件进行编译。
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); int result = compiler.run(null, null, null, "c:/myjava/HelloWorld.java"); System.out.println(result==0?"编译成功":"编译失败");
需要注意的地方:run()方法前三个参数请参考本方法的api。第四个参数传入的时java文件的完整路径。方法返回的结果为0则编译成功,否则为编译失败。
如何在程序中动态运行class文件?
我们有两种方式可以动态加载class文件,它们分别是Runtime类与反射机制运行class文件对应的main方法。
Runtime类
每一个运行的程序都有一个对应的Runtime对象,我们可以通过Runtime.getRuntime()来获取它。通过这个对象,我们可以调用class文件获得一个进程(Process对象),这个进程执行不会显示在当前控制台(如果被加载的class有在控制台输出的语句的话)。但我们可以获得这个进程的标准输出流(一般值System.out,其它情况不知),可以将流导出到文件或是网络。
//动态运行 Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec("java -cp c:/myjava HelloWorld"); InputStream is = process.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String line = ""; while(null!=(line = br.readLine())) { System.out.println(line); }
需要注意的地方:exec()方法传入的是一个系统指令,这里我们传入的时“java -cp c:/myjava HelloWorld”,注意myjava与HelloWorld之间只有空格没有“/”符号,且类文件不加.class后缀。
标准输入与标准输出流
我不知道是否还存在其它标准输入输出流。
public static final InputStream in “标准”输入流。
public static final PrintStream out “标准”输出流。
InputStream is = System.in;
PrintStream ps = System.out;
反射机制加载class文件
利用反射机制我们可以更灵活的加载class文件,通过一个URL数组我们可以指定一个文件夹,然后使用URLClassLoader类获得类加载器,这个加载器可以加载指定文件夹中的任意一个类。加载的结果是得到这个class文件的Class对象(反射)。然后我们获取这个Class对象的main方法,执行main方法,技能加载这个class文件了。但是加载后似乎并没有对应的输出流...emmm
URL[] urls = new URL[] {new URL("File:/c:/myjava/")}; URLClassLoader loader = new URLClassLoader(urls); Class c = loader.loadClass("HelloWorld"); Method m = c.getMethod("main", String[].class); m.invoke(null, (Object)new String[] {});//这里要注意!
注意:在调用invoke()方法时,传入的第一个参数为null,我也不知道为什么。第二个参数为该方法的实参列表,但是这个方法的形参是数组,那么在传入实参时,务必要强转为Object类型,否则会将数组中的元素拆分作为该方法的实参。
以上是关于79 动态编译与动态运行的主要内容,如果未能解决你的问题,请参考以下文章