复制代码
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175package com.example.demo.dimension; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import java.util.Stack; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; /** * @ClassName: CompilerTest * @Description: JAVA源文件动态编译 * @date: 2018年7月16日 上午9:45:32 * */ public class CompilerTest { public static void main(String[] args) throws Exception { String classPath = "G:/deleted/apktool/dynamicClass" ; System.out.println( calculate("1.0+1.0",classPath)); } /** * @Title: testHello * @Description: 测试动态编译java文件 * @param: @param classPath * @return: void * @throws */ public static void testHello(String classPath){ String className = "Main" ; String source = "public class "+className+" { public static void main(String[] args) {System.out.println("Hello World!");} }"; boolean isSuccess = complie(source,className,classPath) ; System.out.println( "Complie successfully:"+isSuccess ); } /** * @Title: calculate * @Description: 测试动态编译并且加载类并执行对应方法 * @param: @param expr * @param: @param classPath * @param: @return * @param: @throws Exception * @return: double * @throws */ private static double calculate(String expr,String classPath) throws Exception { String className = "Main"; String methodName = "calculate"; String source = "public class " + className + " { public static double " + methodName + "() { return " + expr + "; } }"; // 省略动态编译Java源代码的相关代码,参见上一节 boolean result = complie(source,className, classPath); if (result) { loadClass( new File(classPath) ); ClassLoader loader = CompilerTest.class.getClassLoader(); try { Class<?> clazz = loader.loadClass(className); Method method = clazz.getMethod(methodName, new Class<?>[] {}); Object value = method.invoke(null, new Object[] {}); return (Double) value; } catch (Exception e) { throw new Exception("内部错误。",e); } } else { throw new Exception("错误的表达式。"); } } /** * @Title: complie * @Description: 动态编译java类成成class文件放入指定目录 * @param: @param expr * @param: @param classPath * @param: @return * @param: @throws Exception * @throws */ public static boolean complie(String source,String className,String classPath){ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); StringSourceJavaObject sourceObject = null; try { Iterable<String> options = Arrays.asList("-d", classPath); sourceObject = new CompilerTest.StringSourceJavaObject(className, source); Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(sourceObject); CompilationTask task = compiler.getTask(null, fileManager, null, options, null, fileObjects); boolean result = task.call(); return result ; } catch (URISyntaxException e) { e.printStackTrace(); } return false ; } private static class StringSourceJavaObject extends SimpleJavaFileObject { private String content = null; public StringSourceJavaObject(String name, String content) throws URISyntaxException { super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); this.content = content; } public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return content; } } /** * @Title: loadClass * @Description: 动态加载class文件 * @param: @param clazzPath * @param: @throws Exception * @return: void * @throws */ public static void loadClass(File clazzPath) throws Exception{ // 设置class文件所在根路径 // 例如/usr/java/classes下有一个test.App类,则/usr/java/classes即这个类的根路径,而.class文件的实际位置是/usr/java/classes/test/App.class // File clazzPath = new File(class文件所在根路径); // 记录加载.class文件的数量 int clazzCount = 0; //only handle the folder if( clazzPath.isFile() ){ clazzPath = clazzPath.getParentFile() ; } if (clazzPath.exists() && clazzPath.isDirectory()) { // 获取路径长度 int clazzPathLen = clazzPath.getAbsolutePath().length() + 1; Stack<File> stack = new Stack<>(); stack.push(clazzPath); // 遍历类路径 while (stack.isEmpty() == false) { File path = stack.pop(); File[] classFiles = path.listFiles(new FileFilter() { public boolean accept(File pathname) { return pathname.isDirectory() || pathname.getName().endsWith(".class"); } }); for (File subFile : classFiles) { if (subFile.isDirectory()) { stack.push(subFile); } else { if (clazzCount++ == 0) { Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); boolean accessible = method.isAccessible(); try { if (accessible == false) { method.setAccessible(true); } // 设置类加载器 URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); // 将当前类路径加入到类加载器中 method.invoke(classLoader, clazzPath.toURI().toURL()); } finally { method.setAccessible(accessible); } } // 文件名称 String className = subFile.getAbsolutePath(); className = className.substring(clazzPathLen, className.length() - 6); className = className.replace(File.separatorChar, '.'); // 加载Class类 Class.forName(className); System.out.println( String.format( "读取应用程序类文件[class=%s]", className) ); } } } } } }
参考:
动态加载jar和class文件 https://blog.csdn.net/mousebaby808/article/details/31788325
JAVA源文件动态编译 https://blog.csdn.net/m1993619/article/details/78734682
最后
以上就是背后吐司最近收集整理的关于Java类文件动态编译并执行方法的全部内容,更多相关Java类文件动态编译并执行方法内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复