Java底层(二) - Java的动态编译

在Java的动态编译中用到了两个Java底层类,即com.sun.tools.javac.Main和Class。

用过javascript的人都知道在JS中的eval()方法特别好用,可以动态的调用函数,但是在java中我们要实现类似的功能,实现动态编译该如何实现呢?

我们应该会想到一个简单思路:建立一个临时的Temp类暂时放在文件流中,然后进行编译,然后再用java的映射获取临时类中的方法调用即可。

下面是一个例子程序:

import java.io.PrintWriter;
import java.lang.reflect.Method;

public class JavaCT {
 
 public static void main(String args[]){
  JavaCT jc = new JavaCT();
  jc.eval("liao");
 }
 
 public void eval(String str){
  //System.out.println(System.getProperty("user.dir"));
  String s = "class Temp{";
  s += "public static String call(String[] ss){";
  s += "System.out.println(\"" + str + "\");";
  s += "return \"return str\";";
  s += "}}";
  
  try{
   java.io.File f = new java.io.File("Temp.java");
   PrintWriter pw = new PrintWriter(f);
   pw.println(s);
   pw.close();
   
   //动态编译
   String[] commadline = {"-d",System.getProperty("user.dir"),"Temp.java"};
   int status = com.sun.tools.javac.Main.compile(commadline);
   if(status != 0) System.out.println("Faile !!!!!");
  }catch(Exception e){
   System.out.println("编译错误!");
  }
  
  try {
   Class<?> cls = Class.forName("Temp");
   
   //System.out.println(ClassLoader.getSystemClassLoader().getResource("Temp.java"));
   //映射call方法
   Method call = cls.getMethod("call", new Class[]{String[].class});
   //执行call方法
   System.out.println(call.invoke(null, new Object[]{new String[0]}));
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   System.out.println("运行错误!");
  }
  
 }
}

通过该例子可以知道一个类可以通过字符串创建并执行它,那么只需要把该程序稍微修改就可以变成JS中类似的eval()了。我们只需要修改Temp中的call方法即可。

你可能感兴趣的:(java,动态编译)