失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Java动态编译执行

Java动态编译执行

时间:2020-02-26 00:55:50

相关推荐

Java动态编译执行

在某些情况下,我们需要动态生成java代码,通过动态编译,然后执行代码。JAVA API提供了相应的工具(JavaCompiler)来实现动态编译。下面我们通过一个简单的例子介绍,如何通过JavaCompiler实现java代码动态编译。

一、获取JavaCompiler

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

1

获取JDK提供的java编译器,如果没有提供编译器,则返回null;

二、编译

//获取java文件管理类StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);//获取java文件对象迭代器Iterable<? extends JavaFileObject> it = manager.getJavaFileObjects(files);//设置编译参数ArrayList<String> ops = new ArrayList<String>();ops.add("-Xlint:unchecked");//设置classpathops.add("-classpath");ops.add(CLASS_PATH);//获取编译任务pilationTask task = compiler.getTask(null, manager, null, ops, null, it);//执行编译任务task.call();

1234567891011121314

当我们要编译的源代码中,引用了其他代码,我们需要将引用代码路径设置到-classpath中,否则会编译失败。

三、执行

//要加载的类名String className = "xxx.xxx.xxx";//获取类加载器ClassLoader classLoader = XXX.class.getClassLoader();//加载类Class<?> cls = classLoader.loadClass(className);//调用方法名称String methodName = "execute";//方法参数类型数组Class<?>[] paramCls = {...};//获取方法Method method = cls.getDeclaredMethod(methodName , paramCls);//创建类实例Object obj = cls.newInstance();//方法参数Object[] params = {...};//调用方法Object result = method.invoke(obj, params);

12345678910111213141516171819

四、完整代码

//ClassUtil.javaimport java.io.FileWriter;import java.io.BufferedWriter;import java.io.File;import java.io.IOException;import java.util.ArrayList;import javax.tools.JavaCompiler;import javax.tools.ToolProvider;import javax.tools.JavaFileObject;import javax.tools.StandardJavaFileManager;import mons.logging.Log;import mons.logging.LogFactory;public class ClassUtil {private static final Log logger = LogFactory.getLog(ClassUtil.class);private static JavaCompiler compiler;static{compiler = ToolProvider.getSystemJavaCompiler();}/*** 获取java文件路径* @param file* @return*/private static String getFilePath(String file){int last1 = file.lastIndexOf('/');int last2 = file.lastIndexOf('\\');return file.substring(0, last1>last2?last1:last2)+File.separatorChar;}/*** 编译java文件* @param ops 编译参数* @param files 编译文件*/private static void javac(List<String> ops,String... files){StandardJavaFileManager manager = null;try{manager = compiler.getStandardFileManager(null, null, null);Iterable<? extends JavaFileObject> it = manager.getJavaFileObjects(files);pilationTask task = compiler.getTask(null, manager, null, ops, null, it);task.call();if(logger.isDebugEnabled()){for(String file:files)logger.debug("Compile Java File:" + file);}}catch(Exception e){logger.error(e);}finally{if(manager!=null){try {manager.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 生成java文件* @param file 文件名* @param source java代码* @throws Exception*/private static void writeJavaFile(String file,String source)throws Exception{if(logger.isDebugEnabled()){logger.debug("Write Java Source Code to:"+file);}BufferedWriter bw = null;try{File dir = new File(getFilePath(file));if(!dir.exists())dir.mkdirs();bw = new BufferedWriter(new FileWriter(file));bw.write(source);bw.flush();}catch(Exception e){throw e;}finally{if(bw!=null){bw.close();}}}/*** 加载类* @param name 类名* @return*/private static Class<?> load(String name){Class<?> cls = null;ClassLoader classLoader = null;try{classLoader = ClassUtil.class.getClassLoader();cls = classLoader.loadClass(name);if(logger.isDebugEnabled()){logger.debug("Load Class["+name+"] by "+classLoader);}}catch(Exception e){logger.error(e);}return cls;}/*** 编译代码并加载类* @param filePath java代码路径* @param source java代码* @param clsName 类名* @param ops 编译参数* @return*/public static Class<?> loadClass(String filePath,String source,String clsName,List<String> ops){try {writeJavaFile(CLASS_PATH+filePath,source);javac(ops,CLASS_PATH+filePath);return load(clsName);} catch (Exception e) {logger.error(e);}return null;}/*** 调用类方法* @param cls 类* @param methodName 方法名* @param paramsCls 方法参数类型* @param params 方法参数* @return*/public static Object invoke(Class<?> cls,String methodName,Class<?>[] paramsCls,Object[] params){Object result = null;try {Method method = cls.getDeclaredMethod(methodName, paramsCls);Object obj = cls.newInstance();result = method.invoke(obj, params);} catch (Exception e) {logger.error(e);}return result;}}

1234567891011121314151617181922232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811911122123124125126127128129130131132133134135136137138139140141142143144

五、测试

public class ClassUtilTest {private static final Log logger = LogFactory.getLog(ClassUtilTest.class);public static void main(String args[]){StringBuilder sb = new StringBuilder();sb.append("package com.even.test;");sb.append("import java.util.Map;\nimport java.text.DecimalFormat;\n");sb.append("public class Sum{\n");sb.append("private final DecimalFormat df = new DecimalFormat(\"#.#####\");\n");sb.append("public Double calculate(Map<String,Double> data){\n");sb.append("double d = (30*data.get(\"f1\") + 20*data.get(\"f2\") + 50*data.get(\"f3\"))/100;\n");sb.append("return Double.valueOf(df.format(d));}}\n");//设置编译参数ArrayList<String> ops = new ArrayList<String>();ops.add("-Xlint:unchecked");//编译代码,返回classClass<?> cls = ClassUtil.loadClass("/com/even/test/Sum.java",sb.toString(),"com.even.test.Sum",ops);//准备测试数据Map<String,Double> data = new HashMap<String,Double>();data.put("f1", 10.0);data.put("f2", 20.0);data.put("f3", 30.0);//执行测试方法Object result = ClassUtil.invoke(cls, "calculate", new Class[]{Map.class}, new Object[]{data});//输出结果logger.debug(data);logger.debug("(30*f1+20*f2+50*f3)/100 = "+result);}

12345678910111213141516171819222324252627

测试结果

16:12:02.860 DEBUG com.even.tools.ClassUtil - Write Java Source Code to: .../classes//com/even/test/Sum.java16:12:03.544 DEBUG com.even.tools.ClassUtil - Compile Java File:.../classes//com/even/test/Sum.java16:12:03.545 DEBUG com.even.tools.ClassUtil - Load Class[com.even.test.Sum] by sun.misc.Launcher$AppClassLoader@73d16e9316:12:03.547 DEBUG com.even.test.ClassUtilTest - {f1=10.0, f2=20.0, f3=30.0}16:12:03.547 DEBUG com.even.test.ClassUtilTest - (30*f1+20*f2+50*f3)/100 = 22.0

如果觉得《Java动态编译执行》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。