java动态编译&动态调用

    最近接到一个很特殊的case,用户要求自己在客户端以java Code的形式输入一些业务逻辑;我第一反应就是,用户他会写java Code吗?哎,不过面对用户的需求,我们编码人员有啥资格说不。
   实现思路:
          1.得到用户输入的java code片段
          2.把java code片段包装成一个类
          3.建临时java文件
          4.动态编译该文件
          5.得到class文件然后动态调用
          6.虚拟机退出时删除临时的java文件和编译产生的class文件
   20110602 14:13 今天发现了新的解决方案,就是使用beanshell,现在正在学习,等解决了问题再分享。嘿嘿
   下面的程序源代码实现了用户输入一段java Code,然后动态编译,最后动态调用。希望对有相同需要的人有帮助。嘿嘿
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Random;

import com.sun.tools.javac.*;

public class RuntimeCode {
	private static Main javac = new Main();
	
	public static void main(String[] args) throws Exception{
		while(true){
			BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
			System.out.print("Please enter your java code: ");
			String code = sysin.readLine();
			File returnFile = compile(code);
			if(returnFile != null){
				run(returnFile);
			}else{
				System.out.print("error hanppen");
			}
		}
	}
	
	/**
	 * call this method to create a temp .java file and compile it.
	 * @param code
	 * @return
	 * @throws IOException
	 * @throws Exception
	 */
	private synchronized static File compile(String code) throws IOException,Exception{
		File file;
		file = File.createTempFile("JavaRuntime", ".java",
				new File(System.getProperty("user.dir")));
		file.deleteOnExit();
		String filename = file.getName();
		String classname = getClassName(filename);
		PrintWriter out = new PrintWriter(new FileOutputStream(file));
		out.println("public class " + classname + "{");
		out.println("public static void main(String[] args) throws Exception{");
		out.println(code);
		out.println("}");
		out.println("}");
		out.flush();
		out.close();
		String[] args = new String[]{"-d", System.getProperty("user.dir")+"\\bin",filename};
		int status = javac.compile(args);
		switch(status){
			case 0 :
				//exit_ok
				return file;
			case 1 :
				//exit_error
				return null;
			case 2 :
				//exit_cmderr
				return null;
			case 3 :
				//exit_syserr
				return null;
			case 4 :
				//exit_abnormal
				return null;
		}
		return file;
	}
	
	/**
	 * call this method to run the compiled .class file.
	 * @param file
	 */
	private static synchronized void run(File file){
		String filename = file.getName();
	    String classname = getClassName(filename);
		File classFile = new File(file.getParent()+"\\bin", classname + ".class");
		classFile.deleteOnExit();
		try{
			Class cls = Class.forName(classname);
			Method main = cls.getMethod("main", new Class[]{String[].class});
			main.invoke(null, new Object[]{new String[0]});
		}catch(SecurityException se){
			se.printStackTrace();
		}catch(NoSuchMethodException nme){
			debug("a matching method is not found or if then name is or:" + nme.toString());
		}catch(InvocationTargetException ite){
			debug("Exception in main:" + ite.getTargetException());
		}catch(Exception e){
			debug(e.toString());
		}
	}

	/**
	 * print error message.
	 * @param msg
	 */
	private static void debug(String msg){
		System.err.println(msg);
	}
	
	/**
	 * call this method to get a class name by input .java file name.
	 * @param filename
	 * @return
	 */
	private static String getClassName(String filename){
		return filename.substring(0, filename.length()-5);
	}
	
}

猜你喜欢

转载自chenyao-cd-sc.iteye.com/blog/1064790
今日推荐