需求:实现在网页上编辑java文件,然后动态编译执行。
用到了 URLClassLoader、ClassFileManager、JavaCompiler
直接上代码
自定义类加载器 DynamicClassLoader
import java.net.URLClassLoader;
import java.net.URL;
/**
* 自定义类加载器
* 定义findClass和loadClass方法
*/
public class DynamicClassLoader extends URLClassLoader {
// 指定类加载器
public DynamicClassLoader(ClassLoader parent) {
super(new URL[0], parent);
}
public Class findClassByClassName(String className) throws ClassNotFoundException {
return this.findClass(className);
}
public Class loadClass(String fullName, JavaClassObject jco) {
byte[] classData = jco.getBytes();
return this.defineClass(fullName, classData, 0, classData.length);
}
}
类加载器 JavaClassObject
import javax.tools.SimpleJavaFileObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
/**
* 将输出流交给JavaCompiler,最后JavaCompiler将编译后的class文件写入输出流中
*/
public class JavaClassObject extends SimpleJavaFileObject {
/**
* 定义一个输出流,用于装载JavaCompiler编译后的Class文件
*/
protected final ByteArrayOutputStream bos = new ByteArrayOutputStream();
/**
* 调用父类构造器
* @param name
* @param kind
*/
public JavaClassObject(String name, Kind kind) {
super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind);
}
/**
* 获取输出流为byte[]数组
* @return
*/
public byte[] getBytes() {
return bos.toByteArray();
}
/**
* 重写openOutputStream,将我们的输出流交给JavaCompiler,让它将编译好的Class装载进来
* @return
* @throws IOException
*/
@Override
public OutputStream openOutputStream() throws IOException {
return bos;
}
/**
* 重写finalize方法,在对象被回收时关闭输出流
* @throws Throwable
*/
@Override
protected void finalize() throws Throwable {
super.finalize();
bos.close();
}
}
类文件管理器 ClassFileManager
import java.io.IOException;
import javax.tools.*;
/**
* 类文件管理器
* 用于JavaCompiler将编译好后的class,保存到jclassObject中
*/
public class ClassFileManager extends ForwardingJavaFileManager {
/**
* 保存编译后Class文件的对象
*/
private JavaClassObject jclassObject;
/**
* 调用