首先定义自己的ClassLoader,可以加载磁盘上的.class文件:
1 public class MyClassLoader extends ClassLoader{ 2 private String rootDir = "."; 3 4 public MyClassLoader(String rootDir){ 5 this.rootDir = rootDir; 6 } 7 8 @Override 9 public Class<?> findClass(String name)throws ClassNotFoundException{ 10 byte[] bytes = readClassFile(name); 11 if(bytes!=null){ 12 return defineClass(name, bytes, 0, bytes.length); 13 }else{ 14 throw new ClassNotFoundException(); 15 } 16 } 17 18 private byte[] readClassFile(String name){ 19 try { 20 File file = new File(rootDir+File.separatorChar+name+".class"); 21 InputStream input = new FileInputStream(file); 22 byte[] buffer = new byte[4096]; 23 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 24 int num = 0; 25 while((num = input.read(buffer))!=-1){ 26 baos.write(buffer, 0, num); 27 } 28 input.close(); 29 return baos.toByteArray(); 30 } catch (Exception e) { 31 e.printStackTrace(); 32 } 33 return null; 34 35 } 36 }
定义自己的JavaFileObject:
1 public class MyJavaFileObject extends SimpleJavaFileObject{ 2 private String content; 3 4 protected MyJavaFileObject(String name, String content) { 5 super(URI.create("string:///"+name.replace(".", "/")+Kind.SOURCE.extension), Kind.SOURCE); 6 this.content = content; 7 } 8 9 @Override 10 public CharSequence getCharContent(boolean ignoreEncodingErrors){ 11 return content; 12 } 13 14 }
再定义自己的编译器:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 /** 2 * 自定义编译器 3 * 4 * @author rui.chen 5 * 6 */ 7 public class MyCompiler { 8 9 /** 10 * 将输入的java源代码编译为二进制字节码 11 * @param className 类名 12 * @param source 类的实现java代码 13 * @return 是否编译成功 14 */ 15 public boolean compile(String className, String source) { 16 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 17 StandardJavaFileManager fileManager = compiler.getStandardFileManager( 18 null, null, null); 19 MyJavaFileObject obj = new MyJavaFileObject(className, source); 20 CompilationTask task = compiler.getTask(null, fileManager, null, null, 21 null, Arrays.asList(obj)); 22 return task.call(); 23 } 24 25 /** 26 * 通过反射加载类及调用类中的方法 27 * @param className 类名 28 * @param methodName 方法名 29 * @param types 参数类型 30 * @param args 方法参数数组 31 * @return 方法返回值 32 */ 33 public Object invoke(String className, String methodName, Class<?>[] types, Object[] args) { 34 try { 35 ClassLoader loader = new MyClassLoader("."); 36 Class<?> clazz = loader.loadClass(className); 37 Method method = clazz.getMethod(methodName, types); 38 Object result = method.invoke(clazz.newInstance(), args); 39 return result; 40 } catch (Exception e) { 41 e.printStackTrace(); 42 } 43 return null; 44 45 } 46 }
最后上测试代码,实现一个简单的打印方法sayHello:
1 public class CompilerTest { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 MyCompiler compiler = new MyCompiler(); 8 String source = "public class SaySomething {public void saySomething(String sth){System.out.println(sth);}}"; 9 compiler.compile("SaySomething", source); 10 compiler.invoke("SaySomething", "saySomething", new Class[]{String.class}, new String[]{"hello!"}); 11 } 12 13 }
参考资料:
java深度历险——成富;