动态编译-反射调用

来源:互联网 发布:硕放菜鸟网络招聘 编辑:程序博客网 时间:2024/05/21 08:56

一、动态编译

  1. JAVA6.0引入了动态编译机制。
  2. 动态编译的应用场景:
  •      可以做一个浏览器端编写java代码,上传服务器编译和运行的在线评测系统,需要进行安全检查。
  •      服务器动态加载某些类文件进行编译

二、动态编译的两种做法:

1.通过Runtime调用javac,启动新的进程去操作(jdk5.0以前)
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. Runtime run=Runtime.getRuntime();  
  2. Process process = run.exec("javac -cp e:/java/helloworld.java");  
2.通过javaCompiler动态编译(常用)
代码:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <pre name="code" class="java">        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();  
  2.         int flag = compiler.run(nullnullnull,"E:/workspace/images/TestJava.java");  
  3.         System.out.println(flag == 0 ? "编译成功" : "编译失败");  

第一个参数:为java编译器提供参数
第二个参数:得到java编译器的输出信息
第三个参数:接受编译器的错误信息
第四个参数:可变参数(是一个String数组)能传入一个或多个java源文件
返回值:0表示编译成功,非0表示编译失败

三、动态运行编译好的类

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

例如:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <pre name="code" class="java">        Runtime run = Runtime.getRuntime();  
  2.         Process process = run.exec("java -cp E:/workspace/images   TestJava");  


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


例如:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. try {  
  2.     URL[] urls = new URL[] { new URL("file:/" + "E:/workspace/images/") };  
  3.     URLClassLoader loader = new URLClassLoader(urls);  
  4.     // 通过反射调用此类  
  5.     Class clazz = loader.loadClass("TestJava");  
  6.     Method m = clazz.getMethod("main", String[].class);  
  7.     // m.invoke(null,new String[]{"aa","bb"});  
  8.     // 由于可变参数是jdk5.0之后才有,上面代码会编译成m.invoke(null,"aa","bb");会发生参数不匹配的问题  
  9.     // 因此必须加上Object 强转  
  10.     m.invoke(null, (Object) new String[] {});  
  11.   
  12. catch (Exception e) {  
  13.     e.printStackTrace();  
  14. }  
注意:反射中的可变参数


整体Demo:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class TestCompil {  
  2.     public static void main(String[] args) throws IOException {  
  3.         // 通过IO流创建一个临时文件,然后动态编译  
  4.         String strjava = "public class TestJava{public static void main(String[] args){System.out.println(\"nihao\");}}";  
  5.         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(  
  6.                 new FileOutputStream("E:/workspace/images/TestJava.java")));  
  7.         bw.write(strjava);  
  8.         bw.flush();  
  9.         bw.close();  
  10.         //动态编译  
  11.         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();  
  12.         int flag = compiler.run(nullnullnull,"E:/workspace/images/TestJava.java");  
  13.         System.out.println(flag == 0 ? "编译成功" : "编译失败");  
  14.           
  15.         //两种动态执行编译方法  
  16.         //1.通过Runtime.getRuntime();启动新的线程进行  
  17.         Runtime run = Runtime.getRuntime();  
  18.         Process process = run.exec("java -cp E:/workspace/images   TestJava");  
  19.           
  20.         InputStream is = process.getInputStream();  
  21.         BufferedReader bis = new BufferedReader(new InputStreamReader(is));  
  22.         String info = null;  
  23.         while (null != (info = bis.readLine())) {  
  24.             System.out.println(info);  
  25.         }  
  26.           
  27.         //2.通过反射动态执行  
  28.         try {  
  29.             URL[] urls = new URL[] { new URL("file:/" + "E:/workspace/images/") };  
  30.             URLClassLoader loader = new URLClassLoader(urls);  
  31.             // 通过反射调用此类  
  32.             Class clazz = loader.loadClass("TestJava");  
  33.             Method m = clazz.getMethod("main", String[].class);  
  34.             // m.invoke(null,new String[]{"aa","bb"});  
  35.             // 由于可变参数是jdk5.0之后才有,上面代码会编译成m.invoke(null,"aa","bb");会发生参数不匹配的问题  
  36.             // 因此必须加上Object 强转  
  37.             m.invoke(null, (Object) new String[] {});  
  38.   
  39.         } catch (Exception e) {  
  40.             e.printStackTrace();  
  41.         }  
  42.     }  
  43.   
  44. }  

结果:
编译成功
nihao
nihao


0 0