15_自定义类加载器深入详解
自定义类加载器
代码:
public class MyTest16 extends ClassLoader{
private String classLoaderName;
private final String fileExtension = ".class";
public MyTest16(String classLoaderName){
/**
* 使用由方法getSystemClassLoader()所返回的类加载器作为他的parentClassLoader(双亲)
*/
super();
this.classLoaderName = classLoaderName;
}
/**
* 会使用指定的parent做为这个类加载器的双亲
* @param parent
* @param classLoaderName
*/
public MyTest16(ClassLoader parent,String classLoaderName){
super(parent);
this.classLoaderName = classLoaderName;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] data = this.loadClassData(name);
return this.defineClass(name,data,0,data.length);
}
/**
* 这个name就是用户传进来需要被加载的类的名字(二进制名 全限定名)
* @param name
* @return
*/
private byte[] loadClassData(String name){
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream baos = null;
try{
is = new FileInputStream(new File(name+this.fileExtension));
baos = new ByteArrayOutputStream();
int ch = 0;
while (-1 != (ch=is.read())){
baos.write(ch);
}
data = baos.toByteArray();
} catch (Exception e){
e.printStackTrace();
} finally {
try {
is.close();
baos.close();
}catch (Exception e){
e.printStackTrace();
}
}
return data;
}
public static void test(ClassLoader classLoader) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class<?> clazz = classLoader.loadClass("top.tomxwd.classloader.MyTest1");
System.out.println("clazz.newInstance() = " + clazz.newInstance());
}
public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
MyTest16 loader1 = new MyTest16("loader1");
test(loader1);
}
}
输出:
clazz.newInstance() = top.tomxwd.classloader.MyTest1@4554617c
可以看到代码中并没有显式去使用我们重写的方法,但是classLoader的loadClass中会调用findClass方法。【这个只是理想状态,然而并不是,这样写其实还是由应用类加载器加载的。因为双亲委托机制,应用类加载器是可以对类路径下的类进行加载的。】
评论区