自定义ClassLoader的方式很多,简单的就是直接实现java.lang.ClassLoader
类,重写findClass()
及loadClass()
方法。java.lang.ClassLoader
是一个抽象类,
loadClass() - 其定义了双亲委派模型的模板方法loadClass(String,boolean)
,我们如果要打破双亲委派模型的话就可以直接重写该方法。
findClass() - 是作为loadClass(String,boolean)方法中的钩子方法,在父加载器找不到指定类时,会回调本类findClass()方法。
自定义类加载器
public class MyClassLoader extends ClassLoader {
// 加载外部自定路径
private String dir;
public MyClassLoader(ClassLoader parent, String dir) {
super(parent);
this.dir = dir;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String path = name.replaceAll("\\.", "/") + ".class";
try {
path = dir + "/" + path;
path = path.replaceAll("/+", "/");
FileInputStream fis = new FileInputStream(path);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int b;
while ((b = fis.read()) != -1) {
bos.write(b);
}
byte[] bytes = bos.toByteArray();
// 定义内存数据结构等,该方法是final方法
return defineClass(name, bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException(e.getMessage());
}
}
}
demo:
public class ClassLoaderDemo {
public static void main(String[] args) throws Exception {
MyClassLoader classLoader = new MyClassLoader(ClassLoaderDemo.class.getClassLoader(), "d:/tmp/");
Class<?> clazz = classLoader.loadClass("com.ext.Demo");
clazz.newInstance();
}
}
在D盘的tmp目录下存放对应的类
执行时会加载到外部的Demo.class