在某些情况下,我们需要动态生成java代码,通过动态编译,然后执行代码。JAVAAPI提供了相应的工具(JavaCompiler)来实现动态编译。下面我们通过一个简单的例子介绍,如何通过JavaCompiler实现java代码动态编译。
一、获取JavaCompiler
?
1
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
获取JDK提供的java编译器,如果没有提供编译器,则返回null;
二、编译
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//获取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();
|
当我们要编译的源代码中,引用了其他代码,我们需要将引用代码路径设置到-classpath中,否则会编译失败。
三、执行
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//要加载的类名
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
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
145
146
147
|
//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
|
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" );
//编译代码,返回class
Class<?> 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
|
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动态编译执行代码示例的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
原文链接:http://blog.csdn.net/zleven/article/details/54094493
相关文章
猜你喜欢
- 个人服务器网站搭建:如何选择适合自己的建站程序或框架? 2025-06-10
- 64M VPS建站:能否支持高流量网站运行? 2025-06-10
- 64M VPS建站:怎样选择合适的域名和SSL证书? 2025-06-10
- 64M VPS建站:怎样优化以提高网站加载速度? 2025-06-10
- 64M VPS建站:是否适合初学者操作和管理? 2025-06-10
TA的动态
- 2025-07-10 怎样使用阿里云的安全工具进行服务器漏洞扫描和修复?
- 2025-07-10 怎样使用命令行工具优化Linux云服务器的Ping性能?
- 2025-07-10 怎样使用Xshell连接华为云服务器,实现高效远程管理?
- 2025-07-10 怎样利用云服务器D盘搭建稳定、高效的网站托管环境?
- 2025-07-10 怎样使用阿里云的安全组功能来增强服务器防火墙的安全性?
快网idc优惠网
QQ交流群
您的支持,是我们最大的动力!
热门文章
-
2025-06-04 96
-
2025-05-25 50
-
2025-05-29 102
-
2025-05-27 70
-
2025-05-29 21
热门评论