Java动态编译执行代码示例

2025-05-29 0 64

在某些情况下,我们需要动态生成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

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 Java动态编译执行代码示例 https://www.kuaiidc.com/113101.html

相关文章

发表评论
暂无评论