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");
//设置classpath
ops.add("-classpath");
ops.add(CLASS_PATH);
//获取编译任务
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it);
//执行编译任务
task.call();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
当我们要编译的源代码中,引用了其他代码,我们需要将引用代码路径设置到-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);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
四、完整代码
//ClassUtil.java
import 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 org.apache.commons.logging.Log;
import org.apache.commons.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);JavaCompiler.CompilationTask 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;}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
五、测试
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);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
测试结果
16:12:02.860 DEBUG com.even.tools.ClassUtil - Write Java Source Code to: .../classes//com/even/test/Sum.java
16:12:03.544 DEBUG com.even.tools.ClassUtil - Compile Java File:.../classes//com/even/test/Sum.java
16:12:03.545 DEBUG com.even.tools.ClassUtil - Load Class[com.even.test.Sum] by sun.misc.Launcher$AppClassLoader@73d16e93
16: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动态编译执行相关推荐
- java 动态字符串_Java动态编译执行一串字符串,类似于Javascript里的eval函数
Javascript里的eval函数能动态执行一串js脚本. 那Java里怎么做到呢. 有两种方法: 一种是使用可以执行js脚本的Java类 ScriptEngineManagerpublic sta ...
- “Java是编译执行的语言”这句话对吗?
现在让你谈谈对Java平台的理解,你是否会感觉内容过于庞大?这个问题是比较宽泛的,Java发展到现在已经不仅仅是语言这么简单了,Java平台涉及的,包括但不仅限于下面提到的这些内容: Java语言本身 ...
- JAVA 文件编译执行与虚拟机(JVM)简单介绍
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytpo3 java程序的内存分配 JAVA 文件编译执行与虚拟机(JVM)介绍 ...
- java 动态编译_老生常谈Java动态编译(必看篇)
一.动态编译简介 new创建对象是静态加载类,在编译时刻就需要加载所有可能使用到的类. 一百个类,有一个类错了,都无法编译. 通过动态加载类可以解决该问题 二.代码实例 2.1 OfficeBette ...
- java动态编译无法导包_java动态编译整个项目,解决jar包找不到问题.doc
java动态编译整个项目,解决jar包找不到问题.doc 还剩 8页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,喜欢就下载吧,价低环保! 内容要点: 64. } 65. 66. /*** ...
- java 动态编译 canino_java动态编译
在HotSpot虚拟机中,有两个技术是至关重要的,即动态编译(Dynamic compilation)和Profiling. HotSpot是如何动态编译Javad的bytecode呢?Java by ...
- JVM调优——Java动态编译过程中的内存溢出问题
由于测试环境项目每2小时内存就溢出一次, 分析问题,发现Java动态加载Class并运行那块存在内存溢出问题, 遂本地调测. 一.找到动态编译那块的代码,具体如下 /** * @MethodName ...
- java动态编译类文件并加载到内存中
如果你想在动态编译并加载了class后,能够用hibernate的数据访问接口以面向对象的方式来操作该class类,请参考这篇博文-http://www.cnblogs.com/anai/p/4270 ...
- java 动态编译_Java动态编译
概述: Java的动态编译就是在运行期直接编译.java文件,执行.class,并且能够获得相关的输入输出,甚至还能监听相关的事件. 步骤: 1.创建或自动生成.java文件 2.调用JavaComp ...
最新文章
- 企业分布式微服务云SpringCloud SpringBoot mybatis (五)路由网关(zuul)
- Spring Security源码解析(一)——认证和鉴权
- 湘苗培优|值不值?效果告诉你
- 我的DWR学习(二)
- Web安全之跨站脚本攻击(XSS)
- 马哥学习李洋个人笔记之-----正则表达式
- 长虹智慧厨房解决方案,让你AI上智慧家居生活
- 《Windows编程循序渐进》——对话框应用程序
- 分享一个自己写的基于TP的关系模型(2)
- Microsoft Office Visio 2007 简体中文专业版
- 车辆检测技术的应用分析
- cisco的ccna与华为的hcne考试培训心得
- 光纤猫上的LOS灯红色闪烁解决方法
- SQL(HIVE -HUE)剔除的三种方式
- NextDay-Java(适用软件测试)
- 官方活动|最高可免费领60天会员时长
- 计算机共享访问权限 xp,上面就是xp访问win7共享要密码的解决方法
- acr38u PHP调用,ACS ACR38U-N1智能卡读卡器驱动
- 微软输入法的使用技巧
- oracle的left join和inner join的区别
热门文章
- 后台系统可扩展性学习笔记(十)Database Partitioning
- 《dp补卡——多重背包》
- 弗林的计算机体系结构分类
- c ++明明的随机数_从列表C ++程序中随机建议电影
- java boolean例子_Java Field setBoolean()用法及代码示例
- LeetCode 128. 最长连续序列 golang
- C语言模拟实现标准库函数之strstr()
- mysql 学习笔记04 insert与update语句
- [Linux]消息队列
- 穿越火线全部服务器都显示爆满,穿越火线大区全部爆满,频道挤不进去背后的故事!...