forked from luhaoaimama1/JavaZone
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDynamicLoader.java
More file actions
84 lines (73 loc) · 3.05 KB
/
Copy pathDynamicLoader.java
File metadata and controls
84 lines (73 loc) · 3.05 KB
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
package classload;
import javax.tools.*;
import java.io.*;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.CharBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Required JDK >= 1.6<br><br>
* This class can help you create the Java byte code dynamically through the string and load it into memory.<br><br>
*
* HOW TO:<br>
* First step. <code>Map<String, byte[]> bytecode = DynamicLoader.compile("TestClass.java", javaSrc);</code><br>
* Second step. <code>DynamicLoader.MemoryClassLoader classLoader = new DynamicLoader.MemoryClassLoader(bytecode);</code><br>
* Third step. <code>Class clazz = classLoader.loadClass("TestClass");</code><br>
* <br>
* Then just like the normal use of the call this class can be.
*/
public class DynamicLoader {
/**
* auto fill in the java-name with code, return null if cannot find the public class
* @param javaSrc source code string
* @return return the Map, the KEY means ClassName, the VALUE means bytecode.
*/
public static Map<String, byte[]> compile(String javaSrc) {
Pattern pattern = Pattern.compile("public\\s+class\\s+(\\w+)");
Matcher matcher = pattern.matcher(javaSrc);
if (matcher.find())
return compile(matcher.group(1) + ".java", javaSrc);
return null;
}
/**
* @param javaName the name of your public class,eg: <code>TestClass.java</code>
* @param javaSrc source code string
* @return return the Map, the KEY means ClassName, the VALUE means bytecode.
*/
public static Map<String, byte[]> compile(String javaName, String javaSrc) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager stdManager = compiler.getStandardFileManager(null, null, null);
try (MemoryJavaFileManager manager = new MemoryJavaFileManager(stdManager)) {
JavaFileObject javaFileObject = manager.makeStringSource(javaName, javaSrc);
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, Arrays.asList(javaFileObject));
if (task.call())
return manager.getClassBytes();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static class MemoryClassLoader extends URLClassLoader {
Map<String, byte[]> classBytes = new HashMap<String, byte[]>();
public MemoryClassLoader() {
super(new URL[0], MemoryClassLoader.class.getClassLoader());
}
public void add(Map<String, byte[]> classBytes){
this.classBytes.putAll(classBytes);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] buf = classBytes.get(name);
if (buf == null) {
return super.findClass(name);
}
classBytes.remove(name);
return defineClass(name, buf, 0, buf.length);
}
}
}