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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/387214.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

树莓派pwm驱动好盈电调及伺服电机

本文讲述如何通过树莓派的硬件PWM控制好盈电调来驱动RC车子的前进后退&#xff0c;以及如何驱动伺服电机来控制车子转向。 1. 好盈电调简介 车子上的电调型号为&#xff1a;WP-10BLS-A-RTR&#xff0c;在好盈官网并没有搜到对应手册&#xff0c;但找到一份通用RC竞速车的电调使…

数据结构04串

第四章 串 STL&#xff1a;string http://blog.csdn.net/weixin_37289816/article/details/54716009计算机上非数值处理的对象基本上是字符串数据。 在不同类型的应用中&#xff0c;字符串具有不同的特点&#xff0c;要有效的实现字符串的处理&#xff0c;必须选用合适的存储…

CAS单点登录原理解析

CAS单点登录原理解析 SSO英文全称Single Sign On&#xff0c;单点登录。SSO是在多个应用系统中&#xff0c;用户只需要登录一次就可以访问所有相互信任的应用系统。CAS是一种基于http协议的B/S应用系统单点登录实现方案&#xff0c;认识CAS之前首先要熟悉http协议、Session与Co…

JDK1.6版添加了新的ScriptEngine类,允许用户直接执行js代码。

JDK1.6版添加了新的ScriptEngine类&#xff0c;允许用户直接执行js代码。在Java中直接调用js代码 不能调用浏览器中定义的js函数&#xff0c;会抛出异常提示ReferenceError: “alert” is not defined。[java] view plaincopypackage com.sinaapp.manjushri; import javax.sc…

数据结构05数组和广义表

第五章 数组 和 广义表 数组和广义表可以看成是线性表在下述含义上的扩展&#xff1a;表中的数据元素本身也是一个数据结构。 5.1 数组的定义 n维数组中每个元素都受着n个关系的约束&#xff0c;每个元素都有一个直接后继元素。 可以把二维数组看成是这样一个定长线性表&…

k8s的ingress使用

ingress 可以配置一个入口来提供k8s上service从外部来访问的url、负载平衡流量、终止SSL和提供基于名称的虚拟主机。 配置ingress的yaml&#xff1a; 要求域名解析无误 要求service对应的pod正常 一、test1.domain.com --> service1:8080 apiVersion: extensions/v1beta1…

JDK1.8中如何用ScriptEngine动态执行JS

JDK1.8中如何用ScriptEngine动态执行JS jdk1.6开始就提供了动态脚本语言诸如JavaScript动态的支持。这无疑是一个很好的功能&#xff0c;毕竟Java的语法不是适合成为动态语言。而JDK通过执行JavaScript脚本可以弥补这一不足。这也符合“Java虚拟机不仅仅是Java一种语言的虚拟机…

数据结构06树和二叉树

第六章 树和二叉树 6.1 树的定义和基本术语 树 Tree 是n个结点的有限集。 任意一棵非空树中&#xff1a; &#xff08;1&#xff09;有且仅有一个特定的称为根&#xff08;root&#xff09;的结点&#xff1b; &#xff08;2&#xff09;当n>1时&#xff0c;其余结点可…

2019.03.20 mvt,Django分页

MVT模式 MVT各部分的功能: M全拼为Model&#xff0c;与MVC中的M功能相同&#xff0c;负责和数据库交互&#xff0c;进行数据处理。 V全拼为View&#xff0c;与MVC中的C功能相同&#xff0c;接收请求&#xff0c;进行业务处理&#xff0c;返回响应。 T全拼为Tem…

CountDownLatch,CyclicBarrier和Semaphore

在java 1.5中&#xff0c;提供了一些非常有用的辅助类来帮助我们进行并发编程&#xff0c;比如CountDownLatch&#xff0c;CyclicBarrier和Semaphore&#xff0c;今天我们就来学习一下这三个辅助类的用法。以下是本文目录大纲&#xff1a;一.CountDownLatch用法二.CyclicBarrie…

数据结构07排序

第十章内部排序 10.1 概述 排序就是把一组数据按关键字的大小有规律地排列。经过排序的数据更易于查找。 排序前KiKj&#xff0c;且Ki在前: 排序方法是稳定的&#xff0c;若排序后Ki在前&#xff1b; 排序方法是不稳定的&#xff0c;如排序后Kj在前。 分类&#xff1a; 内…

数据结构08查找

第九章 查找 另一种在实际应用中大量使用的数据结构--查找表。 所谓查找&#xff0c;即为在一个含有众多的数据元素的查找表中找出某个“特定的”数据元素。 查找表 search table 是由同一类型的数据元素构成的集合。集合中的数据元素之间存在着完全松散的关系&#xff0c;故…

下载Centos7 64位镜像

下载Centos7 64位镜像 1.打开Centos官网 打开Centos官方网站地址&#xff1a;https://www.centos.org/&#xff0c;点击Get CentOS Now 2.点击Minimal ISO镜像 Minimal ISO镜像&#xff0c;与DVD ISO镜像的差别有很多&#xff0c;这里只说两点 1.Minimal ISO类似于Windows的纯净…

[Objective-C语言教程]结构体(17)

Objective-C数组可定义包含多个相同类型的数据项的变量类型&#xff0c;但结构体是Objective-C编程中的另一个用户定义数据类型&#xff0c;它可组合不同类型的数据项。 结构体用于表示记录&#xff0c;假设要图书馆中跟踪书籍信息。可能希望跟踪每本书的以下属性 - 标题作者学…

Scala01入门

第1章 可伸展的语言 Scala应用范围广&#xff0c;从编写脚本&#xff0c;到建立大型系统。 运行在标准Java平台上&#xff0c;与Java库无缝交互。 更能发挥力量的地方&#xff1a;建立大型系统或可重用控件的架构。 将面向对象和函数式编程加入到静态类型语言。 在Scala中&a…

架构师之路17年精选80篇

【架构必备】 《互联网架构如何实现“高并发”》4W 《TCP接入层的负载均衡、高可用、扩展性架构设计》2.2W 《配置中心架构设计演进》1.7W 《跨公网调用的大坑与架构优化》1.4W 《DNS在架构设计中的巧用》1.9W 《消息如何在网络上安全传输》1.2W 《10W定时任务&#xff0c;如何…

iphone手机型号获取

#import <sys/utsname.h> //手机型号 NSString *device [self iphoneType]; (NSString *)iphoneType { struct utsname systemInfo; uname(&systemInfo); NSString *platform [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; if…

Java网络01基本网络概念

协议 Protocol&#xff1a;明确规则 &#xff08;1&#xff09;地址格式&#xff1b; &#xff08;2&#xff09;数据如何分包&#xff1b; ... TCP/IP四层模型&#xff1a; 应用层 HTTP SMTP POP IMAP 传输层 TCP UDP 网际层 IP 主机网络层 host to host layer 数模、…

apache的产品分类说明

分类 项目名 说明 开发语言 服务器&#xff08;共20&#xff09; Apache HTTP Server全球第一HTTP服务器C/CTomcatJava的Web服务器JavaJames邮件服务器JavaSpamAssassin反垃圾邮件C/CPerlApache的Perl编程语言支持C/CTclTCL脚本语言C/CDirectory Server超级目录服务器JavaAxisW…

Java网络02基本Web概念

URI Uniform Resource Identifier 同一资源标识符 以特定语法标识一个资源的字符串 绝对URI&#xff1a;URI模式模式特有部分 scheme:scheme-specific-part scheme分为&#xff1a; data file本地文件系统 ftp http telnet urn 统一资源名 scheme-specific-part为&am…